[Codility] Array Inversion Count

https://app.codility.com/programmers/trainings/4/array_inversion_count/start/

 

Codility

Your browser is not supported Please, update your browser or switch to a different one. Learn more about what browsers are supported

app.codility.com


 

해결전략

 

정렬 Sorting

 

※ 중요!

  • QuickSort를 사용하면 안 된다!!

 

처음 시도한 코드 - 선택 정렬 (시간 초과)

 

 

#include <algorithm>
using namespace std;

int solution(vector<int> &A) {
    int answer = 0;
    int n = A.size();

    for(int i = 0; i < n-1; i++){
        int idx = i;
        for(int j = i+1; j < n; j++){
            if(A[idx] > A[j]) answer++;
        }
    }

    answer = (answer > 1000000000) ? -1 : answer;

    return answer;
}

 


 

정답코드 -  MergeSort 병합정렬

 

#include <algorithm>
using namespace std;

int answer;

int Merge(vector<int>& v, int left, int mid, int right) 
{
  int i = left;
  int j = mid;
  int k = 0;

  int invCount = 0;
  int temp[(right - left + 1)];
 
  while ((i < mid) && (j <= right)) 
  {
    if (v[i] <= v[j]) {
      temp[k] = v[i];
      ++k;
      ++i;
    } 
    else {
      temp[k] = v[j];
      invCount += (mid - i);
      ++k;
      ++j;
    }
  }
 
  while (i < mid) {
    temp[k] = v[i];
    ++k;
    ++i;
  }
 
  while (j <= right) {
    temp[k] = v[j];
    ++k;
    ++j;
  }
 
  for (i = left, k = 0; i <= right; i++, k++) {
    v[i] = temp[k];
  }
 
  return invCount;
}

int MergeSort(vector<int>& v, int left, int right) 
{
  int cnt = 0;
 
  if (left < right) 
  {
    int mid = (right + left) / 2;

    cnt = MergeSort(v, left, mid);
    cnt += MergeSort(v, mid + 1, right);
    cnt += Merge(v, left, mid + 1, right);
  }

  return cnt > 1000000000 ? -1 : cnt; // 문제조건: 100000000초과일 때 -1 리턴
}

int solution(vector<int> &A) {
    
    return MergeSort(A, 0, A.size()-1);
}

 

 

 

 

#include <algorithm> 
using namespace std; 

int answer; // 결과값을 저장할 전역 변수입니다.

// Merge 함수는 두 개의 정렬된 부분 배열을 병합하고, 역순 정렬 쌍의 수를 반환합니다.
int Merge(vector<int>& v, int left, int mid, int right) 
{
  int i = left; // 왼쪽 부분 배열의 시작 인덱스입니다.
  int j = mid; // 오른쪽 부분 배열의 시작 인덱스입니다.
  int k = 0; // 임시 배열의 인덱스입니다.

  int invCount = 0; // 역순 정렬 쌍의 수를 저장하는 변수입니다.
  int temp[(right - left + 1)]; // 병합된 결과를 저장할 임시 배열입니다.
 
  // 왼쪽 부분 배열과 오른쪽 부분 배열을 모두 훑을 때까지 반복합니다.
  while ((i < mid) && (j <= right)) 
  {
    // 왼쪽 요소가 오른쪽 요소보다 작거나 같으면 왼쪽 요소를 임시 배열에 추가합니다.
    if (v[i] <= v[j]) {
      temp[k] = v[i];
      ++k;
      ++i;
    } 
    // 왼쪽 요소가 오른쪽 요소보다 크면 오른쪽 요소를 임시 배열에 추가하고, 역순 정렬 쌍의 수를 갱신합니다.
    else {
      temp[k] = v[j];
      invCount += (mid - i);
      ++k;
      ++j;
    }
  }
 
  // 왼쪽 부분 배열의 남은 요소들을 임시 배열에 추가합니다.
  while (i < mid) {
    temp[k] = v[i];
    ++k;
    ++i;
  }
 
  // 오른쪽 부분 배열의 남은 요소들을 임시 배열에 추가합니다.
  while (j <= right) {
    temp[k] = v[j];
    ++k;
    ++j;
  }
 
  // 임시 배열의 요소들을 원본 배열에 복사합니다.
  for (i = left, k = 0; i <= right; i++, k++) {
    v[i] = temp[k];
  }
 
  return invCount; // 역순 정렬 쌍의 수를 반환합니다.
}

// MergeSort 함수는 벡터를 정렬하고, 역순 정렬 쌍의 수를 반환합니다.
int MergeSort(vector<int>& v, int left, int right) 
{
  int cnt = 0; // 역순 정렬 쌍의 수를 저장하는 변수
 
  // 벡터에 두 개 이상의 요소가 있으면 분할하고 병합합니다.
  if (left < right) 
  {
    int mid = (right + left) / 2; // 중간 인덱스를 계산합니다.

    cnt = MergeSort(v, left, mid); 			// 왼쪽 부분 배열을 정렬하고, 역순 정렬 쌍의 수를 더합니다.
    cnt += MergeSort(v, mid + 1, right); 	// 오른쪽 부분 배열을 정렬하고, 역순 정렬 쌍의 수를 더합니다.
    cnt += Merge(v, left, mid + 1, right);  // 두 부분 배열을 병합하고, 역순 정렬 쌍의 수를 더합니다.
  }

  return cnt > 1000000000 ? -1 : cnt; // 역순 정렬 쌍의 수가 1000000000을 초과하면 -1을 반환하고, 그렇지 않으면 역순 정렬 쌍의 수를 반환합니다.
}

// solution 함수는 주어진 벡터를 정렬하고, 역순 정렬 쌍의 수를 반환합니다.
int solution(vector<int> &A) {
    
    return MergeSort(A, 0, A.size()-1); // 벡터를 정렬하고, 역순 정렬 쌍의 수를 반환합니다.
}

 

'⭐ 코딩테스트 > Codility' 카테고리의 다른 글

[Codility] Disappearing Pairs  (0) 2024.02.19
[Codility] Binary Gap  (0) 2024.02.18
[Codility] Tree Height  (0) 2024.02.18
[Codility] Tree Longest Zigzag  (0) 2024.02.18
[Codility] The Matrix  (0) 2024.02.17