본문 바로가기
알고리즘/문제집

[알고리즘-5] 기초 정렬 알고리즘 문제 풀이

by 정긔린 2022. 3. 23.
반응형

안녕하세요 기린입니다 :)

이번 시간에는 앞서 배웠던 정렬 알고리즘을 활용해 실제로 문제를 풀어보는 시간을 가져보겠습니다.

먼저 알고리즘 문제 풀이 사이트는 종류가 다양한데 저는 최백준님 사이트를 추천드립니다 !

 

백준 온라인 저지: https://www.acmicpc.net/

 

백준 온라인 저지에 들어가셔서 일단 회원가입 후 로그인 해보실게요 !

알고리즘을 이제 막 시작하신 분이라면 문제 카테고리에서 > 알고리즘 분류 > 단계별로 풀어보기 를 먼저 스터디 해보시는걸 추천드려요 ! 

희는 단계별 풀어보기를 해보도록 하겠습니다 : ]

첫 번째 문제는 '수 정렬하기' 입니다. https://www.acmicpc.net/submit/2750

 

N개의 수가 주어졌을 때, 이를 오름차순으로 정렬하는 프로그램을 작성하시오.
입력: 첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 절댓값이 1,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.

문제에 다른 조건 없이 단순하게 정렬을 하면 되는데요 문제풀이의 시간 제한 조건이 1초인걸 보실 수 있습니다.온라인 체점 시스템의 경우 1초에 1억번 정도 연산을 할 수 있다고 생각하고 문제를 푸시면 될 것 같은데요위 문제의 경우 1,000 * 1,000  = 1,000,000 번 정도 연산을 하기때문에 앞서 배운 정렬 알고리즘으로 코드를 작성해도큰 문제가 없다고 생각하시면 될 것 같습니다. 그럼 아래 코드를 보시겠습니다 !

#include <stdio.h>

int array[1001];

int main(void) {
	int number, i, j, min, index, temp;
	// N개의 수 입력 
	scanf("%d", &number);

	// N개 만큼 입력받음 
	for(i = 0; i < number; i++) {
		scanf("%d", &array[i]);
	}

	// 정렬 
	for(i = 0; i < number; i++) {
		min = 1001;
		for (j = i; j < number; j++) {
			if (min > array[j]) {
				min = array[j];
				index = j;
			}
		}
		temp = array[i];
		array[i] = array[index];
		array[index] = temp;
	}
	
	// 출력
	for (i = 0; i < number; i++) {
		printf("%d\n", array[i]);
	} 
	return 0;
}

앞서 배운 알고리즘을 그대로 적용했죠 ? 이 소스 코드의 시간 복잡도는 O(N^2) 입니다. 실제로 실행시켜서 문제에 나와있는 입력값을 복사하여 입력해보고 출력이 제대로 나오는지 확인해보세요. 그리고 제출을 해보고 체점 결과를 확인해봅시다 !

체점 결과

앞으로 계속 이런식으로 문제를 풀어보도록 하겠습니다 :)

 

두 번째 문제는 '세수 정렬' 입니다. https://www.acmicpc.net/problem/2752

동규는 세수를 하다가 정렬이 하고싶어졌다.
숫자 세 개를 생각한 뒤에, 이를 오름차순으로 정렬하고 싶어 졌다.
숫자 세 개가 주어졌을 때, 가장 작은 수, 그 다음 수, 가장 큰 수를 출력하는 프로그램을 작성하시오.
입력: 숫자 세 개가 주어진다. 이 숫자는 1보다 크거나 같고, 1,000,000보다 작거나 같다. 이 숫자는 모두 다르다.

세수를 하다가... 정렬이 하고싶어 지다니,,

세 개의 숫자만 정렬을 하면 되겠죠? 바로 소스코드를 봅시다.

#include <stdio.h>

int array[3];

int main(void) {
	int i, j, min, index, temp;
	
	// N개 만큼 입력받음 
	for(i = 0; i < 3; i++) {
		scanf("%d", &array[i]);
	}

	// 정렬 
	for(i = 0; i < 3; i++) {
		min = 1000001;
		for (j = i; j < 3; j++) {
			if (min > array[j]) {
				min = array[j];
				index = j;
			}
		}
		temp = array[i];
		array[i] = array[index];
		array[index] = temp;
	}
	
	// 출력
	for (i = 0; i < 3; i++) {
		printf("%d ", array[i]);
	} 
	return 0;
}

 

