이 영역을 누르면 첫 페이지로 이동
Stranger's LAB 블로그의 첫 페이지로 이동

Stranger's LAB

페이지 맨 위로 올라가기

Stranger's LAB

프로그래밍과 관련하여 다양한 알고리즘 문제를 풀어보고, 프로그래밍 언어를 이해해 볼 수 있도록 돕고자 만든 블로그 입니다.

[백준] 2750번 : 수 정렬하기 - JAVA [자바]

  • 2020.05.29 16:20
  • JAVA - 백준 [BAEK JOON]/정렬
글 작성자: ST_
728x90






www.acmicpc.net/problem/2750

 

2750번: 수 정렬하기

첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 숫자가 주어진다. 이 수는 절댓값이 1,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.

www.acmicpc.net

 








  • 문제



 

 

 

정렬의 가장 기초적인 문제다!





 






  • 9가지 방법을 이용하여 풀이한다.




먼저 정렬 방법은 여러가지가 있지만 가장 쉽게 쓸 수 있는 방법은 크게 3가지가 있다.

 

먼저, 선택정렬이다.

 

첫 번째 인덱스부터 시작하여 뒤의 인덱스들의 값들과 비교하여 최솟값들을 차곡차곡 쌓아나가는 방법이다. 가장 구현하기 쉽다는 장점이 있으나 시간복잡도가 O(n2) 으로 그리 좋은 성능의 알고리즘은 아니다. 아마 정렬을 구현해보거나 접해본 분들이라면 한 번 쯤은 보았을 코드다.

 

[선택정렬]

int[] arr; // 이미 초기화 되어 있는 배열이라고 가정

for(int i = 0; i < arr.length - 1; i++) {
	for(int j = i + 1; j < arr.length; j++) {
    
		if(arr[i] > arr[j]) {
			// 값 교환
			int temp = arr[j];
			arr[j] = arr[i];
			arr[i] = temp;
		}
	}
}

 

 

 

두 번째 방법은 가장 간단한 방법으로, Arrays.sort() 메소드를 쓰는 방법이다. Arrays.sort() 는 자바에서 기본으로 제공되는 메소드로, 자체 정렬 알고리즘을 구현 할 필요 없이 sort() 안에 배열만 넣어주면 자동으로 해당 배열이 정렬되어 나온다. Arrays.sort() 의 경우 dual-pivot Quicksort 알고리즘을 쓰고 있기 때문에 시간복잡도는 평균 O(nlogn) 으로 좋은 성능을 내고 있다. 물론 최악의 경우에는 O(n2)  이기 때문에 저격 데이터를 넣을 경우 효율은 떨어질 수 있다. 이와 관련해서는 수 정렬하기 2 을 풀면 알 수 있다. 그럼에도 나쁘지 않은 알고리즘인 것은 맞다. (사실상 직접 비교 정렬 알고리즘은 O(nlogn) 이 마지노선 시간복잡도로 보고 있다.)

 

아래 Java API문서에서 Arrays.sort 에 대한 설명이다.

https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/Arrays.html#sort(int%5B%5D)

 

 

 

 

 

세 번째로는 Counting Sort 정렬 알고리즘을 사용하는 방법이다.

정확히 말하자면 Counting Sort를 '응용한' 방법이다. 좀 더 구체적으로 말하자면 값을 비교하면서 정렬하는 것이 아니라 각 입력받은 값을 index 으로 하여 해당 값의 출현 빈도수를 체크하고, 출력하는 방법을 사용하는 것이다. 이 경우에는 시간복잡도가 O(n)으로 매우 빠른 알고리즘에 속한다. 자세한 내용은 아래 내용을 참고하길 바란다.

 

st-lab.tistory.com/104

 

카운팅 정렬 (Counting Sort / 계수 정렬) _ Java[자바]

Counting Sort [계수 정렬 / 카운팅 정렬] Counting Sort... 계수 정렬, 카운팅 정렬 등으로 많이 불리지만, 가장 와닿는 단어는 카운팅 정렬이므로 이 포스팅에서는 카운팅 정렬로 통일하여 쓰겠다. 카운�

st-lab.tistory.com

 

 

 

이렇게 3가지의 정렬 방법을 써보면서 각 입력 방법을 달리하여 써 볼 것이다.

 

