LeetCode Problems/Medium

๐Ÿง‘๐Ÿป‍๐Ÿ’ป LeetCode Medium Collections 1 - 20 Problems

metamong 2024. 9. 9.

0300. Longest Increasing Subsequence / 0053. Maximum Subarray

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        length = len(nums)
        dp = [1]*length

        for x in range(1,length):
            for y in range(0,x):
                if nums[y] < nums[x]:
                    dp[x] = max(dp[x],dp[y]+1)
        return max(dp)
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        ans,curmax=-10001,0
        for i in range(len(nums)):
            curmax=max(curmax+nums[i],nums[i])
            ans=max(ans,curmax)
        return ans

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 300) ์ „ํ˜•์  LIS ์œ ํ˜• ๋ฌธ์ œ. ์œ„ ์ฝ”๋“œ๋Š” O(n^2)์œผ๋กœ ํ•ด๊ฒฐํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‚˜, ์ด๋ถ„ํƒ์ƒ‰์„ ํ™œ์šฉํ•œ O(nlogn) ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ’€์ด๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 053) subarray์˜ ์—ฐ์†๋œ ๋ถ€๋ถ„ํ•ฉ์ด ๊ฐ€์žฅ ํด ๋•Œ์˜ sum ๊ฐ’์„ ์ถœ๋ ฅํ•˜๋Š” ๋ฌธ์ œ. dp ๋˜๋Š” divide & conquer ๊ธฐ๋ฒ• ๋ชจ๋‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅ(์œ„ ํ’€์ด๋Š” dp๋กœ curmax๋ฅผ O(n)์œผ๋กœ ๋Œ๋ฉฐ ๊ณ„์† ์—…๋ฐ์ดํŠธ)


0152. Maximum Product Subarray / 0198. House Robber

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        dp=(nums[0],nums[0])
        ans=nums[0]
        for i in range(1,len(nums)):
            dp=(max(dp[0]*nums[i],dp[1]*nums[i],nums[i]),min(dp[0]*nums[i],dp[1]*nums[i],nums[i]))
            ans = max(ans,max(dp))
        return ans
class Solution:
    def rob(self, nums: List[int]) -> int:
        dp=(nums[0],0)
        for x in range(1,len(nums)):
            dp=(dp[1]+nums[x],max(dp))
        return max(dp)

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 152) subarray์˜ ํ•ฉ์ด ์•„๋‹Œ subarray์˜ product ์ตœ๋Œ“๊ฐ’์„ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ. ๋ฐฐ์—ด์— 0๊ณผ ์Œ์ˆ˜๋„ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์Œ์ˆ˜์™€ ์Œ์ˆ˜๋ฅผ ๊ณฑํ•˜๋ฉด ๋‹ค์‹œ ์–‘์ˆ˜๋กœ ๋ฐ”๋€Œ์–ด ํฐ ๊ฐ’์œผ๋กœ ๋˜๊ธฐ ๋•Œ๋ฌธ์— dp-table์˜ tuple๊ฐ’์„ ํ˜„์žฌ์˜ ์ตœ๋Œ“๊ฐ’๊ณผ ์ตœ์†Ÿ๊ฐ’ ๋‘ ๊ฐœ ๋ชจ๋‘ update ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. ์ž๊ธฐ ์ž์‹  / ์ž๊ธฐ ์ž์‹ ๊ณผ ์•ž ์›์†Œ์˜ ์ตœ๋Œ“๊ฐ’๊ณผ์˜ ๊ณฑ / ์ž๊ธฐ ์ž์‹ ๊ณผ ์•ž ์›์†Œ์˜ ์ตœ์†Ÿ๊ฐ’๊ณผ์˜ ๊ณฑ ์ด๋ ‡๊ฒŒ 3๊ฐœ ์ค‘ ์ตœ๋Œ“๊ฐ’๊ณผ ์ตœ์†Ÿ๊ฐ’์œผ๋กœ update ํ•„์š”

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 198) ์—ฐ์†ํ•ด์„œ ์ง‘์„ ํ„ธ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๋„์–ด์„œ ์ง‘์„ ํ„ธ ๊ฒฝ์šฐ ๊ฐ€์ ธ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๋ˆ์˜ ์ตœ๋Œ“๊ฐ’์„ ๊ตฌํ•ด์•ผ ํ•œ๋‹ค.

 

