leetcode hot100

1. Two Sum

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        di = dict()
        for i, elem in enumerate(nums):
            if (target - elem) in di:
                return [i, di[target-elem]]
            di[elem] = i

字典(哈希表)解决法,开始犯了2个问题,一个是直接把所有值先存入字典,这样会导致可能找到2个同一元素;一个问题是返回时用di[elem],因为此时elem还没存入di。

2. Add Two Numbers

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        res = ListNode()
        head = res
        forward = 0
        while l1 or l2:
            v1 = l1.val if l1 is not None else 0
            v2 = l2.val if l2 is not None else 0
            tmp_val = v1 + v2 + forward
            if tmp_val >= 10:
                tmp_val = tmp_val - 10
                forward = 1
            else:
                forward = 0
            res.val = tmp_val
            l1 = l1.next if l1 is not None else l1
            l2 = l2.next if l2 is not None else l2
            if l1 or l2:
                res.next = ListNode()
                res = res.next
        if forward != 0:
            res.next = ListNode()
            res = res.next
            res.val = forward
        return head

写的过程出现的问题:1.没有设置head导致最后结果返回最后一位 2.每次循环开辟一个新的Node默认为0,导致最后会多出一个0,这个加一个判断是否到末尾 3.当l1和l2都走完后有可能还会有一次进位在最后需要判断

4.不够简洁,重新写。

3. Longest Substring Without Repeating Characters

先暴力解法

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        max_len = 0
        for i in range(len(s)):
            set_s = set()
            current_len = 0
            for j in range(i, len(s)):
                if s[j] in set_s:
                    break
                set_s.add(s[j])
                current_len += 1
            if current_len > max_len:
                max_len = current_len
        return max_len

滑动窗口解法,右边移动,如果碰到前面出现过的,左边移动至不重复再继续找。

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        max_len = 0
        current_len = 0
        start = 0
        set_s = set()
        for end in range(len(s)):
            current_len += 1
            while s[end] in set_s:
                current_len -= 1
                set_s.remove(s[start])
                start += 1
            max_len = current_len if current_len > max_len else max_len
            set_s.add(s[end])
        return max_len

4. Median of Two Sorted Arrays

5. Longest Palindromic Substring

class Solution:
    def longestPalindrome(self, s: str) -> str:
        dp = [[False for i in range(len(s))] for j in range(len(s))]
        for i in range(len(s)):
            dp[i][i] = True
        for i in range(len(s) - 1):
            dp[i][i + 1] = True if s[i] == s[i + 1] else False
        for i in range(len(s)):
            for step in range(1, len(s)):
                if i-step < 0 or i + step >= len(s) or not dp[i - step + 1][i + step - 1]:
                    break
                dp[i - step][i + step] = True if s[i - step] == s[i + step] else False
            for step in range(1, len(s) - 1):
                if i - step < 0 or i + 1 + step >= len(s) or not dp[i - step + 1][i + step]:
                    break
                dp[i - step][i + 1 + step] = True if s[i - step] == s[i + 1 + step] else False
        max_str = ""
        for i in range(len(s)):
            for j in range(i, len(s)):
                if dp[i][j] and j - i + 1 > len(max_str):
                    max_str = s[i:j + 1]
        return max_str

10. Regular Expression Matching

11. Container With Most Water

class Solution:
    def calcaute_area(self, height, left, right):
        return min(height[left], height[right]) * (right - left)

    def maxArea(self, height: List[int]) -> int:
        left = 0
        right = len(height) - 1
        best_left = height[left]
        best_right = height[right]
        max_area = self.calcaute_area(height, left, right)
        while left < right:
            if height[left] < height[right]:
                while height[left] <= best_left and left < right:
                    left += 1
            else:
                while height[right] <= best_right and left < right:
                    right -= 1
            if left < right:
                area = self.calcaute_area(height, left, right)
                if area > max_area:
                    max_area = area
                    best_left = height[left]
                    best_right = height[right]
                else:
                    if height[left] < height[right]:
                        left += 1
                    else:
                        right -= 1
        return max_area

双指针,关键在于指针移动顺序,因为面积取决于短板,所以率先移动短板指针。另外,相对简洁的官方答案,多加了一步:如果移动后的高度<=原来最优的高度,面积必然不会更大,所以可以跳过此种情况的计算。

