Permutation(순열)

1. next_permutation

c++에는 algorithm헤더에 매개변수의 배열/iterator의 다음 순열을 적용시켜 바뀌었다면 true/false를 반환해주는 메서드가 존재해서 이를 do~while문으로 쉽게 순열문제를 해결할 수 있다.

하지만, 자바는 존재하지 않기 때문에 다음과 같이 구현할 수 있다.

public boolean next_permutation(int[] arr){
    //뒤에서부터 탐색해서 내림차순이 깨지는 지점(a) 찾기
    int a = arr.length-2;
    while(a>=0 && arr[a] >= arr[a+1]) a--;
    if(a < 0) return false; //a가 -1이라면 배열전체가 내림차순정렬된 상태로 순열탐색이 끝난다.

    //뒤에서부터 탐색하면서 a보다 큰 첫번째 인덱스(b) 찾기
    int b = arr.length-1;
    while(arr[a] >= arr[b])b--;
    //찾은 a와 b swap
    swap(arr,a,b);

    //a+1부터 끝까지 오름차순으로 재정렬
    a += 1;
    b = arr.length-1;
    while(a< b){
        swap(arr,a++,b--);
    }
    return true;
}

private void swap(int[] arr, int src, int target){
    int tmp = arr[src];
    arr[src] = arr[target];
    arr[target] = tmp;
}
@Test
void test(){
    int[] arr = new int[]{1,2,3,4};

    do{
        System.out.println(Arrays.toString(arr));
    }while(next_permutation(arr));
}

2. swap

구현하기가 가장 쉬워 보통 알고리즘문제에 순열이 등장할때 많이쓰는 방식중 하나로 재귀함수를 이용한 백트래킹을 이용한 방법이다.

public void permutation(int[] arr, int depth, int n,int r){
    if(depth == r){
        System.out.println(Arrays.toString(arr));
        return;
    }

    for(int i=depth; i < n; i++){
        swap(arr,depth,i);
        permutation(arr, depth+1,n,r);
        swap(arr,depth,i);
    }
}
  private void swap(int[] arr, int src, int target){
    int tmp = arr[src];
    arr[src] = arr[target];
    arr[target] = tmp;
}

@Test
void test(){
    int[] arr = new int[]{1,2,3,4};
    permutation(arr,0,4,4);
}

3. visited

swap과 구현코드는 비슷하기 때문에 구현하는 것은 쉽게 할 수 있다. 하지만 swap과 다르게 배열의 앞에서부터 값을 쌓아나가는 방식으로 List를 이용해 값을 쌓아 나갈 수도 있고 depth가 r과 같아질때가 아니더라도 조건처리하기가 훨씬 쉽다.

if(visited[i]) continue; 부분만 지워주면 중복순열(자기자신을 포함)을 구할수 있다.

public void permutation(int arr[],int tmp[],boolean[] visited,int depth, int n, int r){
    if(depth == r){
     System.out.println(cnt++ + " " + Arrays.toString(tmp));
        return;
    }
    for(int i=0; i < n; i++){
        if(visited[i])continue;
        visited[i] = true;
        tmp[depth] = arr[i];
        visitedPermutation(arr,tmp,visited,depth+1,n,r);
        visited[i] =false;
    }
}

public void listPermutation(int arr[], List<Integer> tmp, boolean[] visited, int depth, int n, int r){
    if(depth == r){
        System.out.println(tmp.toString());
        return;
    }
    for(int i=0; i < n; i++){
        if(visited[i])continue;
        visited[i] = true;
        tmp.add(arr[i]);
        listPermutation(arr,tmp,visited,depth+1,n,r);
        visited[i] =false;
        tmp.remove(tmp.size()-1);
    }
}
public void rePermutation(int arr[],int tmp[],boolean[] visited,int depth, int n, int r){
    if(depth == r){
     System.out.println(Arrays.toString(tmp));
        return;
    }
    for(int i=0; i < n; i++){
        visited[i] = true;
        tmp[depth] = arr[i];
        visitedPermutation(arr,tmp,visited,depth+1,n,r);
        visited[i] =false;
    }
}

@Test
void test(){
    int[] arr = new int[]{1,2,3};
    int[]tmp = new int[3];
    List<Integer> list = new ArrayList<>();
    boolean[] visited = new boolean[3];
    System.out.println("---Array---");
    permutation(arr,tmp,visited,0,3,3);
    System.out.println("----List---");
    listPermutation(arr,list,visited,0,3,3);
    System.out.println("--중복순열--");
    rePermutation(arr,tmp,visited,0,3,3);
}

Related Posts

Go in Action

Go in Action

  • Books
  • 2022년 3월 29일

저는 개인적으로 GoLang을 접한지는 꽤 되었습니다. 제가 Go를 학습할때는 인터넷을 통해 충분히 학습할 수 있었는 데, 키워드들이 많지 않았고 http://golang.site 에 대부분 필요한 내용은 설명되어있어 무리없이 학습할 수 있었습니다. 그런데 책을 구매하게 된 이유는 요즘 읽을 책이 마땅치 않았기도 하고, Go 책을 개인적으로 소장하고 싶어 구매해본 책입니다. 책이 나온...

Read More
[MST] Prim 알고리즘

[MST] Prim 알고리즘

우선순위 큐의 방법을 이용하는 알고리즘으로 vertex를 한개씩 선택하며 최소 비용의 edge를 찾는 방법이다. decrease-key의 개념을 이용하며 decrease-key는 현재 계산된 v노드까지의 거리보다 현재 노드 u부터 v까지의 경로가 더 작다면 값을 갱신해주는 방법을 이용한다. 1. 특징 정점 선택 기반 시작 정점부터 출발하여...

Read More
Spring Security 적용해보기

Spring Security 적용해보기

지난번에 spring boot를 이용해서 graphQL서버를 구성해보았는데, 서비스를 운영할때 가장 중요한 보안을 설정하기 위해 springSecurity를 적용한 사례를 작성해보려고 한다. 우선, 인증 방식을 선택해야 하는데, 버스정보 어플같은 경우 사용자를 구분할 별도의 인증이 필요없기 때문에 간단하게 api-key를 통한 인증을 구현해...

Read More