: ํ•ด๋‹น ์›์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฒฝ์šฐ๋Š”, ์•ž์„  dp ์›์†Œ์—์„œ ํฌํ•จํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ + ํ•ด๋‹น ์›์†Œ / ํ•ด๋‹น ์›์†Œ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋Š”, ํ•ด๋‹น ์›์†Œ ์—†์ด, ์•ž์„  dp์˜ ์ตœ๋Œ“๊ฐ’์œผ๋กœ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.


0238. Product of Array Except Self / 0098. Validate Binary Search Tree

class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        ans=[]
        pre,after = [],[]
        pre_n,after_n=1,1
        for x in range(len(nums)):
            pre_n*=(nums[x])
            pre.append(pre_n)
            after_n*=(nums[len(nums)-1-x])
            after.append(after_n)
        a,b=-1,len(nums)-2
        for x in range(len(nums)):  
            if a < 0:
                ans.append(after[b])
            elif b < 0:
                ans.append(pre[a])
            else:
                ans.append(pre[a]*after[b])
            a+=1
            b-=1
        return ans
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        def check(node, low=-float('inf'), high=float('inf')):
            if not node:
                return True
    
            if node.val <= low or node.val >= high:
                return False
    
            return (check(node.left, low, node.val) and check(node.right, node.val, high))
    
        return check(root)

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 238) ํ˜„์žฌ ์›์†Œ์˜ index๊ฐ€ x๋ผ๋ฉด (index 0 ~ (x-1)๊นŒ์ง€์˜ ๊ณฑ) x (index (x+1)๋ถ€ํ„ฐ ๋๊นŒ์ง€์˜ ๊ณฑ)์„ ๊ฐ ์›์†Œ๋งˆ๋‹ค ์—…๋ฐ์ดํŠธํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 098) ์ฃผ์–ด์ง„ Tree๊ฐ€ Binary Search Tree๋ฅผ ๋งŒ์กฑํ•˜๋ฉด์„œ valid BST์ธ์ง€๊นŒ์ง€ ๋‘ ๊ฐ€์ง€ ์กฐ๊ฑด์„ ๋งŒ์กฑ์‹œํ‚ค๋Š” ์ง€ ํ™•์ธํ•˜๋Š” ๋ฌธ์ œ. valid BST๋ž€, head node๊ฐ€ ์žˆ๊ณ  left ๋˜๋Š” right child๊ฐ€ ์žˆ๋‹ค๋ฉด, ์ „์ฒด tree์˜ ๋ชจ๋“  subtree๊ฐ€ left.val < head.val < right.val์„ ๋งŒ์กฑ์‹œํ‚ค๋Š” tree์ด๋‹ค.

: ์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•  ๊ฑด, ์ „์ฒด tree์˜ ๋ชจ๋“  subtree๊ฐ€ left.val < head.val < right.val์„ ๋งŒ์กฑ์‹œ์ผœ์•ผ ํ•œ๋‹ค๋Š” ์ . ์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ํ™•์ธํ•˜์ž

: ์ดˆ๋ก์ƒ‰์„ ๊ฐ€๋ฆฌํ‚ค๋Š” sub-tree๋Š” left.val < root.val < right.val ์†์„ฑ์„ ๋งŒ์กฑํ•˜๋Š” tree์ด๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋ณด๋‹ค ์Šค์ผ€์ผ์ด ๋” ํฐ ํŒŒ๋ž€์ƒ‰ ์˜์—ญ์˜ subtree๋ฅผ ๋ณด์•˜์„ ๋•Œ root.val 33๊ธฐ์ค€ 4๋ฒˆ ๋…ธ๋“œ val์€ 0๋ฒˆ ๋…ธ๋“œ val ๋ณด๋‹ค ํฌ๊ณ , 5๋ฒˆ ๋…ธ๋“œ val์€ 0๋ฒˆ ๋…ธ๋“œ val ๋ณด๋‹ค ์ž‘์œผ๋ฏ€๋กœ ๋งŒ์กฑํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ, ๋ชจ๋“  subtree์— ๋Œ€ํ•ด left.val < root.val < right.val ์†์„ฑ์„ ๋งŒ์กฑํ•ด์•ผ ํ•œ๋‹ค.

 

