[백준 1377] 버블 소트(G2)

2026. 1. 13. 10:28·Algorithm

문제 바로가기

 

간단한 정렬문제인데, 왜 G2 문제지? 라고 생각하며 접근했다가 틀린 문제이다.

 

 

문제 요구사항을 요약하자면, 

버블정렬 알고리즘은 2중 for문으로 돌아간다. 

아래 예시로 예를들어보면

N=5,

배열 A는 10, 1, 5, 2, 3 이렇게 배열이 있을 때를 

i가 1일 때, 

j가 1부터 N-i 번 반복하게 된다.

 

i = 1 일 때,

[j=1]  1, 10, 5, 2, 3

[j=2] 1, 5, 10, 2, 3 

[j=3] 1, 5, 2, 10, 3

[j=4] 1, 5, 2, 3, 10

 

i = 2 일 때,

[j=1] 1, 5, 2, 3, 10

[j=2] 1, 2, 5, 3, 10

[j=3] 1, 2, 3, 5, 10

 

i = 3 일 때,

[j=1] 1, 2, 3, 5, 10

[j=2] 1, 2, 3, 5, 10

 

i=2, j=3 일때, 이미 정렬이 완료된 상태이다.

 

따라서 i=3일 때, 반복문이 도는 동안 한번도 swap이 진행되지 않아서

i=3 을 출력한다.

 

여기까지 문제를 이해했고 이제 이걸  어떻게 구현할까 고민해야한다.

 

단순하게 C++ 코드로 알고리즘을 떡하니 줬는데, 설마 저거 그대로 푸는게 답이겠어?

라고 생각하지 않고, 나는 그대로 풀었다. 결과는 "시간 초과"가 나왔다..

 

그 뒤로 어떻게 풀면 좋을지 고민을 해봤는데 도저히 답안이 생각 나지 않아서, 다른 자료들을 찾아봤다.

 

다른 블로그들을 여러개 찾아보면서 풀이 방법이 똑같아 보이지만 내가 이해가 잘 되지 않아서 제대로 정리해보려고 한다.

 

문제 풀이의 방법은 다른 자료들을 찾아봐도 아래와 같이 답을 한다.

특정 데이터가 안쪽 루프에서 swap의 왼쪽으로 이동할 수 있는 최대 거리가 1이므로,

정렬전과 정렬 후를 비교해서 왼쪽으로 가장 많이 이동한 값이다.

 

10, 1, 5, 2, 3 인 초기 배열 상태에서 

1, 2, 3, 5, 10 최종 정렬 배열 데이터를 비교한다. 

오른쪽으로 이동(-),왼쪽으로 이동(+)로 표현하겠다.

이때 10은 4번 오른쪽으로 이동했으니 +4로 표현하겠다.

 

10: -4

1: +1

5: -1

2: +2

3: +2

 

이므로 답은 2+1인 3이라는것이다.

 

맨처음 이 답안을 보고 무슨 말인지 도무지 이해가 되지 않았다.

 

그런데 곰곰히 생각해보니 아래와 같은 이유였다.

외부 for문인 i마다 내부 for문인 j가 N-i 만큼 반복해서 비교하고 swap한다.

왼쪽의 값이 오른쪽의 값보다 큰 경우에 왼쪽값이 오른쪽으로 이동한다.

하나의 값을 기준으로 볼 때 오른쪽으로 가는 경우는 외부 for문 내에서는 여러번 갈 수 있다.

그러나 왼쪽으로는 한번밖에 가지 못한다.

 

이게 무슨 말이냐면

 

10, 1, 5, 2, 3에서 10을 기준으로 관찰해보자.

 

{외부 for문

i = 1 일 때,

 

    {내부 for문

        [j=1]  1, 10, 5, 2, 3

        1(+1), 10(-1)

 

        [j=2] 1, 5, 10, 2, 3 

        1(+1), 5(+1), 10(-2)

 

        [j=3] 1, 5, 2, 10, 3

        1(+1), 2(+1), 5(+1), 10(-3)

 

        [j=4] 1, 5, 2, 3, 10

        1(+1), 2(+1), 3(+1), 5(+1), 10(-4)

    }

}

 

이렇게 10은 오른쪽으로 4번 이동하고, 다른 작은 값들은 왼쪽으로 최대 한번 이동했다.

왼쪽으로 이동한 값이 즉 i의 반복 횟수를 넘을 수 없으며 똑같다는 것이다.

특히 swap을 했는지 안했는지 여부를 판별할 수 있다는 아이디어였다.

 

이걸 이해하는데 오래 걸렸다.. ㅠㅠ

 

그럼 이걸 어떻게 구현할까?

 

먼저 맨처음 풀이였던 버블 정렬을 이용해서 풀면 시간 초과가 났던 이유를 분석해보면

버블정렬은 N^2이기 때문이었다.

 

자바의 Arrays.sort()를 사용하면 nlogn이므로 시간문제는 없었다.

 

정렬전 수의 인덱스를 저장하고, 정렬 후의 인덱스와 비교한뒤

그 차를 구해서 풀면 된다.

 

 

 

class mData implements Comparable<mData> {
    int value;
    int index;

    public mData(int value, int index) {
        super();
        this.value = value;
        this.index = index;
    }

    @Override
    public int compareTo(mData o) { // value 기준 오름차순 정렬하기
        return this.value - o.value;
    }

 

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());

        mData[] A = new mData[N];

        for (int i = 0; i < N; i++) {
            A[i] = new mData(Integer.parseInt(br.readLine()), i);
        }

        Arrays.sort(A);

        int Max = 0;

        for (int i = 0; i < N; i++) {
            if (Max < A[i].index - i) {
                Max = A[i].index -i;
            }
        }

        System.out.println(Max+1);
    }
}

'Algorithm' 카테고리의 다른 글

[백준 11286] 절댓값 힙(S1) — 우선순위 큐 재정의  (0) 2026.01.12
[백준 11720] 숫자의 합(V4) - 문제를 분석하는 습관  (0) 2026.01.04
[백준 1074] Z(G5) — 재귀로 방문 순서 계산하기  (0) 2025.12.23
[백준 1629] 곱셈 (S1) — 메모리 초과에서 분할정복 모듈러 거듭제곱까지  (0) 2025.12.22
'Algorithm' 카테고리의 다른 글
  • [백준 11286] 절댓값 힙(S1) — 우선순위 큐 재정의
  • [백준 11720] 숫자의 합(V4) - 문제를 분석하는 습관
  • [백준 1074] Z(G5) — 재귀로 방문 순서 계산하기
  • [백준 1629] 곱셈 (S1) — 메모리 초과에서 분할정복 모듈러 거듭제곱까지
goodjunseon
goodjunseon
  • goodjunseon
    The Dev/Arch Archives
    goodjunseon
  • 전체
    오늘
    어제
    • 분류 전체보기 (13)
      • Retrospective (1)
      • Tech Note (7)
        • Architecture (2)
        • Trouble Shooting (1)
      • Tech Insight (0)
      • Algorithm (5)
      • About me (0)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    코딩테스트
    Algorithm
    도메인주도개발
    spring
    Tech Note
    기술블로그
    ONECO
    백준
    알고리즘
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
goodjunseon
[백준 1377] 버블 소트(G2)
상단으로

티스토리툴바