[Coding Test] LIS

2024. 4. 2. 21:08

알고리즘 키워드
1. 
2. 
3. 

 


1. LIS 가 뭔데?

LIS == '가장 긴 증가하는 부분 수열'

 

    부분 수열 (Subsequence)

  • 수열에서 일부 요소를 제거하고 남은 요소들이 원래 순서대로 나열된 것을 말한다.

 

  • 일반적으로 정형화된 알고리즘이라기 보다는, 알면 좋은 자주나오는 개념이라고 생각하면 된다.

 

  • 1. 가장 기본적으로 해결하는 방법은 DP 를 사용하는 방법이 있고 -> O(N^2)
    • 1) 수열의 각 위치에 대해서, 그 위치를 마지막으로 하는 가장 긴 증가하는 부분 수열의 길이를 찾아냄
    • 2) 이후 이를 바탕으로 전체 문제의 해답을 구함.
  • 2. 보다 효율적인 이분탐색을 가지고 활용하는 방안이 있다. -> O(NlogN)
    • 1) 수열을 순차적으로 탐색하면서, 현재까지 발견된 가장 긴 증가하는 부분 수열을 유지한다.
    • 2) 새로운 요소가 나타나면, 이분탐색을 통해서 적절한 위치를 찾는다.
    • cf) 실제 LIS 요소들을 정확히 구성하지는 않지만, 가장 긴 증가하는 부분 수열의 길이를 효율적으로 사용할 수 있다.

 

2. LIS 를 푸는 코드

DP, BS 2가지로 푸는 방식을 나눌 수 있다.
  • 1) DP 로 푸는 코드
public class LIS_DP {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        int[] arr = new int[N];
        int[] dp = new int[N];

        for (int i = 0; i < N; i++) {
            arr[i] = scanner.nextInt();
        }

        int maxLength = 0;
        for (int i = 0; i < N; i++) {
            dp[i] = 1; // 초기값은 자기 자신만으로 구성된 부분 수열
            for (int j = 0; j < i; j++) {
                if (arr[j] < arr[i] && dp[j] + 1 > dp[i]) {
                    dp[i] = dp[j] + 1; // j번째 요소를 포함하는 경우의 수열 길이 갱신
                }
            }
            maxLength = Math.max(maxLength, dp[i]);
        }

        System.out.println(maxLength);
        scanner.close();
    }
}

 

 

  • BS (이진탐색) 으로 푸는 코드
public class LIS_BinarySearch {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        ArrayList<Integer> lis = new ArrayList<>();

        for (int i = 0; i < N; i++) {
            int num = scanner.nextInt();
            if (lis.isEmpty() || num > lis.get(lis.size() - 1)) {
                lis.add(num);
            } else {
                int left = 0, right = lis.size() - 1;
                while (left < right) {
                    int mid = (left + right) / 2;
                    if (lis.get(mid) >= num) {
                        right = mid;
                    } else {
                        left = mid + 1;
                    }
                }
                lis.set(right, num);
            }
        }

        System.out.println(lis.size());
        scanner.close();
    }
}

 

 

 

 

 

3. LIS 문제인것을 판단하는 근거

중요한 포인트 4가지.
  • 1. 순서가 중요한 수열
    • 문제에서 주어진 데이터가 순서를 유지해야 하는 수열 혹은 리스트.
    • 특히 요소들 간의 상대적인 순서가 결과에 영향을 미칠때.
  • 2. 증가하는 부분
    • 문제 설명에 " 증가하는 부분수열", "가장 긴 상승하는 경로", "연속적이지 않아도 되는 증가 순서" 가 있다면.
  • 3. 최대 길이 또는 최대 개수 찾기
    • 문제에서 어떤 조건을 만족하는 가장 긴 길이나 가장 많은 개수를 찾으라는 요구가 있을때
    • 이때 조건이 증가하는 순서와 관련되어 있다면, LIS 문제의 변형일 수 있다.
  • 4. DP 나 BS 카테고리
    • 문제가 DP 나 BS 카테고리에 있다면, LIS 를 의심해보자.

 

 

🔎 예제 모음집 

LIS 예제 모음집

 

 

 

 

※ 출처 및 참고 내용 : 

 

 

'STUDY > Coding Test' 카테고리의 다른 글

[Coding Test] 우선순위 큐  (0) 2024.04.11
[CodingTest] Greedy  (0) 2024.03.29
[Coding Test]누적합  (1) 2024.03.14

BELATED ARTICLES

more