[백준] 1517번 - 버블 소트 (C언어) [Platinum5]

2023. 6. 1. 18:55·알고리즘

input output
3
3 2 1
3

해당 문제는 버블 정렬에 대한 개념을 설명하고 SWAP이 일어나는 횟수를 구하는 문제여서 단순히 버블정렬을 사용한다면 시간초과가 발생한다. 시간 제한이 1초이므로 시간복잡도가 O(N^2)인 버블정렬로는 절대 구현할 수 없다. 보다 빠른 알고리즘인 합병정렬을 사용하거나 세그먼트 트리를 이용하면 O(NlogN)의 시간 복잡도를 가지므로 문제 해결이 가능하다. 

 

필자는 합병 정렬을 사용하였다. 

우선, 버블 정렬에서 SWAP이 일어나는 구간은 어떤 원소 i가 존재할 때, i보다 앞에 있으면서 작은 수들을 뒤로 보낼때 작은 수들의 갯수만큼 SWAP이 일어난다. 따라서 합병 정렬에서는 정복 단계에서 SWAP이 일어나고 정렬은 합병 단계에서 일어난다. 버블 정렬에서 SWAP의 경우와 유사한 경우를 합병정렬에서 찾아보면 오른쪽으로 분할된 리스트의 원소가 왼쪽으로 분할된 리스트의 원소보다 작은 경우 SWAP이 일어나고 각 리스트의 인덱스간의 차이를 저장하여 더 하면 SWAP 횟수를 구할 수 있다. 

 

전체 소스 코드는 아래와 같다.

#include <stdio.h>
#pragma warning(disable:4996)
typedef long long int ll;

ll sorted[500001];
ll arr[500001];
ll answer = 0;

void merge(int left, int mid, int right) {
	int i = left;
	int j = mid + 1;
	int k = left;

	while (i <= mid && j <= right) {
		if (arr[i] <= arr[j]) {
			sorted[k] = arr[i];
			i++;
		}
		else {
			sorted[k] = arr[j];
			answer += j - k; // swap 구간
			j++;
		}
		k++;
	}

	if (i > mid) {
		for (int a = j; a <= right;a++) {
			sorted[k++] = arr[a];
		}
	}
	else {
		for (int a = i; a <= mid; a++) {
			sorted[k++] = arr[a];
		}
	}

	for (int a = left; a <= right;a++) {
		arr[a] = sorted[a];
	}
}

void merge_sort(int left, int right) {
	if (left >= right) return;
	int mid = (left + right) / 2;
	merge_sort(left, mid);
	merge_sort(mid + 1, right);
	merge(left, mid, right);
}

int main() {
	int n;
	scanf("%d", &n);

	for (int i = 0; i < n;i++)
		scanf("%lld", &arr[i]);

	merge_sort(0, n - 1);
	printf("%lld", answer);

	return 0;
}

해당 문제는 합병 정렬에 대한 지식이 충분하다면 쉽게 해결 가능한 문제이다. 다음엔 세그먼트 트리로 도전할 것이다.

 

[1517번]

https://www.acmicpc.net/problem/1517

 

1517번: 버블 소트

첫째 줄에 N(1 ≤ N ≤ 500,000)이 주어진다. 다음 줄에는 N개의 정수로 A[1], A[2], …, A[N]이 주어진다. 각각의 A[i]는 0 ≤ |A[i]| ≤ 1,000,000,000의 범위에 들어있다.

www.acmicpc.net

 

[github]

https://github.com/MinWook6457

 

MinWook6457 - Overview

MinWook6457 has 18 repositories available. Follow their code on GitHub.

github.com

 

 

'알고리즘' 카테고리의 다른 글

[백준] 1300번 - K번째 수 (C언어) [Gold2]  (0) 2023.06.06
[백준] 11053번 - 가장 긴 증가하는 부분 수열 (C언어) [Silver2]  (0) 2023.06.02
[백준] 2042번 - 구간 합 구하기 (C언어) [Gold1]  (0) 2023.05.31
[백준] 1918번 - 후위 표기식 (C언어) [Gold2]  (0) 2023.05.30
[백준] 1937번 - 욕심쟁이 판다 (C언어) [Gold3]  (0) 2023.05.29
'알고리즘' 카테고리의 다른 글
  • [백준] 1300번 - K번째 수 (C언어) [Gold2]
  • [백준] 11053번 - 가장 긴 증가하는 부분 수열 (C언어) [Silver2]
  • [백준] 2042번 - 구간 합 구하기 (C언어) [Gold1]
  • [백준] 1918번 - 후위 표기식 (C언어) [Gold2]
min._.uuk_
min._.uuk_
하루 하나 기록하기
  • min._.uuk_
    기록하는 습관
    min._.uuk_
  • 전체
    오늘
    어제
    • 분류 전체보기 (33)
      • 알고리즘 (15)
      • 자바 스크립트 (2)
      • 인실리코젠 (15)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    백준 #MST #최소비용신장트리 #크루스칼 #그리디 #알고리즘
    백준 #BOJ #스택 #수열
    Apache #POI #JAVA #maven
    #BOJ #백준 #10989번 #C언어 #카운팅정렬 #정렬
    백준 #동적계획법 #dp #백트래킹 #dfs
    인실리코젠 #크롤링 #SpringBoot #MVC #jQuery
    백준 #세그먼트 트리 #구간합 #c언어 #골드1 #탐색
    JS #테트리스 #HTML #CSS #추억의 게임
    백준 #후위표기식 #스택 #중위표기식 #우선순위 #1918번
    백준 #1407번 #재귀함수
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
min._.uuk_
[백준] 1517번 - 버블 소트 (C언어) [Platinum5]
상단으로

티스토리툴바