: recursion ํ™œ์šฉ์‹œ ํ•จ์ˆ˜์˜ parameter ์„ธ ์ข…๋ฅ˜๋ฅผ head node, ํ•ด๋‹น head node๋ฅผ head๋กœ ๊ฐ–๊ณ  ์žˆ๋Š” subtree์—์„œ head node ๊ฐ€๋Šฅํ•œ ๋ฒ”์œ„ ์ตœ์†Ÿ๊ฐ’-1, ์ตœ๋Œ“๊ฐ’+1 ์ด๋ ‡๊ฒŒ ์„ค์ •. recursiveํ•˜๊ฒŒ ๊ฐ node๋ฅผ ๋Œ๋ฉฐ ๊ฐ node๊ฐ€ ๊ฐ€๋Šฅํ•œ ๋ฒ”์œ„ ์ตœ์†Ÿ๊ฐ’๊ณผ ์ตœ๋Œ“๊ฐ’ ์‚ฌ์ด์— ์†ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฐ”๋กœ False ๋ฆฌํ„ด. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ•ด๋‹น node์˜ left์™€ right ๊ฐ๊ฐ head node๋กœ ๋‘๋Š” subtree recusiveํ•˜๊ฒŒ ๋Œ๋ ค(left์™€ right ๋ชจ๋‘ ๋งŒ์กฑํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ and ์กฐ๊ฑด ์—ฐ๊ฒฐ) ๊ณ„์† ํ™•์ธ! (์œ„ ์˜ค๋ฅธ์ชฝ ๊ทธ๋ฆผ ์ฐธ๊ณ )


0150. Evaluate Reverse Polish Notation / 0102. Binary Tree Level Order Traversal

import math
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack=[]
        operands=['*', '+', '-', '/']
        for token in tokens:
            if token not in operands:
                stack.append(int(token))
            else:
                x,y=stack.pop(),stack.pop()
                if token == '+':
                    stack.append(x+y)
                elif token == '-':
                    stack.append(y-x)
                elif token == '/':
                    stack.append(math.trunc(y/x))
                else: #*
                    stack.append(x*y)
        return stack[-1]
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
from collections import deque
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root:
            return None
        queue = deque([root])
        answer = []
        while queue:
            level = []
            length = len(queue)
            for _ in range(length):
                cur = queue.popleft()
                level.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            answer.append(level)
        return answer

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0150) operand์— ๋”ฐ๋ผ ์ตœ๊ทผ์— ๋“ค์–ด์˜จ ๋‘ ๊ฐœ์˜ ์›์†Œ๋ฅผ ์—ฐ์‚ฐํ•˜๋Š” ์ „ํ˜•์ ์ธ stack ๋ฌธ์ œ. ์˜ˆ๋ฅผ ๋“ค์–ด 3 4 + ๋ผ๋ฉด, ์ˆซ์ž๋งŒ stack์— ๋„ฃ๊ณ , +์™€ ๊ฐ™์€ operand๋ฅผ ๋งŒ๋‚ฌ์„ ๋•Œ ์ตœ๊ทผ์— ๋„ฃ์€ ๋‘ ๊ฐœ๋ฅผ ๋นผ์„œ operand์— ๋”ฐ๋ผ ์—ฐ์‚ฐํ•œ ๋’ค, ๋‹ค์‹œ stack์— ๋„ฃ๊ธฐ๋ฅผ ๋ฐ˜๋ณต. ์ด ๋•Œ ๋‚˜๋ˆ—์…ˆ๋งŒ ์ฃผ์˜. ํŒŒ์ด์ฌ์˜ ๊ฒฝ์šฐ / ์—ฐ์‚ฐ์ž ์‚ฌ์šฉํ•˜์—ฌ ๋‚˜๋ˆ„๊ณ , math.trunc() ํ•จ์ˆ˜(์†Œ์ˆ˜์  ๋ฒ„๋ฆฌ๋Š” ํ•จ์ˆ˜) ํ™œ์šฉํ•˜์—ฌ ์—ฐ์‚ฐ

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0102) level order๋กœ ์ฝ์–ด์„œ level ๋ณ„ node์˜ value๋ฅผ ํ•œ ๊ฐœ์˜ list๋กœ ๋งŒ๋“ค๊ณ  ์ „์ฒด ์ด์ค‘ list๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๋ฌธ์ œ. level๋ณ„๋กœ node๋ฅผ ์ฝ์œผ๋ฏ€๋กœ BFS ํ™œ์šฉ. for๋ฌธ ๋‚ด๋ถ€์— print(root)๋ฅผ ๋„ฃ๋Š”๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค.

