Open peppermintt0504 opened 1 year ago
문제 풀이 해당 문제는 최대 배열의 길이가 500,000이므로 버블소트를 진행한다면 O(N^2)로 시간 초과가 나온다. 시간 초과를 피하기 위해 버블 솔트와 같이 스왑을 하지만 시간 복잡도가 낮은 병합 정령(merge sort)로 문제를 풀었다.
병합 정렬을 이용하여 O(nlogn)으로 해결할 수 있다.
정렬된 LeftArray와 RightArray로 나누어서 LeftArray의 길이를 count에 넣고 정렬을 시작한다.
이제 LeftArray의 맨 앞단의 숫자와 RightArray의 맨 앞단 숫자를 비교한다.
이 과정에서 작은 숫자를 새로운 배열에 추가한다.
해당 숫자가 RightArray의 숫자라면 count를 SwapCount에 추가한다.
해당 숫자가 LeftArray의 숫자라면 count를 줄인다.
위 그림에서는 RightArray의 1을 삽입하고, count 3을 Swapcount에 추가한다.
위 병합 정렬을 사용하면 시간 초과 없이 스왑 횟수를 출력할 수 있다.
풀이 코드
import java.io.*; import java.util.*; import java.util.Map.Entry; public class Main { public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); public static StringTokenizer st; public static int INF = Integer.MAX_VALUE; static long swapCount = 0; static long[] sorted; public static void main(String[] args) throws IOException { int N = Integer.parseInt(br.readLine()); sorted = new long[N]; long[] arr = new long[N]; arr = Arrays.stream(br.readLine().split(" ")).mapToLong(Long::parseLong).toArray(); mergeSort(arr, 0,N-1); System.out.println(swapCount); } static void mergeSort(long[] arr, int left, int right) { if(left < right) { int mid = (left + right) / 2; mergeSort(arr,left,mid); mergeSort(arr,mid+1,right); merge(arr, left,right); } } static void merge(long[] arr, int start, int end) { int mid = (start+end) / 2; int left = start; int right = mid+1; int index = start; while(left <= mid && right <= end) { if(arr[left] <= arr[right]) { sorted[index++] = arr[left++]; }else { sorted[index++] = arr[right++]; swapCount += mid + 1 - left; } } while(left <= mid) { sorted[index++] = arr[left++]; } while(right <= end) { sorted[index++] = arr[right++]; } for(int i = start; i <= end; i++) { arr[i] = sorted[i]; } } }
문제 풀이 해당 문제는 최대 배열의 길이가 500,000이므로 버블소트를 진행한다면 O(N^2)로 시간 초과가 나온다. 시간 초과를 피하기 위해 버블 솔트와 같이 스왑을 하지만 시간 복잡도가 낮은 병합 정령(merge sort)로 문제를 풀었다.
병합 정렬을 이용하여 O(nlogn)으로 해결할 수 있다.
정렬된 LeftArray와 RightArray로 나누어서 LeftArray의 길이를 count에 넣고 정렬을 시작한다.
이제 LeftArray의 맨 앞단의 숫자와 RightArray의 맨 앞단 숫자를 비교한다.
이 과정에서 작은 숫자를 새로운 배열에 추가한다.
해당 숫자가 RightArray의 숫자라면 count를 SwapCount에 추가한다.
해당 숫자가 LeftArray의 숫자라면 count를 줄인다.
위 그림에서는 RightArray의 1을 삽입하고, count 3을 Swapcount에 추가한다.
위 병합 정렬을 사용하면 시간 초과 없이 스왑 횟수를 출력할 수 있다.
풀이 코드