첫 번째 문제와 같이 3개의 수를 한번씩 비교해가면서 정렬하고있죠 :)

세 번째 문제는 '1,000,000 개 수 정렬' 입니다 https://www.acmicpc.net/problem/2751

N개의 수가 주어졌을 때, 이를 오름차순으로 정렬하는 프로그램을 작성하시오.
입력: 첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 절댓값이 1,000,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.
출력: 첫째 줄부터 N개의 줄에 오름차순으로 정렬한 결과를 한줄에 하나씩 출력한다.

위 문제는 데이터의 갯수가 100만개 이므로 시간 복잡도 O(N * logN)인 퀵 정렬을 사용해 볼게요 !

#include <stdio.h>

int number, data[1000000];

void quickSort(int* data, int start, int end) {
	// 원소가 1개인 경우에는 함수 종료 
	if (start >= end) {
		return;
	}
	
	// key는 첫 번째 원소 
	int key = start; 
	int i = start + 1, j = end, temp;
	
	// 엇갈릴 때까지 반복 
	while (i <= j) {
		// 키 값보다 큰 값을 만날 때까지 
		while (data[i] <= data[key]) {
			i++; 
		}
		// 키 값보다 작은 값을 만날 때까지 
		while (data[j] >= data[key] && j > start) {
			j--; 
		}
		// 현재 엇갈린 상태면 키 값과 교체 
		if (i > j) {
			temp = data[j];
			data[j] = data[key];
			data[key] = temp;
		} 
		// 엇갈리지 않았다면 i와 j를 교체 
		else {
			temp = data[j];
			data[j] = data[i];
			data[i] = temp;
		}
	}
		
	quickSort(data, start, j - 1);
	quickSort(data, j + 1, end);
}

int main(void) {

	// N 입력받기 
	scanf("%d", &number);

	// N개 만큼 입력받기 
	for (int i = 0; i < number; i++) {
		scanf("%d", &data[i]);
	}
	
	// 정렬 
	quickSort(data, 0, number - 1);
	
	// 출력
	for (int i = 0; i < number; i++) {
		printf("%d\n", data[i]);
	} 
	return 0;
}

 

퀵 정렬을 이용해서 100만개의 데이터를 정렬해봤습니다 :) 그치만 위 소스코드를 넣어 제출하시면 시간 초과로 나오실겁니다 !!
사실 기본적으로 O(N * logN)을 요구하는 문제는 기본적인 퀵 정렬 소스코드를 넣었을 때 틀리다고 처리가 됩니다. 왜냐하면 앞서 말했듯 최악의 경우 O(N ^ 2)가 나올 수 있기 때문이죠 :]  

그래서 일반적으로 C++ 알고리즘 STL(Standard Template Library) 라이브러리를 사용하는데요 STL 라이브러리에서 제공하는 sort() 함수는 퀵 정렬을 기반으로 처리하되 별도의 처리를 거쳐 최악의 경우에도 시간 복잡도 O(N * logN)를 보장한답니다. 나중에 배울 병합 정렬이나 힙 정렬을 사용한다면 더 좋구요 아래는 stl 라이브러리를 사용한 소스 코드이니 참고하시기 바랍니다 

이 소스코드로 제출하면 정답처리가 됩니다

#include <stdio.h>
#include <algorithm>

int number, data[1000000];

int main(void) {

	// N 입력받기 
	scanf("%d", &number);

	// N개 만큼 입력받기 
	for (int i = 0; i < number; i++) {
		scanf("%d", &data[i]);
	}
	
	// 정렬 
	std::sort(data, data + number);
	
	// 출력
	for (int i = 0; i < number; i++) {
		printf("%d\n", data[i]);
	} 
	return 0;
}

 

다음시간에는 병합정렬에 대해 알아보겠습니다 :]

자 그럼 즐거운 코딩하세요 !

 

문의: ralla0405@gmail.com

반응형