์ฆ‰ root์˜ ๊ธธ์ด ์ž์ฒด๊ฐ€ ํ˜„ level์˜ node ๊ฐœ์ˆ˜์ด๋ฏ€๋กœ length = len(queue)๋กœ length๋งŒํผ popleft() ์ง„ํ–‰ํ•œ ๋‹ค์Œ, for๋ฌธ ๋Œ ๋•Œ๋งˆ๋‹ค level list์— node.val append. ์ตœ์ข…์ ์œผ๋กœ level list๋ฅผ ๊ณ„์† ๋„ฃ์€ answer 2์ฐจ์› list ์ถœ๋ ฅ


0133. Clone Graph / 0200. Number of Islands

"""
# Definition for a Node.
class Node:
    def __init__(self, val = 0, neighbors = None):
        self.val = val
        self.neighbors = neighbors if neighbors is not None else []
"""

from typing import Optional
from collections import deque
class Solution:
    def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
        if not node:
            return
        clone = Node(node.val)
        clones = {node: clone}
        queue = deque([node])
        while queue:
            node = queue.popleft()
            for nei in node.neighbors:
                if nei not in clones:
                    clones[nei] = Node(nei.val)
                    queue.append(nei)
                clones[node].neighbors.append(clones[nei])
        return clone
from collections import deque
class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        def BFS(graph, start):
            graph[start[0]][start[1]] = '0'
            queue = deque([start])
            dx, dy = [-1,1,0,0], [0,0,-1,1]
            while queue:
                node = queue.popleft()
                for i in range(4):
                    nx, ny = node[0]+dx[i], node[1]+dy[i]
                    if 0<=nx<m and 0<=ny<n:
                        if graph[nx][ny] == '1':
                            graph[nx][ny] = '0'
                            queue.append((nx,ny))
        m, n = len(grid), len(grid[0])
        ans = 0
        for x in range(m):
            for y in range(n):
                if grid[x][y] == '1':
                    ans += 1
                    BFS(grid,(x,y))
        return ans

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0133) BFS

(1) ์‹œ์ž‘ node๋ฅผ ์œ„ํ•œ clone Node class๋ฅผ ์ƒ์„ฑ.

(2) ๊ทธ ๋‹ค์Œ queue์— ๋„ฃ๊ณ , BFS๋กœ ์—ฐ๊ฒฐ ๋…ธ๋“œ ํ™•์ธ. ์—ฐ๊ฒฐ ๋…ธ๋“œ ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๊ธฐ์กด ๋…ธ๋“œ์˜ neighbors์— update

(3) ์—ฐ๊ฒฐ ๋…ธ๋“œ๊ฐ€ clones์— ์—†๋‹ค๋ฉด ์—ฐ๊ฒฐ ๋…ธ๋“œ๊ฐ€ ๋“ค์–ด๊ฐ„ ์ƒˆ๋กœ์šด Node class ์ƒ์„ฑํ•˜๊ณ  clones dictionary์— ์ƒ์„ฑํ•œ Node class ์‚ฝ์ž…. queue์— append

(4) ์œ„ (2) ~ (3) ๊ณผ์ • queue์— ์•„๋ฌด ๊ฒƒ๋„ ์—†์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต

(5) ์ตœ์ข…) 'return the copy of the given node as a reference to the cloned graph'๋ผ๊ณ  ํ•˜์˜€์œผ๋ฏ€๋กœ the given node(val = 1)๋กœ ์ฒ˜์Œ์— ๋งŒ๋“  clone ๋ฐ”๋กœ return (return clone)

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0200) ์—ฐ๊ฒฐ์š”์†Œ์˜ ๊ฐœ์ˆ˜ ์œ ํ˜•


1456. Maximum Number of Vowels in a Substring of Given Length / 0033. Search in Rotated Sorted Array