15. 3Sum

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        arr = sorted(nums)
        res = []
        for i in range(len(arr)):
            if arr[i] > 0:
                break
            if i > 0 and arr[i] == arr[i - 1]:
                continue
            left = i + 1
            right = len(arr) - 1
            while left < right:
                if left > i + 1 and arr[left] == arr[left - 1] and left < right:
                    left += 1
                    continue
                sum = arr[left] + arr[right] + arr[i]
                if sum == 0:
                    res.append([arr[i], arr[left], arr[right]])
                    left += 1
                    right -= 1
                elif sum > 0:
                    right -= 1
                else:
                    left += 1
        return res

三个数相加,先排序,遍历第一个数,然后后两个数用双指针。容易错的是结果不能重复,所以要限制第一第二个数不能重复(因为排序了所以判断和前一个数不同即可)

17. Letter Combinations of a Phone Number

19. Remove Nth Node From End of List

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        nums = 0
        p = head
        while p:
            nums += 1
            p = p.next
        k = nums - n
        pre = head
        if k == 0:
            head = head.next
            return head
        for i in range(k-1):
            pre = pre.next
        middle = pre.next
        pro = middle.next
        pre.next = pro
        middle.next = None
        return head

20. Valid Parentheses

class Solution:
    def isValid(self, s: str) -> bool:
        stack = []
        valid_ch = {"[":"]", "{":"}", "(":")"}
        for elem in s:
            if len(stack) != 0 and valid_ch.get(stack[-1], None) == elem:
                stack.pop()
            else:
                stack.append(elem)
        return len(stack) == 0

21. Merge Two Sorted Lists

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        dummy_node = ListNode()
        p = dummy_node
        while list1 and list2:
            if list1.val <= list2.val:
                p.next = list1
                list1 = list1.next
            else:
                p.next = list2
                list2 = list2.next
            p = p.next
        p.next = list1 if list1 else list2
        return dummy_node.next

22. Generate Parentheses

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        res = []
        def dfs(s, left, right):
            if left == 0 and right == 0:
                res.append(s)
            if left > right:
                return
            if left > 0:
                dfs(s + "(", left - 1, right)
            if right > 0:
                dfs(s + ")", left, right - 1)
        dfs("", n, n)
        return res

31. Next Permutation

33. Search in Rotated Sorted Array

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        low = 0
        high = len(nums) - 1
        while low <= high:
            mid = int((low + high) / 2)
            if nums[mid] == target:
                return mid
            if nums[low] <= nums[mid]:
                if target < nums[mid] and target >= nums[low]:
                    high = mid - 1
                else:
                    low = mid + 1
            else:
                if target > nums[mid] and target <= nums[high]:
                    low = mid + 1
                else:
                    high = mid - 1
        return -1

思路是二分查找,且左边或者右边至少有一个有序数组,找到有序数组,就可以直接判断target是否在其中。判断有序数组时,得用<=,等号涵盖了没有数的情况。

34. Find First and Last Position of Element in Sorted Array

39. Combination Sum

class Solution:

    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        res = []
        def dfs(candidates, target, cur_sum, arr, from_index):
            if cur_sum == target:
                res.append(arr.copy())
            elif cur_sum > target:
                return
            for i in range(from_index, len(candidates)):
                arr.append(candidates[i])
                dfs(candidates, target, cur_sum + candidates[i], arr, i)
                arr.pop()
        dfs(candidates, target, 0, [], 0)
        return res

注意数组加进去时要copy否则会在其他地方被改掉,再就是要加一个from_index,不再往回挑选导致重复。

46. Permutations

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        res = []

        def dfs(nums, used_index, one):
            if len(used_index) == len(nums):
                res.append(one.copy())
            for i in range(len(nums)):
                if i in used_index:
                    continue
                one.append(nums[i])
                used_index.add(i)
                dfs(nums, used_index, one)
                one.pop()
                used_index.discard(i)

        dfs(nums, set(), [])
        return res

48. Rotate Image

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        # f(i, j) => f(j, n-i-1)
        # f(j, n-i-1) => f(n-i-1, n-j-1)
        # f(n-i-1, n-j-1) => f(n-j-1, i)
        # f(n-j-1, i) => f(i, j)
        n = len(matrix)
        visited = [[False for i in range(n)] for j in range(n)]
        for i in range(n):
            for j in range(n):
                if not visited[i][j]:
                    visited[i][j] = True
                    visited[j][n-i-1] = True
                    visited[n-i-1][n-j-1] = True
                    visited[n-j-1][i] = True
                    t1 = matrix[i][j]
                    t2 = matrix[j][n-i-1]
                    t3 = matrix[n-i-1][n-j-1]
                    t4 = matrix[n-j-1][i]
                    matrix[j][n-i-1] = t1
                    matrix[n-i-1][n-j-1] = t2
                    matrix[n-j-1][i] = t3
                    matrix[i][j] = t4

