[BOJ 1083][Gold 4] 소트
백준 1083
제한
시간제한 | 메모리 제한 | 제출 | 정답 | 맞은 사람 | 정답 비율 |
---|---|---|---|---|---|
2 초 | 128 MB | 2730 | 637 | 509 | 29.490% |
문제
크기가 N인 배열 A가 있다. 배열에 있는 모든 수는 서로 다르다. 이 배열을 소트할 때, 연속된 두 개의 원소만 교환할 수 있다. 그리고, 교환은 많아봐야 S번 할 수 있다. 이때, 소트한 결과가 사전순으로 가장 뒷서는 것을 출력한다.
입력
첫째 줄에 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄에는 각 원소가 차례대로 주어진다. 이 값은 1000000보다 작거나 같은 자연수이다. 마지막 줄에는 S가 주어진다. S는 1000000보다 작거나 같은 음이 아닌 정수이다.
출력
첫째 줄에 문제의 정답을 출력한다.
예제 입력1
7
10 20 30 40 50 60 70
1
예제 출력1
20 10 30 40 50 60 70
예제 입력2
5
3 5 1 2 4
2
예제 출력2
5 3 2 1 4
예제 입력3
10
19 20 17 18 15 16 13 14 11 12
5
예제 출력3
20 19 18 17 16 15 14 13 12 11
풀이
처음에 완전탐색을 생각했다. S의 최댓값인 10^6, N의 최대값인 50으로 가정한다.
예제 2를 가정해 보면
5
3 5 1 2 4
2
에서 각 원소를 노드라고 가정하고 간선간의 순열에 대한 경우의 수를 생각한다면
(n-1)P(s)
50P10^6 > 2*10^8(2초)
=> 시간초과
이므로 시간초과가 예상이 되어, 최적화된 방법을 생각해 보았다.
사전순으로 가장 뒷자리에 해당하는 경우는 가장 왼쪽에 있는 숫자의 크기를 가능하면 최대화 시키는 것이다.
7
10 20 30 40 50 60 70
1
예제 1을 참고하면, 가장 큰 값은 70이지만 횟수가 1개로 한정되어 가장 왼쪽에 있는 20과 교환할수 밖에없다.
그래서 현재 가지고 있는 횟수 S에 맞춰서 범위를 지정해 맨왼쪽부터 S를 다쓰거나 맨 오른쪽까지 갈때 까지 최댓값을 가져오는 방식으로 채택해 보았다.
이 아이디어는 bubble sort에 영감을 얻었고, 시간복잡도는 O(n2) 즉 2500 이라서 10^8 에는 한참 못미치기 때문에 시간문제도 해결할 수 있다.
while 문에서 한 루프를 돌때 마다 교체를 사용한 횟수를 차감하고, 인덱스를 1씩 증가시킨다.
그리고 종료조건을 S를 소진한 경우(S=0) 또는 인덱스가 오른쪽 끝(idx = N-1)까지 갔을 경우이다.
소스코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N;
static int[] nums;
static int S;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
nums = new int[N];
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i = 0 ; i < N ; i++){
nums[i] = Integer.parseInt(st.nextToken());
}
S = Integer.parseInt(br.readLine());
int current = 0;
while (S>0 && current<N-1){
int maxIdx = current;
for(int i = current ; i <= current+S ; i++){
if(i>=N) break;
if(nums[i]>nums[maxIdx]) maxIdx = i;
}
int distance = maxIdx-current;
for (int i = maxIdx; i > current ; i--) {
swap(i,i-1);
}
S-=distance;
current++;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < nums.length ; i++){
sb.append(nums[i]+" ");
}
System.out.println(sb);
}
static void swap(int idx1, int idx2){
int temp = nums[idx1];
nums[idx1] = nums[idx2];
nums[idx2] = temp;
}
}