class Solution:
    def maxVowels(self, s: str, k: int) -> int:
        ans=0
        for letter in s[:k]:
            if letter in 'aeiou':
                ans+=1
        start=0
        prev=ans
        for letter in s[k:]:
            if s[start] in 'aeiou':
                prev-=1
            if letter in 'aeiou':
                prev+=1
            ans=max(ans,prev)
            start+=1
        return ans
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        start,end=0,len(nums)-1
        while start<=end:
            mid = (start+end)//2
            if target == nums[mid]:
                return mid
            
            #left
            if nums[start] <= nums[mid]:
                if target > nums[mid] or target < nums[start]:
                    start = mid + 1
                else:
                    end = mid - 1
            
            #right
            else:
                if target < nums[mid] or target > nums[end]:
                    end = mid - 1
                else:
                    start = mid + 1
        return -1

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 1456) ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ๋ฌธ์ œ. ์ •ํ•ด์ง„ ๊ธธ์ด๋งŒํผ ์˜ค๋ฅธ์ชฝ ๋๊นŒ์ง€ ์Šฌ๋ผ์ด๋“œ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๋งจ ์•ž๊ณผ ๋งจ ๋’ค์˜ ๊ธ€์ž๊ฐ€ vowel์— ๋“ค์–ด๊ฐ€๋Š” ์ง€์— ๋”ฐ๋ผ -=1, +=1. max() ํ•จ์ˆ˜ ์‚ฌ์šฉํ•ด์„œ ์—…๋ฐ์ดํŠธ

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0033) ์ด๋ถ„ํƒ์ƒ‰ ์‘์šฉ๋ฒ„์ „. ์›๋ž˜ ์ด๋ถ„ํƒ์ƒ‰์€ sorted ๋œ ์ƒํƒœ์—์„œ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๊ตญ๋ฃฐ์ด๋‚˜, rotated sorted array์—์„œ ์ด๋ถ„ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•œ๋‹ค๋Š” ์ ์ด ์ฃผ๋ชฉํ•  ๋งŒํ•œ ๋ถ€๋ถ„. ๋‹จ rotated sorted array๋Š” sorted๋œ array 2๊ฐœ๊ฐ€ ๊ฒฐํ•ฉํ•œ ๊ฒƒ์ž„์„ ์•Œ์•„์•ผ ํ•œ๋‹ค.

: mid ์›์†Œ๊ฐ€ ์™ผ์ชฝ sorted array์— ์†ํ•˜๋Š” ์ง€, ์˜ค๋ฅธ์ชฝ sorted array์— ์†ํ•˜๋Š” ์ง€์— ๋”ฐ๋ผ์„œ ๋‹ค๋ฅด๊ฒŒ ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด start, end update


0139. Word Break / 0207. Course Schedule

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        dp = [True] + [False]* len(s)
        for i in range(1, len(s) + 1):
            for word in wordDict:
                if s[i - len(word): i] == word:
                    dp[i] = dp[i-len(word)]
                if dp[i]: #found True only once
                    break
        return dp[-1]