그리고 이 3가지 알고리즘에 입출력 방법을 달리하여 풀어 볼 것인데, 다음과 같이 방법을 제시할 것이다.

  1. 선택 정렬 + Scanner
  2. 선택 정렬 + BufferedReader
  3. 선택 정렬 + BufferedReader + StringBuilder
  4. Arrays.sort + Scanner
  5. Arrays.sort + BufferedReader
  6. Arrays.sort + BufferedReader + StringBuilder
  7. 카운팅 정렬 + Scanner
  8. 카운팅 정렬 + BufferedReader
  9. 카운팅 정렬 + BufferedReader + StringBuilder

 

이 번 포스팅에서 각각의 성능을 비교하고, 앞으로 있을 정렬 알고리즘에서 반복 설명하지 않고 이 글을 참고할 수 있도록 이 번 포스팅에서 최대한 많이 알아가도록 하셨으면 한다.




 




  • 풀이




- 방법 1 : [선택 정렬(Selection Sort) + Scanner]

 

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
    
		Scanner in = new Scanner(System.in);
		
		int N = in.nextInt();
		int[] arr = new int[N];
		
		for(int i = 0; i < N; i++) {
			arr[i] = in.nextInt();
		}

		// Selection sort
		for(int i = 0; i < N - 1; i++) {
			for(int j = i + 1; j < N; j++) {
				if(arr[i] > arr[j]) {
					int temp = arr[j];
					arr[j] = arr[i];
					arr[i] = temp;
				}
			}
		}
		
		for(int val : arr) {
			System.out.println(val);
		}

	}
}

 

 

가장 기본적인 방법이라 할 수 있다.

아마 대부분의 언어에 대해 학습 할 때 한 번쯤은 구현해볼 것이다.

 

 











- 방법 2 : [선택 정렬(Selection Sort) + BufferedReader]

 

 

 

입력 방법을 바꾼 방식이다. 알고리즘은 선택 정렬로 동일하다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
    
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int N = Integer.parseInt(br.readLine());
		int[] arr = new int[N];
		
		for(int i = 0; i < N; i++) {
			arr[i] = Integer.parseInt(br.readLine());
		}

		// Selection sort
		for(int i = 0; i < N - 1; i++) {
			for(int j = i + 1; j < N; j++) {
				if(arr[i] > arr[j]) {
					int temp = arr[j];
					arr[j] = arr[i];
					arr[i] = temp;
				}
			}
		}
		
		for(int val : arr) {
			System.out.println(val);
		}

	}
}

 

 

 

 

 











- 방법 3 : [선택 정렬(Selection Sort) + BufferedReader + StringBuilder]

 

 

 

출력 방법또한 반복적으로 출력을 해주는 것이 아닌, 하나의 문자열로 이어 한 번에 출력해주는 방식이다. 마찬가지로 성능면에서 단일 반복 출력에 비해 좋은 성능을 갖고 있다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
    
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringBuilder sb = new StringBuilder();
        
		int N = Integer.parseInt(br.readLine());
		int[] arr = new int[N];
		
		for(int i = 0; i < N; i++) {
			arr[i] = Integer.parseInt(br.readLine());
		}

		// Selection sort
		for(int i = 0; i < N - 1; i++) {
			for(int j = i + 1; j < N; j++) {
				if(arr[i] > arr[j]) {
					int temp = arr[j];
					arr[j] = arr[i];
					arr[i] = temp;
				}
			}
		}
		
		for(int val : arr) {
			sb.append(val).append('\n');
		}
		System.out.println(sb);
	}
}

 

 

 

 

 











- 방법 4 : [Arrays.sort + Scanner]

 

 

 

자바에서 기본적으로 제공해주는 정렬 메소드다. 사용자 구현이 따로 필요없고, Arrays 패키지만 import 해준 뒤 sort 메소드를 사용하면 된다.

 

import java.util.Scanner;
import java.util.Arrays;

public class Main {
	public static void main(String[] args) {
    
		Scanner in = new Scanner(System.in);
		
		int N = in.nextInt();
		int[] arr = new int[N];
		
		for(int i = 0; i < N; i++) {
			arr[i] = in.nextInt();
		}

		// 정렬 메소드
		Arrays.sort(arr);
		
		for(int val : arr) {
			System.out.println(val);
		}

	}
}

 

 

 

 

 

 










- 방법 5 : [Arrays.sort + BufferedReader]

 

 

 

방법 4에서 입력 방식을 BufferedReader 로 변경한 방식이다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;

