알고리즘 문제 풀이

[Swift] BOJ 12738 가장 긴 증가하는 부분 수열 3

lgvv 2022. 5. 12. 16:37

BOJ 12738 가장 긴 증가하는 부분 수열 3 

 

✅ 풀었다.

 

일단 이 문제는 dp를 사용해서 풀려고 했었는데, 시간 초과로 다른 접근 방법이 필요했다.

2022.04.01 - [코딩테스트] - [Swift] BOJ 11053 가장 긴 증가하는 부분 수열

 

[Swift] BOJ 11053 가장 긴 증가하는 부분 수열

BOJ 11053 가장 긴 증가하는 부분 수열 ✅ dp라는데 진짜 어려웠다. 우선 알고리즘 풀이법이 이해가 가지 않았다. 주어진 값이 10 20 10 30 20 50 있다고 가정하자. list 10 20 10 30 20 50 dp 1 2 1 3 2 4..

rldd.tistory.com

위의 문제는 dp로 해결이 가능했었는데

 

아무튼 아이디어가 도통 떠오르지 않아서 다른 분들의 로직을 참고하였음.

 

✅ 알고리즘 접근법

이분 탐색을 이용하였는데, C++에는 lower_bound를 제공해주어서 그런지, 이 부분을 따로 구현하지 않더라.

진짜 Swift로 알고리즘 공부하는데 가장 힘든 것은 직접 전부 구현해야 하는 것들이 정말 많다는 것이다.

 

 

1. list의 마지막 값과 현재 값을 비교.

2.  

  2-1. 현재 값이 list의 마지막 값보다 크다면 list의 끝에 현재 값을 대입 

  2-2. 현재 값이 list의 마지막 값보다 작다면 list를 거꾸로 순회       

    2-2-1. lowerBound를 통해서 나보다 작은 값의 index를 찾음. 

  2-3. lowerBound를 통해 찾은 list[index]를 현재 값으로 변경

 

여기서 잘 이해해야 하는 포인트는 어차피 list의 길이가 최대 길이라는 점이지 그 안의 원소를 하나하나 따질 필요가 없다.

 

 

 

✅ 코드

        let _ = Double(readLine()!)!
        let input = readLine()!.components(separatedBy: " ").map{ Double($0)! }
        
        // 최장 수열을 담을 배열이 필요하다.
        var list = [input[0]]
        
        /* (로직)
            값이 있는 부분의 뒤에서부터 탐색한다.
            탐색하려는 인덱스의 값보다 새로운 값이 더 큰 경우에는 탐색하려는 인덱스 뒤에 값을 넣어줍니다.
            탐색 인덱스가 맨 처음 인덱스까지 가도 자신보다 작은 인덱스를 못찾는 경우 맨 처음에 넣어준다.
            항생 배열에 들아간 숫자의 갯수가 최장 수열의 길이이다.
         */
        input.forEach { element in
            if element == list.last { }
            else if element > list.last! {
                list.append(element)
            } else { // 이 경우에는 list순회
                let position = lowerBound(arr: list, n: list.count, key: element)
                list[position] = element
            }
        }
        print(list.count)
        
        
        func lowerBound(arr: [Double], n: Int, key: Double) -> Int {
            var start: Int = 0
            var end: Int = n
            
            var mid: Int = n
            
            while end - start > 0 {
                mid = (start + end) / 2
                
                if arr[mid] < key {
                    start = mid + 1
                } else {
                    end = mid
                }
            }
            return end
        }

 

 

(참고)

http://melonicedlatte.com/algorithm/2018/07/15/171956.html

 

[백준] 12738번 C/C++ 풀이 _ 가장 긴 증가하는 수열 3 - Easy is Perfect

시간 제한메모리 제한제출정답맞은 사람정답 비율3 초512 MB116160949758.956% 문제수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.예를 들어, 수열 A = {10, 20, 10,

melonicedlatte.com

https://kunkunwoo.tistory.com/157

 

백준 12738번, 14003번 _ 가장 긴 증가하는 부분 수열 3, 5

https://www.acmicpc.net/problem/12738 12738번: 가장 긴 증가하는 부분 수열 3 첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (-1,000,000,00..

kunkunwoo.tistory.com

https://blockdmask.tistory.com/168

 

[탐색] lower_bound, upper_bound

안녕하세요. BlockDMask 입니다. 오늘은  이진탐색과 유사하나 조금 다른 lower_bound 와 upper_bound에 대해 알아보겠습니다. 1. lower_bound lower_bound 란? - 이진탐색(Binary Search)기반의 탐색 방법입..

blockdmask.tistory.com

https://chanhuiseok.github.io/posts/algo-55/

 

알고리즘 - c++ lower_bound, upper_bound 활용하기

컴퓨터/IT/알고리즘 정리 블로그

chanhuiseok.github.io

 

'알고리즘 문제 풀이' 카테고리의 다른 글

[Swift] BOJ 1920 수 찾기  (0) 2022.05.12
[Swift] BOJ 7453 합이 0인 네 정수  (0) 2022.05.12
[Swift] BOJ 1300 K번째 수  (0) 2022.05.12
[Swift] BOJ 1238 파티  (0) 2022.05.11
[Swift] BOJ 1916 최소비용 구하기  (0) 2022.05.11