class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        from collections import deque
        indegree = [0] * (numCourses)
        graph = [[] for _ in range(numCourses)]

        for prerequisite in prerequisites:
            x,y=prerequisite[0],prerequisite[1]
            graph[y].append(x)
            indegree[x]+=1
        
        res = 0
        q = deque()

        for i in range(numCourses):
            if indegree[i] == 0:
                q.append(i)  

        while q:
            node = q.popleft()
            res += 1
            for i in graph[node]:
                indegree[i] -= 1
                if indegree[i] == 0:
                    q.append(i)
                    
        return res==numCourses

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0139) 'leetcode'๋ผ๋Š” ๋ฌธ์ž์—ด์„ ์˜ˆ๋กœ ๋“ค์ž๋ฉด, wordDict = ['leet', 'code']๋ผ๊ณ  ํ–ˆ์„ ๋•Œ, DP[x]๋ž€ index x๊นŒ์ง€์˜ ๋ฌธ์ž์—ด์ด wordDict๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ง€์˜ ์—ฌ๋ถ€๋ฅผ ๋œปํ•œ๋‹ค. ๋”ฐ๋ผ์„œ wordDict๋ฅผ ์ง์ ‘ ๋Œ๋ฉฐ word์˜ ๊ธธ์ด๋ฅผ w๋ผ๊ณ  ํ•œ๋‹ค๋ฉด DP[x] = DP[x-w]๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜ ๊ทธ๋ฆผ ์ฐธ์กฐ.

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0207) prerequisite์œผ๋กœ course์˜ ์ˆœ์„œ๊ฐ€ ์ •ํ•ด์ง„ ์ƒํƒœ์—์„œ, ๋ชจ๋“  course๋ฅผ ๋“ค์„ ์ˆ˜ ์žˆ๋Š” ์ง€, ์ฆ‰ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ traverseํ•  ์ˆ˜ ์žˆ๋Š” ์ง€ = ์œ„์ƒ ์ •๋ ฌ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ๋ฌป๋Š” ๋ฌธ์ œ. ์œ„์ƒ ์ •๋ ฌ์ด ๊ฐ€๋Šฅํ•œ ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„ , ์ƒ์„ฑํ•œ ๊ทธ๋ž˜ํ”„๊ฐ€ DAG(Directed Acyclic Graph; ๋ฐฉํ–ฅ ๋น„์ˆœํ™˜ ๊ทธ๋ž˜ํ”„)๋ฅผ ๋งŒ์กฑํ•ด์•ผ ํ•œ๋‹ค. queue๋ฅผ ๋งŒ๋“ค์–ด popleft()๋กœ ๊บผ๋‚ผ ๋•Œ๋งˆ๋‹ค ๋ฐฉ๋ฌธ ํ™•์ธ. ๊บผ๋‚ธ ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๋ฅผ ๋ˆ„์ ํ•ด์„œ ๊ตฌํ•œ๋‹ค. ๊ตฌํ•œ ๊ฒฐ๊ณผ์™€ ์ „์ฒด ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๋ฅผ ๋น„๊ตํ•˜์—ฌ ๊ฐ™๋‹ค๋ฉด ๋ฐฉํ–ฅ ๋น„์ˆœํ™˜ ๊ทธ๋ž˜ํ”„์ด๋ฏ€๋กœ true. ๊ฐ™์ง€ ์•Š๋‹ค๋ฉด ๋ฐฉํ–ฅ ๋น„์ˆœํ™˜ ๊ทธ๋ž˜ํ”„๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ false.


0236. Lowest Common Ancestor of a Binary Tree / 0046. Permutations

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if root:
            if root == p or root == q:
                return root
            
            l = self.lowestCommonAncestor(root.left, p, q)
            r = self.lowestCommonAncestor(root.right, p, q)

            if l and r:
                return root
            else:
                return l or r
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def track():
            if len(ans) == length:
                ans_collections.append(ans[:])
            else:
                for x in range(length):
                    if len(ans) != 0 and nums[x] in ans:
                        continue
                    else:
                        ans.append(nums[x])
                        track()
                        ans.pop()
        nums.sort()
        ans_collections=[]
        ans=[]
        length = len(nums)
        track()
        return ans_collections

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0236) ์žฌ๊ท€ํ•จ์ˆ˜ ํ™œ์šฉ. p์™€ q ๋…ธ๋“œ์˜ LCA๋ฅผ ์ฐพ๋Š” ๋ฌธ์ œ. ์ด ๋•Œ root ์ž์ฒด๊ฐ€ p ๋˜๋Š” q์ด๋ฉด root๊ฐ€ LCA์ด๋ฏ€๋กœ return root. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์žฌ๊ท€์ ์œผ๋กœ left / right ๊ฐ๊ฐ ํŒŒ๊ณ ๋“ค์–ด์„œ ํ™•์ธ. l๊ณผ r ๋ชจ๋‘ ์กด์žฌํ•œ๋‹ค๋ฉด(์ฆ‰, p์™€ q ๊ฐ๊ฐ์ด l๊ณผ r ๋˜๋Š”, r๊ณผ l์— ์กด์žฌํ•œ๋‹ค๋ฉด) ๊ฒฐ๊ตญ์€ root๊ฐ€ LCA. ๊ทธ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด l ๋˜๋Š” r ํ•œ์ชฝ์— p์™€ q ๋‘ ๊ฐœ๊ฐ€ ๊ฐ™์ด ์กด์žฌํ•œ๋‹ค๋ฉด l ๋˜๋Š” r์„ ๋ฆฌํ„ด

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป0046) ์ „ํ˜•์ ์ธ backtracking ๋ฌธ์ œ. ๋จผ์ € sortingํ•˜๊ณ  ์ง„ํ–‰. ์ด ๋•Œ, ์ ์ ˆํ•œ ans๋ฅผ ์ฐพ์„ ๋•Œ๋งˆ๋‹ค ans_collections list์— ans๋ฅผ appendํ•œ๋‹ค. ans_collections.append(ans)๋ฅผ ํ•œ๋‹ค๋ฉด, ans์˜ reference๋ฅผ appendํ•˜๋ฏ€๋กœ, ์‹ค์ œ ans ์ž์ฒด์˜ current copy๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์•„๋‹˜. ๋”ฐ๋ผ์„œ ์ดํ›„ ans๊ฐ€ ๊ณ„์† ๋ณ€ํ•  ๋•Œ๋งˆ๋‹ค ans์˜ ๋‚ด์šฉ๋„ ๋ณ€ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ans_collections.append(ans[:]) ์ฝ”๋“œ(shallow copy of ans)๋ฅผ ์‚ฌ์šฉํ•ด append๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค.