public class Main {
	public static void main(String[] args) throws IOException {
    
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int N = Integer.parseInt(br.readLine());
		int[] arr = new int[N];
		
		for(int i = 0; i < N; i++) {
			arr[i] = Integer.parseInt(br.readLine());
		}

		// 정렬 메소드
		Arrays.sort(arr);
		
		for(int val : arr) {
			System.out.println(val);
		}

	}
}

 

 

 

 











- 방법 6 : [Arrays.sort + BufferedReader + StringBuilder]

 

 

 

마찬가지로 출력또한 더 효율적으로 바꾼 코드다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;

public class Main {
	public static void main(String[] args) throws IOException {
    
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringBuilder sb = new StringBuilder();
        
		int N = Integer.parseInt(br.readLine());
		int[] arr = new int[N];
		
		for(int i = 0; i < N; i++) {
			arr[i] = Integer.parseInt(br.readLine());
		}

		// 정렬 메소드
		Arrays.sort(arr);
		
		for(int val : arr) {
			sb.append(val).append('\n');
		}
		System.out.println(sb);

	}
}

 

 

 

 

 

 

 

 











- 방법 7 : [카운팅 정렬 + Scanner]

 

 

 

필자가 앞서 잠깐 언급했던 정렬 방법 중 하나다. 중복되는 수는 없다고 하니 boolean 배열을 사용하여 카운팅 정렬 응용을 해보고자 한다. 자세한 방법은 아래 코드에서 확인하면 된다.

 

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
    
		Scanner in = new Scanner(System.in);
		
		int N = in.nextInt();
        
		/*
		  range : -1000 ~ 1000
		  0 은 index[1000] 을 의미
		*/
		boolean[] arr = new boolean[2001];
		
		for(int i = 0; i < N; i++) {
			arr[in.nextInt() + 1000] = true;
		}

		// 정렬 과정이 따로 필요 없음
		
		for(int i = 0; i < 2001; i++) {
			if(arr[i]) {
				System.out.println(i - 1000);
			}
		}
	}
}

 

 

 

 

 











- 방법 8 : [카운팅 정렬 + BufferedReader]

 

 

 

카운팅 정렬 알고리즘에 BufferedReader 로 입력받는 방식이다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
    
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int N = Integer.parseInt(br.readLine());
        
		/*
		  range : -1000 ~ 1000
		  0 은 index[1000] 을 의미
		*/
		boolean[] arr = new boolean[2001];
		
		for(int i = 0; i < N; i++) {
			arr[Integer.parseInt(br.readLine()) + 1000] = true;
		}

		// 정렬 과정이 따로 필요 없음
		
		for(int i = 0; i < 2001; i++) {
			if(arr[i]) {
				System.out.println(i - 1000);
			}
		}
	}
}

 

 

 

 

 

 











- 방법 9 : [카운팅 정렬 + BufferedReader + StringBuilder]

 

 

출력 또한 StringBuilder 로 변경해본다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
    
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringBuilder sb = new StringBuilder();
        
		int N = Integer.parseInt(br.readLine());
        
		/*
		  range : -1000 ~ 1000
		  0 은 index[1000] 을 의미
		*/
		boolean[] arr = new boolean[2001];
		
		for(int i = 0; i < N; i++) {
			arr[Integer.parseInt(br.readLine()) + 1000] = true;
		}

		// 정렬 과정이 따로 필요 없음
		
		for(int i = 0; i < 2001; i++) {
			if(arr[i]) {
				sb.append(i - 1000).append('\n');
			}
		}
		System.out.println(sb);
	}
}

 

 

 

 

 

 

 

 

 

 

 

 

 




  • 성능



 

 


위에서 부터 순서대로

 

채점 번호 : 20082097  -  방법 9 : 카운팅 정렬 + BufferedReader + StringBuilder

채점 번호 : 20082092  -  방법 8 : 카운팅 정렬 + BufferedReader 

채점 번호 : 20082084  -  방법 7 : 카운팅 정렬 + Scanner

채점 번호 : 20082074  -  방법 6 : Arrays.sort + BufferedReader + StringBuilder

채점 번호 : 20082070  -  방법 5 : Arrays.sort + BufferedReader

채점 번호 : 20082060  -  방법 4 : Arrays.sort + Scanner

채점 번호 : 20082053  -  방법 3 : 선택 정렬 + BufferedReader + StringBuilder

채점 번호 : 20082045  -  방법 2 : 선택 정렬 + BufferedReader

