ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • next_permutation, prev_permutation
    Programming/leetcode 2022. 4. 20. 09:23
    728x90

    next_permutation, prev_permutation 

    c++의 레퍼런스에는 들어있지만, python에는 구현되어있지 않아 이 기회에 정리해둘겸 적어본다. 

    python에는 itertools을 이용하여 순열 전체를 구하는 방법은 있다

     

    기본 원리

    예를 들어, [1,2,3,4]라는 것을 순열을 만든다 가정해보자

    [1, 2, 3, 4]  : 오름차순 시작
    [1, 2, 4, 3]
    [1, 3, 2, 4]
    [1, 3, 4, 2]
    [1, 4, 3, 2]
    [2, 1, 3, 4]
    [2, 1, 4, 3]
    [2, 3, 1, 4]
    [2, 3, 4, 1]
    [2, 4, 3, 1]
    [3, 2, 4, 1]
    [3, 4, 2, 1]
    [4, 3, 2, 1] : 내림차순 마무리

    ===> 오름차순으로 시작하고, 내림차순으로 끝이 난다. 

    그리고 중간에 [2,1,3,4]를 보면 특정 지점을 기준으로 오름차순, 내림차순이 이어진다. 

     

    1) 배열의 뒤에서부터 오름차순이 깨지는 부분을 찾자.

    예를 들어,  [1,3,4,2]가 있다고 하자

    그 다음 순서를 찾기 위해서 맨 뒤에서부터 아래 조건으로 while문을 돌리자

    #arr의 최대 길이 
    i = len(arr) - 1
    
    #뒤에서부터 오름차순이 깨지는 곳을 찾자..
    while (i>=0 and arr[i-1] >= arr[i]): i -= 1

    2) [1,3,4,2]에서 오름차순이 깨지는 부분은 [3,4]이다. 

    3과 오름차순 부분[4,2]와 교체할 부분을 찾아야한다. 

    j = len(arr) - 1
    
    # arr[i-1]보다 작으면서 [4,2]에서 arr[i-1]에 가장 가까운 값을 찾자..
    while(arr[i-1] >= arr[j]): j-=1

    왜 가장 가까운 값을 찾느냐하면 바꿨을 때 오름차순이 유지가 되어야하기 때문이다.

    둘다 찾았으면 값을 바꿔주자

    arr[i-1], arr[j] = arr[j], arr[i-1]

    3) 이제 [1,2,4,3]이 완성되었다.

    하지만 아직 한가지 처리가 더 필요하다.  i 부터 j까지 배열을 뒤집어 줘야한다. 

     

    예를 들어 [2,3,4,1]에서 2)까지 진행을 했다면 [2,1,4,3] 이다. 

    여기서 [4,3]을 오름차순으로 만들어줘야지만 사전순 배치가 가능하다. 

     

    while(i<j):
        arr[i], arr[j] = arr[j], arr[i]
        i+=1
        j-=1

     

    전체 코드 (next_permutation)

    arr = [1, 2, 3, 4]
    
    
    def next_permutation():
        i = len(arr) - 1
        # 뒤에서부터 오름차순을 찾는다...오름차순이 끝나는 지점 기록
        while (i > 0 and arr[i-1] >= arr[i]):
            i -= 1
        # 0미만으로 내려가면 더이상 없다..
        if (i <= 0):
            return False
    
        j = len(arr) - 1
    
        # i위치랑 교환할 j를 찾자..
        while(arr[i-1] >= arr[j]):
            j -= 1
    
        arr[i-1], arr[j] = arr[j], arr[i-1]
    
        # 이걸 왜 해야될까???????????????
        # 사전순 배치때문에 필요한 부분이다.
        j = len(arr) -1
        while (i < j):
            arr[i], arr[j] = arr[j], arr[i]
            i += 1
            j -= 1
    
        return True
    
    
    while True:
        print(arr)
        if (next_permutation()):
            continue
        break

    전체 코드(prev_permutation)

    arr = [9, 8, 7, 6]
    
    
    def prev_permutation():
        i = len(arr) - 1
    
        while (i > 0 and arr[i-1] < arr[i]):
            i -= 1
        if (i <= 0):
            return False
        j = len(arr) - 1
    
        while (arr[i-1] <= arr[j]):
            j -= 1
        arr[i-1], arr[j] = arr[j], arr[i-1]
    
    	j = len(arr) - 1
        while (i < j):
            arr[i], arr[j] = arr[j], arr[i]
            i += 1
            j -= 1
        return True
    
    
    while True:
        print(arr)
        if (prev_permutation()):
            continue
        break

    'Programming > leetcode' 카테고리의 다른 글

    104. Maximum Depth of Binary Tree  (1) 2021.03.17
    743. Network Delay Time  (0) 2021.03.10
    78. Subsets  (0) 2021.03.03
    39. Combination Sum  (0) 2021.03.03
    17. Letter Combinations of a Phone Number  (0) 2021.02.24
Designed by Tistory.