0056. Merge Intervals / 0011. Container with Most Water

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        ans=[]
        intervals.sort(key=lambda x: x[0])
        for start,end in intervals:
            if not ans:
                ans.append([start,end])
            elif ans[-1][1] < start:
                ans.append([start,end])
            else: #if overlapped
                ans[-1][1] = max(ans[-1][1], end)
        return ans
class Solution:
    def maxArea(self, height: List[int]) -> int:
        res = 0
        l,r = 0,len(height)-1

        while l < r:
            area = (r-l) * min(height[l], height[r])
            res = max(res, area)

            if height[l] < height[r]:
                l += 1
            else:
                r -= 1
        return res

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0056) ๋จผ์ € ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ์˜ค๋ฆ„์ฐจ์ˆœ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•œ ๋’ค, intervals list ์ง์ ‘ for๋ฌธ์œผ๋กœ ๋Œ๋ฆฌ๋ฉด์„œ ๋งˆ์ง€๋ง‰ ans[-1][1]์™€ start ๋น„๊ต. ๋ฐ”๊ฟ”์•ผ ํ•˜๋ฉด ans[-1][1] ์ž์ฒด๋ฅผ ๋ฐ”๊ฟˆ

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0011) ํˆฌ ํฌ์ธํ„ฐ O(N)์œผ๋กœ ํ’€์–ด์•ผ TLE ๋˜์ง€ ์•Š๋Š”๋‹ค. ๋งจ ์™ผ์ชฝ๊ณผ ์˜ค๋ฅธ์ชฝ์— ํฌ์ธํ„ฐ๋ฅผ ๋‘๊ณ  ๋‹น์žฅ์˜ ๋‘ ๋ง‰๋Œ€ ์ค‘ ์ตœ์†Ÿ๊ฐ’์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ง‰๋Œ€๋ฅผ ์ค‘๊ฐ„ ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™. ์ตœ๋Œ“๊ฐ’์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ง‰๋Œ€๋ฅผ ์ด๋™ํ•˜๋ฉด ์ตœ์†Ÿ๊ฐ’์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ง‰๋Œ€๋ณด๋‹ค ๊ฐ™๊ฑฐ๋‚˜ ์ž‘์€ ๋ง‰๋Œ€๋งŒ ์‹ค์ œ ๋ฉด์  ๊ณ„์‚ฐ์— ์ ์šฉ๋˜๋ฏ€๋กœ ์ตœ์†Ÿ๊ฐ’์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ง‰๋Œ€๋ฅผ ์ด๋™ํ•˜๋Š” ๋ฐ ์ดˆ์ ์„ ๋‘์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด O(N) ์‹œ๊ฐ„ ๋ณต์žก๋„๋กœ ์ด๋™ํ•ด์„œ optimal solution์„ ์ฐพ๋Š” ๊ฒƒ์ด ๋ณด์žฅ๋˜์–ด ์žˆ์„๊นŒ? ์ฆ๋ช…ํ•ด๋ณด์ž.

 

โ˜… optimal solution์„ ๊ฐ€์ง€๋Š” answer ๋‘ ๋ง‰๋Œ€๊ฐ€ ๊ฐ๊ฐ i์™€ j์— ์žˆ๋‹ค๊ณ  ๊ฐ€์ •.