49. Group Anagrams

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        di = dict()
        for i, s in enumerate(strs):
            new_s = "".join(sorted(s))
            if new_s not in di:
                di[new_s] = []
            di[new_s].append(s)
        return [elem for elem in di.values()]

53. Maximum Subarray

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        current_max = nums[0]
        res = nums[0]
        for i in range(1, len(nums)):
            current_max = max(nums[i], current_max + nums[i])
            if current_max > res:
                res = current_max
        return res

f(i)为0-i之间以i为结尾的最大sum,f(i) = max(f(i - 1) + nums[i], nums[i]),每进一位,看前面的串是否需要断掉。

55. Jump Game

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        max_index = 0
        for i, num in enumerate(nums[:-1]):
            max_index = (num + i) if (num + i > max_index) else max_index
            if max_index == i:
                return False
        if max_index >= len(nums) - 1:
            return True
        return False

每个位置判断目前能到达最远的地方,如果当前最远的地方就是当前位置,说明无法跳出。倒数第二位位置能到达最远地方如果>=最后一位,说明能到达,否则不能到达。

56. Merge Intervals

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        sorted_intervals = sorted(intervals, key=lambda x: x[0])
        res = []
        i = 0
        while i < len(sorted_intervals):
            current_left = sorted_intervals[i][0]
            current_right = sorted_intervals[i][1]
            while i < len(sorted_intervals) - 1 and current_right >= sorted_intervals[i+1][0]:
                current_right = max(current_right, sorted_intervals[i+1][1])
                i += 1
            res.append([current_left, current_right])
            i += 1
        return res

62. Unique Paths

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        #count[mm][nn] = count[mm-1][nn] + count[mm][nn-1]
        count = [[0] * n] * m
        for mm in range(m):
            count[mm][0] = 1
        for nn in range(n):
            count[0][nn] = 1
        for mm in range(1, m):
            for nn in range(1, n):
                count[mm][nn] = count[mm-1][nn] + count[mm][nn-1]
        return count[m-1][n-1]

64. Minimum Path Sum

class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])
        res = [[0 for i in range(n)] for j in range(m)]
        res[0][0] = grid[0][0]
        for i in range(1, m):
            res[i][0] = res[i-1][0] + grid[i][0]
        for i in range(1, n):
            res[0][i] = res[0][i-1] + grid[0][i]
        for i in range(1, m):
            for j in range(1, n):
                res[i][j] = min(res[i-1][j], res[i][j-1]) + grid[i][j]
        return res[m-1][n-1]

70. Climbing Stairs

class Solution:
    def climbStairs(self, n: int) -> int:
        if n == 1:
            return 1
        if n == 2:
            return 2
        res = [0 for i in range(n)]
        res[0] = 1
        res[1] = 2
        for i in range(2, n):
            res[i] = res[i - 1] + res[i - 2]
        return res[n - 1]

75. Sort Colors

class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        count = [0, 0, 0]
        for num in nums:
            count[num] += 1
        for i in range(len(nums)):
            if i < count[0]:
                nums[i] = 0
            elif i < count[0] + count[1]:
                nums[i] = 1
            else:
                nums[i] = 2

78. Subsets

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []
        def get_subset(nums, i, current):
            if i == len(nums):
                res.append(current)
                return
            get_subset(nums, i + 1, current.copy())
            current.append(nums[i])
            get_subset(nums, i + 1, current.copy())
        get_subset(nums, 0, [])
        return res

79. Word Search

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        board_row = len(board)
        board_col = len(board[0])
        def search_exist(board, word, index, used, i, j):
            if index == len(word):
                return True
            up = (i - 1 >= 0) and (board[i - 1][j] == word[index]) and ((i - 1, j) not in used)
            down = (i + 1 < board_row) and (board[i + 1][j] == word[index]) and ((i + 1, j) not in used)
            left = (j - 1 >= 0) and (board[i][j - 1] == word[index]) and ((i, j - 1) not in used)
            right = (j + 1 < board_col) and (board[i][j + 1] == word[index]) and ((i, j + 1) not in used)
            if not (up or down or left or right):
                return False
            if up:
                used.add((i - 1, j))
                up = search_exist(board, word, index + 1, used, i - 1, j)
                used.remove((i - 1, j))
            if down:
                used.add((i + 1, j))
                down = search_exist(board, word, index + 1, used, i + 1, j)
                used.remove((i + 1, j))
            if left:
                used.add((i, j - 1))
                left = search_exist(board, word, index + 1, used, i, j - 1)
                used.remove((i, j - 1))
            if right:
                used.add((i, j + 1))
                right = search_exist(board, word, index + 1, used, i, j + 1)
                used.remove((i, j + 1))
            return up or down or left or right

        for i in range(board_row):
            for j in range(board_col):
                if board[i][j] == word[0] and search_exist(board, word, 1, {(i, j)}, i, j):
                    return True
        return False