채점 번호 : 20082036  -  방법 1 : 선택 정렬 + Scanner

 

 

보이는대로 대체적으로 입출력 과정에서 차이가 난다.

 

또한 카운팅 정렬 > Arrays.sort > 선택 정렬 순으로 성능이 좋다는 것 또한 볼 수 있다. 특히나 정렬 할 데이터가 크면 클 수록 시간은 더욱 차이가 나게 되므로 반드시 방법 7, 8, 9 는 익혀두시길 바란다.

 

 







  • 정리

 

 


정렬 문제의 가장 기초적인 접근방법들을 알아보았다. 정렬 카테고리의 첫 문제인만큼 다양한 접근 방법을 제시하려 했으니, 각 방법마다의 성능을 비교하면 좋을 것 같다. 앞으로의 정렬문제들을 푸는데 있어 가장 뼈대가 되는 기본 중의 기본이라 할 수 있을 정도로 도움이 될 것이다.







저작자표시 비영리 변경금지 (새창열림)

'JAVA - 백준 [BAEK JOON] > 정렬' 카테고리의 다른 글

[백준] 11650번 : 좌표 정렬하기 - JAVA [자바]  (49) 2020.06.10
[백준] 1427번 : 소트인사이드 - JAVA [자바]  (12) 2020.06.03
[백준] 2108번 : 통계학 - JAVA [자바]  (43) 2020.06.01
[백준] 10989번 : 수 정렬하기 3 - JAVA [자바]  (22) 2020.05.31
[백준] 2751번 : 수 정렬하기 2 - JAVA [자바]  (33) 2020.05.30

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • [백준] 1427번 : 소트인사이드 - JAVA [자바]

    [백준] 1427번 : 소트인사이드 - JAVA [자바]

    2020.06.03
  • [백준] 2108번 : 통계학 - JAVA [자바]

    [백준] 2108번 : 통계학 - JAVA [자바]

    2020.06.01
  • [백준] 10989번 : 수 정렬하기 3 - JAVA [자바]

    [백준] 10989번 : 수 정렬하기 3 - JAVA [자바]

    2020.05.31
  • [백준] 2751번 : 수 정렬하기 2 - JAVA [자바]

    [백준] 2751번 : 수 정렬하기 2 - JAVA [자바]

    2020.05.30
다른 글 더 둘러보기

정보

Stranger's LAB 블로그의 첫 페이지로 이동

Stranger's LAB

  • Stranger's LAB의 첫 페이지로 이동

검색

나의 외부 링크

  • st-github

공지사항

  • 공지 - 블로그 사용 설명서

메뉴

  • 홈
  • 방명록

카테고리

  • 전체 카테고리 (267)
    • Java (5)
    • JAVA - 백준 [BAEK JOON] (177)
      • 입출력과 사칙연산 (14)
      • 조건문 (7)
      • 반복문 (11)
      • 1차원 배열 (7)
      • 함수 (3)
      • 문자열 (10)
      • 기본 수학 1 (8)
      • 기본 수학 2 (6)
      • 2차원 배열 (0)
      • 정렬 (10)
      • 재귀 (4)
      • 브루트 포스 (5)
      • 집합과 맵 (0)
      • 기하 1 (5)
      • 정수론 및 조합론 (12)
      • 백트래킹 (8)
      • 동적 계획법 1 (15)
      • 누적 합 (0)
      • 그리디 알고리즘 (5)
      • 스택 (5)
      • 큐, 덱 (7)
      • 분할 정복 (9)
      • 이분 탐색 (7)
      • 기타 문제 (17)
      • 별 찍기 문제 모음 (2)
    • C++ - 백준 [BAEK JOON] (46)
      • 입출력과 사칙연산 (14)
      • 조건문 (7)
      • 반복문 (11)
      • 1차원 배열 (7)
      • 함수 (3)
      • 문자열 (0)
      • 기타 문제 (4)
    • 자료구조 (18)
      • Java (18)
    • 알고리즘 (11)
      • Java (11)
    • 프로그래밍 기초 (6)
    • 이모저모 (2)
    • 일상의 글 (2)

최근 글

정보

ST_의 Stranger's LAB

Stranger's LAB

ST_

블로그 구독하기

  • 구독하기
  • 네이버 이웃 맺기
  • RSS 피드

방문자

  • 전체 방문자
  • 오늘
  • 어제

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. Copyright © ST_.

티스토리툴바