: ๋‹น์žฅ ๋‘ ํฌ์ธํ„ฐ ์ค‘ ๋” ์ž‘์€ ํฌ์ธํ„ฐ๋ฅผ ์›€์ง์ด๋Š”๊ฒŒ optimal ๋ณด์žฅ์ž„์„ ์ฆ๋ช…ํ•ด์•ผ ํ•œ๋‹ค. i์™€ j๊ฐ€ ์ผ๋‹จ optimal์ด๋ผ ๊ฐ€์ •. ๊ทธ๋ ‡๋‹ค๋ฉด i์˜ ์™ผ์ชฝ ๋ง‰๋Œ€๋“ค๊ณผ j์˜ ์˜ค๋ฅธ์ชฝ ๋ง‰๋Œ€๋“ค์€ ๋ฌด์กฐ๊ฑด min(i,j)๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ฐ˜๋Œ€๋กœ ํฌ๋‹ค๋ฉด ๋” ํฐ ๋„ˆ๋น„์— ๋†’์ด๋Š” i ๋˜๋Š” j๋ฅผ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ. ๋”ฐ๋ผ์„œ ๋งจ ์ฒ˜์Œ i๋ฅผ ๋งจ ์™ผ์ชฝ, j๋ฅผ ๋งจ ์˜ค๋ฅธ์ชฝ์— ๋‘๊ณ  ์‹œ์ž‘ํ•˜๋Š” ๊ฑด, i์˜ ์™ผ์ชฝ๊ณผ j์˜ ์˜ค๋ฅธ์ชฝ(๋‹น์—ฐํžˆ ๋‘ ๊ณณ ๋‹ค blank)์ด ๋ชจ๋‘ min(i,j)๋ณด๋‹ค ์ž‘๊ธฐ ๋•Œ๋ฌธ์ด๊ณ , ํ˜„ ์ƒํ™ฉ์—์„œ optimalํ•œ ์ƒํƒœ. ๊ทธ ์ƒํƒœ์—์„œ ๊ณ„์† greedyํ•˜๊ฒŒ optimalํ•œ ์ƒํƒœ๋ฅผ ์ฐพ์•„ ๋‚˜๊ฐ€๋ฉฐ two pointers์ค‘ min(i,j)๋ฅผ ์ค‘์•™์ชฝ์œผ๋กœ ์ด๋™ํ•˜๋ฉฐ optimal solution updateํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค!


0019. Letter Combinations of a Phone Number / 0416. Partition Equal Subset Sum

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        res = []
        digitToChar = {"2" : "abc", "3" : "def", "4" : "ghi", "5" : "jkl",
        "6" : "mno", "7" : "qprs", "8" : "tuv", "9" : "wxyz"}

        def track(i, curStr):
            if len(curStr) == len(digits):
                res.append(curStr)
                return
            for c in digitToChar[digits[i]]:
                track(i+1, curStr+c)
        
        if digits:
            track(0, "")
        
        return res
class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        total = sum(nums)
        if total % 2: return False
        dp = set()
        dp.add(0)
        target = total // 2

        for i in range(len(nums)):
            nextDP = set()
            for t in dp:
                nextDP.add(t + nums[i])
                nextDP.add(t)
            dp = nextDP
        return True if target in dp else False

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0017) ๊ธฐ๋ณธ backtracking ๋ฌธ์ œ. index๋ฅผ ํ™œ์šฉํ•ด ์›€์ง์ด๋ฉด ์ข€ ๋” ๋ฐฑํŠธ๋ž˜ํ‚น ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ฝ”๋“œ๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์งค ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿง‘๐Ÿป‍๐Ÿ’ป 0416) for๋ฌธ์„ ์ง์ ‘ ๋Œ๋ฆฌ๋ฉด์„œ ์˜ˆ๋ฅผ ๋“ค์–ด [1, 2, 3, 4]๋ผ๋ฉด [1,2]๊นŒ์ง€์˜ list์—์„œ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  subset์—์„œ ๊ทธ ๋‹ค์Œ ์›์†Œ 3์„ ๋”ํ–ˆ์„ ๋•Œ์— ๋งŒ๋“ค์–ด์งˆ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  subset sum์„ ๋‹ค์‹œ update ํ•˜๋ฉฐ ์ผ์ผ์ด DP set update


๋Œ“๊ธ€