96. Unique Binary Search Trees

class Solution:
    def numTrees(self, n: int) -> int:
        res = [0 for i in range(n + 1)]
        res[0], res[1] = 1, 1
        for i in range(2, n + 1):
            tmp_res = 0
            for j in range(0, i):
                tmp_res += res[j] * res[i - j - 1]
            res[i] = tmp_res
        return res[n]

98. Validate Binary Search Tree

class Solution:
    def isValidBST(self, root: TreeNode) -> bool:

        def helper(root, lower, upper):
            if not root:
                return True
            return lower < root.val < upper and helper(root.left, lower, root.val) and helper(root.right, root.val, upper)

        return helper(root, float("-inf"), float("inf"))

101. Symmetric Tree

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:

        def helper(left, right):
            if not left and not right:
                return True
            if left and right:
                return left.val == right.val and \
                helper(left.left, right.right) and \
                helper(left.right, right.left)
            return False

        if not root:
            return True
        return helper(root.left, root.right)

102. Binary Tree Level Order Traversal

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        def level_func(node_list):
            tmp_node_list = []
            for node in node_list:
                if node.left:
                    tmp_node_list.append(node.left)
                if node.right:
                    tmp_node_list.append(node.right)
            return tmp_node_list
        
        if not root:
            return []
        res = []
        tmp_node_list = [root]
        while len(tmp_node_list) > 0:
            res.append([node.val for node in tmp_node_list])
            tmp_node_list = level_func(tmp_node_list)
        return res

104. Maximum Depth of Binary Tree

class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        if not root.left and not root.right:
            return 1
        return max(self.maxDepth(root.left) + 1, self.maxDepth(root.right) + 1)

105. Construct Binary Tree from Preorder and Inorder Traversal

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        #preorder: root left right
        #inorder: left root right
        def build(preorder, inorder, preorder_start_index, preorder_end_index,
                  inorder_start_index, inorder_end_index):
            if preorder_start_index >= preorder_end_index:
                return
            root = TreeNode(preorder[preorder_start_index])
            right_set = set()
            inorder_root_index = 0
            for i in range(inorder_start_index, inorder_end_index):
                if inorder[i] == preorder[preorder_start_index]:
                    inorder_root_index = i
                    right_set = set(inorder[i: inorder_end_index])
                    break
            preorder_right_start_index = preorder_end_index
            for i in range(preorder_start_index + 1, preorder_end_index):
                if preorder[i] in right_set:
                    preorder_right_start_index = i
                    break
            root.left = build(preorder, inorder, preorder_start_index + 1, preorder_right_start_index,
                              inorder_start_index, inorder_root_index)
            root.right = build(preorder, inorder, preorder_right_start_index, preorder_end_index,
                               inorder_root_index, inorder_end_index)
            return root

        root = build(preorder, inorder, 0, len(preorder), 0, len(inorder))
        return root

preorder是root left right,inorder是left root right,所以我们可以通过preorder的第一个root去inorder中找root位置,再找到preorder中right开始的位置,这样重新构建left和right。
看了答案发现有几个可以优化的地方,一个是可以建立index来方便找到位置,另一个是right开始的位置可以通过inorder中root位置得到left长度来回推。

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        index = {elem: i for i, elem in enumerate(inorder)}
        def build(preorder, inorder, preorder_start_index, preorder_end_index,
                  inorder_start_index, inorder_end_index):
            if preorder_start_index >= preorder_end_index:
                return
            root = TreeNode(preorder[preorder_start_index])
            inorder_root_index = index[preorder[preorder_start_index]]
            preorder_right_start_index = inorder_root_index - inorder_start_index + preorder_start_index + 1

            root.left = build(preorder, inorder, preorder_start_index + 1, preorder_right_start_index,
                              inorder_start_index, inorder_root_index)
            root.right = build(preorder, inorder, preorder_right_start_index, preorder_end_index,
                               inorder_root_index + 1, inorder_end_index)
            return root

        root = build(preorder, inorder, 0, len(preorder), 0, len(inorder))
        return root

你可能感兴趣的:(leetcode hot100)