👨🏻‍💻iOS 공부/Swift_알고리즘 풀이

[LeetCode] Dynamic Programming

728x90
반응형

DP Easy문제들을 풀어보았다. 

자세한 설명들은 주석에 달아두었다.

 

easy부터 시작해서 감을 익혀 나가야겠다. 

1. Best Time to Buy and Sell Stock

  • Point 
    • 사고 파는 이윤을 최대로
    • 구입가를 최저로
class Solution {
    func maxProfit(_ prices: [Int]) -> Int {
        // 현재 최대 수익은 0
        var maxProfits = 0
        // 현재 최소 구입가는 prices[0]
        var buy = prices[0]
        
        // price를 돌며
        for i in 1..<prices.count {
            // 현재 최고 수익과, 현재가 - 구입가를 비교
            maxProfits = max(maxProfits, prices[i] - buy)
            // 구입가는 현재 구입가와 현재가를 비교한다. 
            buy = min(buy, prices[i])
        }
        // 배열이 순차적으로 진행되기에 index를 거스르는 판매행위는 일어나지 않는다.
        
        return maxProfits
    }
}

 

2. Counting Bits

  • Point
    • 비트연산
    • 몫과 나머지
// 첫 풀이 
class Solution {
    func countBits(_ n: Int) -> [Int] {
        // 1의 갯수를 세줌
        
        for i in 0...n {
            ans.append(String(i, radix: 2).filter {$0 == "1"}.count)
        }
        return ans 
    }
}




// 비트 연산 사용 풀이
class Solution {
    func countBits(_ n: Int) -> [Int] {
        if n == 0 {
            return [0]
        }
        // 0,1인 경우 모두 적어두고
        var ans = [0,1]
        // 2부터 시작
        var idx = 2
        // n까지 조건을 주고 돌면서
        while idx <= n {
            // ans[몫] + ans[나머지]
            // 비트 연산으로 계산
            ans.append(ans[idx >> 1] + ans[idx % 2])
            idx += 1
        }

        return ans
    }
}

 

3. In Subsequence

  • Point
    • 등장 순서
    • 배열의 크기 
class Solution {
    func isSubsequence(_ s: String, _ t: String) -> Bool {
        // 비어있어도 하위 배열 가능
        if s.isEmpty {
            return true
        }
        // 배열화
        var s = s.map { String($0) }
        // 현 위치
        var idx = 0
        
        // t를 돌며
        for w in t {
            // 같을 경우 다음 idx로
            if String(w) == s[idx] {
                idx += 1
            }           
            // idx가 s의 배열과 같다면 모두 순서대로 포함하고 있는 것 
            if idx == s.count {
                return true
            }
        }
        
        
        return false
    }
}

 

4. Min Cost Climbing Stairs

  • Point
    • 최소 출발값 선택
    • 1,2칸 뛸 수 있기에 마지막, 마지막-1 고려해야함
class Solution {
    func minCostClimbingStairs(_ cost: [Int]) -> Int {
        // 각 경우의 최소 cost를 저장하기 위함
        var arr = Array(repeating: 0, count: cost.count)
        // 0,1번째는 바로 저장 
        // 출발선 위치이기에
        arr[0] = cost[0]
        arr[1] = cost[1]
        
        // idx 2부터 시작
        for i in 2..<cost.count {
            // i-1, i-2 중에서 작은 값에서 출발해야 한다. 
            // 최솟값 + 현재값
            // 계속 누적되어 최솟값으로 계산된다.
            arr[i] = min(arr[i-1], arr[i-2]) +  cost[i]
        }
        
        // 마지막 배열 끝 이상으로 나갈 수 있는 경우는 
        // 배열의 총 길이 -1 , -2인 경우이다. 
        // 그렇기에 이 두 개를 비교하여 최솟값을 반환해준다.
        return min(arr[arr.count-1], arr[arr.count-2])
    }
}

 

5. Count Sorted Vowel Strings

  • Point
    • 이전의 값들을 계속 더해준다. 
    • 주어진 수만큼 반복
class Solution {
    func countVowelStrings(_ n: Int) -> Int {
        // 기본 배열
        var res = [1,1,1,1,1]
        // n만큼 반복
        for i in 1...n {
            // 이전 값들을 계속 더해준다. 
            // 결국에 가장 마지막 원소는 
            // 이전의 원소들을 다 더한 값이 된다.
            for j in 1...4 {
                res[j] += res[j-1]
            }
            
        }
        return res.last!
    }
}

 

6. Count_Square_Submatrices_with_All_Ones.swift

 

  • Point
    • 행렬을 2x2로만 판단하여 계속 누적해나간다. 

--행렬 index--

대각(i-1, j-1)   위(i, j-1)

왼쪽(i-1, j)  기준(i, j)

----

1 1

1 1

----

인 경우 왼쪽, 대각, 위의 최솟값이 1이라는 것은 2x2로 만들 수 있다는 것을 의미한다. 

----

1 1

1 2

----

이 처럼 표기하여 2x2가 가능하다는 것을 알린다. 

그리고 최솟값이 2인 경우 그건 3x3으로 만들 수 있다는 것을 의미한다. 

----

1 1 1

1 1 1

1 1 1

----

기존 배열이 이와 같았다면 아래와 같은 순서로 바뀌게 된다

----

1 1 1      1 1 1      1 1 1      1 1 1       1 1 1       1 1 1

1 1 1  >  1 2 1  > 1 2 2  > 1 2 2  > 1 2 2  > 1 2 2

1 1 1      1 1 1      1 1 1       1 2 1      1 2 2     1 2 3

----

최종 배열에서 원소들의 합을 구해주면 답이 된다. 

class Solution {
    func countSquares(_ matrix: [[Int]]) -> Int {
        // matrix 복사
        var temp = matrix
        // 행
        for i in 1..<matrix.count {
            // 열
            for j in 1..<matrix[0].count {
                // temp 행렬 그림
                // 대각  위
                // 왼쪽  기준
                
                // 왼쪽
                let l = temp[i-1][j]
                // 위
                let u = temp[i][j-1]
                // 대각
                let c = temp[i-1][j-1]
                // 최솟값 구하기
                let minC = min(c,min(l,u))
                // 박스의 최솟값이 0이면 그냥 값 그대로 두기
                if min(temp[i][j], minC) == 0 {
                    continue
                // 최솟값이 0이 아닌 경우    
                } else {
                    // 오른쪽 아래 원소에 최솟값 + 1을 할당한다.
                    // 1 1
                    // 1 1
                    // 위 케이스에 해당하기에 
                    // 1 1
                    // 1 2
                    // 이처럼 변경하여 해당 박스는 2x2도 가능하다는 것을 기입해둔다. 
                    // 이후 돌면서 최솟값이 2가 되면 3개까지 가능하다는 말이다!
                    temp[i][j] = (minC+1)
                }
            }
        }
        return temp.flatMap{$0}.reduce(0,+)
    }
}
728x90
반응형