Write in front
After nearly half a month's arrangement, I finally finished the analysis of easy and media topics of the first 100 questions. (The autumn tips have already begun. I wish myself good luck. (Later, I will gradually make up hard in my spare time.)
Articles Catalogue
- 2. Add Two Numbers (Medium)
- 3. Longest Substring Without Repeating Characters (Medium)
- 5. Longest Palindromic Substring (Medium)
- 6. ZigZag Conversion (Medium)
- 8. String to Integer (atoi) (Medium)
- 11. Container With Most Water (Medium)
- 12. Integer to Roman (Medium)
- 15. 3Sum (Medium) **
- 16. 3Sum Closest (Medium)
- 17. Letter Combinations of a Phone Number (Medium)
- 18. 4Sum (Medium)
- 19. Remove Nth Node From End of List (Medium)
- 22. Generate Parentheses (Medium)
- 24. Swap Nodes in Pairs (Medium)
- 29. Divide Two Integers (Medium) X
- 31. Next Permutation (Medium)
- 33. Search in Rotated Sorted Array (Medium)
- 81. Search in Rotated Sorted Array II (Medium)
- 34. Find First and Last Position of Element in Sorted Array (Medium)
- 36. Valid Sudoku (Medium)
- 39. Combination Sum (Medium)
- 40. Combination Sum II (Medium)
- 42. Trapping Rain Water (Hard)
- 43. Multiply Strings (Medium)
- 46. Permutations (Medium)
- 47. Permutations II (Medium)
- 48. Rotate Image (Medium)
- 49. Group Anagrams (Medium)
- 54. Spiral Matrix (Medium)
- 59. Spiral Matrix II (Medium)
- 55. Jump Game (Medium)
- 56. Merge Intervals (Medium)
- 60. Permutation Sequence (Medium)
- 61. Rotate List (Medium)
- 62. Unique Paths (Medium)
- 63. Unique Paths II (Medium)
- 64. Minimum Path Sum (Medium)
- 71. Simplify Path (Medium)
- 73. Set Matrix Zeroes (Medium)
- 74. Search a 2D Matrix (Medium)
- 77. Combinations (Medium)
- 78. Subsets (Medium)
- 90. Subsets II (Medium)
- 79. Word Search (Medium)
- 80. Remove Duplicates from Sorted Array II (Medium)
- 82. Remove Duplicates from Sorted List II (Medium)
- 86. Partition List (Medium)
- 89. Gray Code (Medium)
- 91. Decode Ways (Medium) **
- 92. Reverse Linked List II (Medium)
- 93. Restore IP Addresses (Medium)
- 94. Binary Tree Inorder Traversal (Medium)
- 96. Unique Binary Search Trees (Medium)
- 95. Unique Binary Search Trees II (Medium)
- 98. Validate Binary Search Tree (Medium)
2. Add Two Numbers (Medium)
Topic Description
Add two linked lists
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation: 342 + 465 = 807.
Thoughts on Problem Solving
""" //Similar to merging two linked lists 1. In order l2 The addition of the element of the ___________ to l1 in 2. When a list has been completed, The next thing to do is add up the carry and the rest of the list. 3. When the length of two linked lists is equal, To determine whether the last node value is greater than 10, Possible carry value 4. After traversing all nodes, If carry value still exists, Add a new node """ class Solution: def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: head = l1 carry = 0 while l1 or l2: if l1 and l2: s = l1.val + l2.val + carry l1.val = s%10 carry = s//10 last = l1 # If l1 is empty, refer to l2 as the last node. l1 = l1.next l2 = l2.next elif l1: # l1 is longer than l2 s = l1.val + carry # Completion carry l1.val = s%10 carry = s//10 if carry == 0: # If there is no more carry, the sum is terminated ahead of time. break last = l1 l1 = l1.next elif l2: # l1 is shorter than l2 last.next = l2 s = l2.val + carry l2.val = s%10 carry = s//10 if carry == 0: break last = l2 l2 = l2.next if last.val >= 10: last.val = last.val % 10 carry = 1 if carry: #If carry has value, a new node needs to be added. last.next = ListNode(1) return head
3. Longest Substring Without Repeating Characters (Medium)
https://leetcode.com/problems/longest-substring-without-repeating-characters/
Topic Description
Give a string and return the longest substring without duplicate elements.
Input: "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3.
Thoughts on Problem Solving
""" //Set up a sliding window. //Whether the left boundary will repeat is check ed every time the right boundary slides a position. If the left boundary is repeated, the left boundary slides to the right until the character on the left boundary is not equal to the character on the right boundary position is unknown. //At the end of each move, check the current window length. """ class Solution: def lengthOfLongestSubstring(self, s: str) -> int: if s == '': return 0 start = end = result = 0 while end < len(s): if s[end] not in s[start:end]: end += 1 result = max(result, end-start) else: start = start + s[start:end].find(s[end]) + 1 #return the index of s[end] in s[start:end] end += 1 return result
5. Longest Palindromic Substring (Medium)
Topic Description
Give a string and find the longest palindrome substring.
Input: "babad" Output: "bab" Note: "aba" is also a valid answer.
Thoughts on Problem Solving
""" //Traverse all nodes. 1. From the current node, Traveling to both sides, Until the elements are unequal. Get a palindrome string. 2. check Current palindrome string //Notice the parity length of the original string """ class Solution: def longestPalindrome(self, s: str) -> str: Max = 0 longest = '' for i in range(len(s)): #odd case, like'aba' subStr = self.helper(s, i, i) if len(subStr) >= Max: Max = len(subStr) longest = subStr #even case, like'abba' subStr = self.helper(s, i, i+1) if len(subStr) >= Max: Max = len(subStr) longest = subStr return longest def helper(self, s, start, end): subStr = '' while start >= 0 and end <len(s) and s[start] == s[end]: subStr = s[start:end+1] start -= 1 end += 1 return subStr
6. ZigZag Conversion (Medium)
Topic Description
The string "PAYPALISHIRING" is written in Z-shaped walk and the output is "PAHNAPLSIIGYIR" line by line.
P A H N A P L S I I G Y I R
Design the conversion function.
Thoughts on Problem Solving
# The inverted Z word is stitched together, and the rule of forming Z word is found first. ''' (* *) Although yes z The pattern looks complex, but it's actually simple. The trend is in the order of straight down and inclined upward. * * * Create five storage spaces to store the letters that you walk through each time. * * * * * * * * ''' class Solution: def convert(self, s: str, numRows: int) -> str: # In special cases, the characters are only enough to set the first vertical column. if numRows == 1 or numRows >= len(s): return s L = [''] * numRows index = 0 # Step down, when step=-1, turn back and go up for x in s: L[index] += x if index == 0: step = 1 if index == numRows - 1: step = -1 index += step return ''.join(L)
8. String to Integer (atoi) (Medium)
https://leetcode.com/problems/string-to-integer-atoi/
Topic Description
Thoughts on Problem Solving
class Solution: def myAtoi(self, s: str) -> int: if s == '': return 0 # Remove the space from the string and save it in the list as long as you study the first element of the list. s2 = s.strip().split(' ')[0] # It still needs to be judged once, or it will be wrong. if s2 == '': return 0 flag = 1 num = {'1','2','3','4','5','6','7','8','9','0'} #Save symbols if s2[0] == '-': flag = -1 s2 = s2[1:] elif s2[0] == '+': s2 = s2[1:] # Critical judgment, too important! A single character'+'or'-' if s2 == '': return 0 # The first character is the letter returning 0 if s2[0] not in num: return 0 # If you follow the letters, try to get rid of them. for i in s2: if i not in num: index = s2.index(i) s2 = s2[:index] break s2 = flag * int(s2) if s2 > 2**31 - 1: return 2**31 - 1 elif s2 < -(2**31): return -(2**31) return s2
11. Container With Most Water (Medium)
https://leetcode.com/problems/container-with-most-water/
Topic Description
Given an array, each number represents the length of the partition to determine the maximum volume that can hold water.
Input: [1,8,6,2,5,4,8,3,7] Output: 49
Thoughts on Problem Solving
""" //Short partitions determine the height of the container. //Set up two pointers and move them from the beginning to the middle. 1.If the head pointer is larger than the tail pointer, Then the tail pointer moves to the head. 2.If the head pointer is less than the tail pointer, Then the head pointer moves to the tail.. 3.Every move, check Current volume. """ class Solution: def maxArea(self, height: List[int]) -> int: result = 0 start = 0 end = len(height)-1 while start < end: result = max(result, min(height[start], height[end]) * (end - start)) #Take the two lines in the opposite direction. if height[start] < height[end]: start += 1 else: end -= 1 return result
12. Integer to Roman (Medium)
https://leetcode.com/problems/integer-to-roman/
Topic Description
Convert Roman numerals to decimal numerals.
Thoughts on Problem Solving
class Solution: def intToRoman(self, num: int) -> str: value_roman = {1000:"M", 900:"CM", 500:"D", 400:"CD", 100:"C", 90:"XC", 50:"L", 40:"XL", 10:"X", 9:"IX", 5:"V", 4:"IV", 1:"I"} roman = "" for v in [1000,900,500,400,100,90,50,40,10,9,5,4,1]: roman += value_roman[v] * (num//v) num %= v return roman
15. 3Sum (Medium) **
https://leetcode.com/problems/3sum/
Topic Description
Given an array, find combinations that make sum zero. Combinations cannot be repeated.
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
Thoughts on Problem Solving
""" //dynamic programming //Sort the arrays first. //From scratch, iterate through the elements one by one, with the position i, the left pointer pointing to i+1, and the right pointer pointing to tail. //When the left pointer < the right pointer: 1. Add the values pointed by three pointers. 2. And greater than 0, Explanation and need reduction, Move the right pointer to the left(Because arrays are ordered, The number on the right side is greater than that on the left.) 3. And less than 0, Explanation and need increase. Move the left pointer to the right 4. When sum equals zero, Continue moving the left and right pointers to remove elements that are the same as the current value """ class Solution: def threeSum(self, nums: List[int]) -> List[List[int]]: if len(nums) <3: # deal with special input return [] elif len(nums) == 3: if sum(nums) == 0: return [sorted(nums)] res = [] nums.sort() for i in range(len(nums)-2): if i > 0 and nums[i] == nums[i-1]: continue l, r = i+1, len(nums)-1 while l < r: s = nums[i] + nums[l] + nums[r] if s < 0: l +=1 elif s > 0: r -= 1 else: res.append((nums[i], nums[l], nums[r])) while l < r and nums[l] == nums[l+1]: l += 1 while l < r and nums[r] == nums[r-1]: r -= 1 l += 1; r -= 1 return res
16. 3Sum Closest (Medium)
https://leetcode.com/problems/3sum-closest/
Topic Description
In the same question, just give a target and find the closest value to the target.
Thoughts on Problem Solving
""" //Same question, three pointers. """ class Solution: def threeSumClosest(self, nums, target): nums.sort() res = sum(nums[:3]) for i in range(len(nums)): l, r = i+1, len(nums)-1 while l < r: s = sum((nums[i], nums[l], nums[r])) if abs(s-target) < abs(res-target): res = s if s < target: l += 1 elif s > target: r -= 1 else: # break early return res return res
17. Letter Combinations of a Phone Number (Medium)
https://leetcode.com/problems/letter-combinations-of-a-phone-number/
Topic Description
Input numeric strings, output possible combinations of letters. (Nine Palace keys)
Input: "23" Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
Thoughts on Problem Solving
recursion
""" """ class Solution: def letterCombinations(self, digits: str) -> List[str]: if digits == "": return [] mapp = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'} res = [] self.combinate(digits, mapp, 0, len(digits), '', res) return res def combinate(self, s, mapp, n, m, path, res): if n == m: res.append(path) return for i in mapp[s[n]]: self.combinate(s, mapp, n+1, m, path+i, res)
Non-recursive approach
class Solution: def letterCombinations(self, digits: str) -> List[str]: pad = { '2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz' } if not digits: return [] output = [''] for digit in digits: temp = output output = [] for s in temp: output.extend([s + pad[digit][0], s + pad[digit][1], s+ pad[digit][2]]) if digit == '7' or digit == '9': output.append(s + pad[digit][3]) return output
18. 4Sum (Medium)
https://leetcode.com/problems/4sum/
Topic Description
With 3Sum, it's just four numbers and zero.
Thoughts on Problem Solving
""" 3Sum Expansion //Pass 0-current number as target into 3Sum function in 4Sum """ class Solution: def fourSum(self, nums, target): results = [] nums.sort() for i in range(len(nums)-3): if i == 0 or nums[i] != nums[i-1]: threeResult = self.threeSum(nums[i+1:], target-nums[i]) for item in threeResult: results.append([nums[i]] + item) return results def threeSum(self, nums, target): results = [] nums.sort() for i in range(len(nums)-2): l = i + 1; r = len(nums) - 1 t = target - nums[i] if i == 0 or nums[i] != nums[i-1]: while l < r: s = nums[l] + nums[r] if s == t: results.append([nums[i], nums[l], nums[r]]) while l < r and nums[l] == nums[l+1]: l += 1 while l < r and nums[r] == nums[r-1]: r -= 1 l += 1; r -=1 elif s < t: l += 1 else: r -= 1 return results ==
19. Remove Nth Node From End of List (Medium)
https://leetcode.com/problems/remove-nth-node-from-end-of-list/
Topic Description
Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.
Thoughts on Problem Solving
""" //Creating one or two pointers can solve the problem of finding reciprocal nodes. """ class Solution: def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode: dummy = ListNode(0) dummy.next = head fast, slow = dummy, dummy for i in range(n+1): fast = fast.next while fast: fast, slow = fast.next, slow.next slow.next = slow.next.next return dummy.next
22. Generate Parentheses (Medium)
https://leetcode.com/problems/generate-parentheses/
Topic Description
Given n n n pairs of parentheses, output all possible legitimate combinations.
For example, given n = 3, a solution set is:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
Thoughts on Problem Solving
recursion
class Solution: def generateParenthesis(self, n: int) -> List[str]: combos = [] left = n right = n path = '' self.formParen(left,right,path,combos) return combos def formParen(self,left,right,path,combos): # The left and right parentheses are used up at the same time, and the currently generated path is added to combos. if left == 0 and right == 0: combos.append(path) # When the left parentheses are exhausted, complete all the right parentheses. elif left == 0: combos.append(path+')'*right) # The left and right parentheses in front are paired, only the left parentheses can be used. elif right == left: self.formParen(left-1,right,path+'(',combos) # else: self.formParen(left-1,right,path+'(',combos) self.formParen(left,right-1,path+')',combos)
24. Swap Nodes in Pairs (Medium)
https://leetcode.com/problems/swap-nodes-in-pairs/
Topic Description
Given a linked list, swap every two adjacent nodes and return its head.
Given 1->2->3->4, you should return the list as 2->1->4->3.
Thoughts on Problem Solving
""" You need to be familiar with what the pointer points to. last p1 p2 Before moving: dummy - > 1 - > 2 - > 3 - > 4 - > None last p1 p2 After moving: dummy (last) - > 2 (p2) - > 1 (p1) - > 3 - > 4 - > None (Brackets indicate the last position of the pointer) Each operation needs to move three pointers, temp is the original P2 pointing to content, P2 pointing to p1, p1 pointing to temp, last pointing to p2. Each time the node is moved, it needs to update p1, p2, last """ class Solution: def swapPairs(self, head: ListNode) -> ListNode: if head == None: return if head.next == None: return head cur1, cur2 = head, head.next dummy = ListNode(0) last = dummy last.next = cur1 while cur1: temp = cur2.next cur2.next = cur1 cur1.next = temp last.next = cur2 last = cur1 cur1 = cur1.next if not cur1 or not cur1.next: break else: cur2 = cur1.next return dummy.next
29. Divide Two Integers (Medium) X
https://leetcode.com/problems/divide-two-integers/
Topic Description
Divide two numbers, you can't use multiplication, division, modulus.
Thoughts on Problem Solving
31. Next Permutation (Medium)
https://leetcode.com/problems/next-permutation/
Topic Description
The next permutation is that there can be no other number between the current number and the next number.
Thoughts on Problem Solving
""" //Primary arrangement: 7 8 6 9 8 7 2 //Next: 7 8 7 2 6 8 9 //No arrangement between the two permutations can be found. //Assume that the array size is n 1.From back to front, Find the first A[i-1] < A[i]Of. That's the position of six in the first permutation, and you can see it. A[i]reach A[tail]These are monotonic decreasing sequences.. 2.stay A[i:tail]Find the ratio in the middle A[i-1]The smallest of the largest values. such as[9 8 7 2]7.. 3.Exchange these two values, And A[i:tail]sort, From small to large. """ class Solution: def nextPermutation(self, nums: List[int]) -> None: for i in range(len(nums)-1, 0, -1): if nums[i] > nums[i-1]: nums[i:] = sorted(nums[i:]) for j in range(i, len(nums)): if nums[j] > nums[i-1]: temp = nums[j] nums[j] = nums[i-1] nums[i-1] = temp return nums.sort()
33. Search in Rotated Sorted Array (Medium)
https://leetcode.com/problems/search-in-rotated-sorted-array/
Topic Description
A non-repetitive incremental array rotates at a certain position, returns its index value given a number.
Time complexity O(logn) is required.
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
Thoughts on Problem Solving
""" //Binary search finds the minimum. The minimum is the rotation point. An offset is obtained. //Reuse binary lookup. Each mid needs offset correction to get realMid and compare it with target. """ class Solution: def search(self, nums: List[int], target: int) -> int: left, right = 0, len(nums)-1 while left < right: mid = (left + right)//2 if nums[mid] > nums[right]: left = mid + 1 else: right = mid # when finish the while, we get left == right offset = left left, right = 0, len(nums)-1 while left <= right: mid = (left + right)//2 realMid = (mid + offset)%len(nums) if nums[realMid] == target: return realMid if nums[realMid] < target: left = mid + 1 else: right = mid - 1 return -1
81. Search in Rotated Sorted Array II (Medium)
https://leetcode.com/problems/search-in-rotated-sorted-array-ii/
Topic Description
With the expansion of 30 questions, there may be duplicate numbers in the array.
Thoughts on Problem Solving
The train of thought turns from: Detailed ideas and differences with Search in Rotated Sorted Array I (python code)
The difference between this question and "Search Rotary Sort Array I" is that it needs to be preprocessed when judging the middle position of mid:
while low < high and nums[low] == nums[high]: low += 1
This also causes the worst time complexity of the algorithm to become O(n). Whole or Binary Search
At the same time, I optimize the classification method based on I: first, determine the mid location (high or low), and further determine whether the target location is in a specific range (so-called specific range refers to the binary search range similar to the normal sort) directly into four categories.
python knowledge points: 2 < x < 3 can be written directly in python without disassembly
Code:
class Solution: def search(self, nums, target): if not nums: return False low = 0 high = len(nums) - 1 while low <= high: while low < high and nums[low] == nums[high]:#The aim is to accurately determine the mid position, so the worst time complexity of the algorithm is O(n). low += 1 mid = (low+high)//2 if target == nums[mid]: return True elif nums[mid] >= nums[low]: #Patricia Lee Gauch if nums[low] <= target < nums[mid]: high = mid - 1 else: low = mid + 1 elif nums[mid] <= nums[high]: #Low area if nums[mid] < target <= nums[high]: low = mid + 1 else: high = mid - 1 return False
34. Find First and Last Position of Element in Sorted Array (Medium)
https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
Topic Description
Given an incremental sequence, find the starting and ending positions of a given target (target repeated and continuous). There is no return [-1,-1]. Require time complexity O(logN)
Input: nums = [5,7,7,8,8,10], target = 8 Output: [3,4]
Thoughts on Problem Solving
""" //Both start and end bits use binary lookup. Note here that mid = right, when nums[mid] = nums[right], the final output position is right, right remains unchanged. //Find the location of the target for the first time. //The second lookup, target+1, yields two end s target = 1 1. [0,1,1] target+1 Location does not exist, What you get is the last position 2 2. [0,1,1,3] target+1 Location does not exist, But the last one exists and is greater than 1., This will return to position 2. 3. [0,1,1,2] target+1 Location exists, Return 3 """ class Solution: def searchRange(self, nums: List[int], target: int) -> List[int]: start = self.binarySearch(nums, target) if start == len(nums) or nums[start] != target: return [-1,-1] end = self.binarySearch(nums,target+1) if nums[end] > nums[start]: end -= 1 return [start, end] def binarySearch(self, nums, target): left, right = 0, len(nums)-1 while left < right: mid = (left + right) // 2 if nums[mid] < target: left = mid + 1 else: right = mid return left
36. Valid Sudoku (Medium)
https://leetcode.com/problems/valid-sudoku/
Topic Description
Input: [ ["5","3",".",".","7",".",".",".","."], ["6",".",".","1","9","5",".",".","."], [".","9","8",".",".",".",".","6","."], ["8",".",".",".","6",".",".",".","3"], ["4",".",".","8",".","3",".",".","1"], ["7",".",".",".","2",".",".",".","6"], [".","6",".",".",".",".","2","8","."], [".",".",".","4","1","9",".",".","5"], [".",".",".",".","8",".",".","7","9"] ] Output: true
Thoughts on Problem Solving
""" //Effective Sudoku requires three points: 1. Each row contains 1-9 And without repetition: row = set() 2. Each column contains 1-9 And without repetition: col = set() 3. Each 3*3 cube Contains 1-9 And without repetition cube = set() //Every time you encounter a number, put (cur, i) in row, (j, cur) in col, (i//3, j//3, cur) in cube. //The location//3 of each cell in a 3*3 nine-grid is the same, so we can get the "nine-grid coordinates" from it. There can be no duplicate numbers in the coordinates. """ class Solution: def isValidSudoku(self, board: List[List[str]]) -> bool: row = set() col = set() cube = set() for i in range(9): for j in range(9): if board[i][j] != '.': cur = board[i][j] if (i, cur) in row or (cur, j) in col or (i//3, j//3, cur) in cube: #i//3,j//3 so that all 3X3 squares can have their own coordinates. remember! return False row.add((i, cur)) col.add((cur, j)) cube.add((i//3, j//3, cur)) return True
39. Combination Sum (Medium)
https://leetcode.com/problems/combination-sum/
Topic Description
Give a collection and find all combinations that are target ed.
ps. All numbers are positive and do not repeat
Input: candidates = [2,3,6,7], target = 7, A solution set is: [ [7], [2,2,3] ]
Thoughts on Problem Solving
recursion
""" //recursive thinking //Each time the tar value of the incoming helper decreases, when it is 0, put the path that comes all the way into res """ class Solution: def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: res = [] self.helper(candidates, target, [], res) return res def helper(self, candi, tar, path, res): if tar == 0: # Preventing duplication if sorted(path) not in res: res.append(sorted(path)) return # The sum result is less than 0, the path is invalid if tar < 0: return for i in candi: self.helper(candi, tar-i, path+[i], res)
40. Combination Sum II (Medium)
https://leetcode.com/problems/combination-sum-ii/
Topic Description
Give an array and find all the combinations with target.
ps. All numbers are positive and do not repeat
Input: candidates = [10,1,2,7,6,1,5], target = 8, A solution set is: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
Thoughts on Problem Solving
class Solution: def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]: res = [] self.helper(candidates, target, [], res) return res def helper(self, candi, tar, path, res): if tar == 0: # Preventing duplication if sorted(path) not in res: res.append(sorted(path)) return # The sum result is less than 0, the path is invalid if tar < 0: return for i in range(len(candi)): # Save running time, if the element in candidate is larger than the current remaining target, it is not considered directly if candi[i] > tar: continue self.helper(candi[:i]+candi[i+1:], tar-candi[i], path+[candi[i]], res)
42. Trapping Rain Water (Hard)
The stack is used to compare the current bar with the bar at the top of the stack. If the bar is smaller than the top of the stack, the new bar will be put on the stack. Otherwise, the water storage of the current bar and the bar at the top of the stack will be calculated. Then the stack will be pushed out and the comparison will be repeated until the current bar is smaller than the top or empty of the stack. At this time, the current bar will enter the stack. It ends when there is no new current bar.
The algorithm is as follows:
- Store bar's index with stack (1)
- Traversal array (2)
- When stack is not empty or height [cur] > height [stack. top] (2.1)
- Top the stack out of the stack (2.1.1)
- Calculate the distance of current index and stack top index (2.1.2)
- Calculating the water storage between height[height] and height[stack.top] depends on the smaller of the previous bar and current bar of stack.top (2.1.3)
- Preservation of Water Storage Value (2.1.4)
- Currbar stacking (2.2)
- get a new current bar (2.3)
https://leetcode.com/problems/trapping-rain-water/
- When stack is not empty or height [cur] > height [stack. top] (2.1)
class Solution: def trap(self, height) -> int: ans = 0 cur = 0 stack = [] #(1) while cur < len(height): #(2) while stack and height[cur] > height[stack[-1]]:#(2.1) top = stack.pop() #(2.1.1) if(not stack): break distance = cur - stack[-1] - 1 #(2.1.2) high = min(height[cur], height[stack[-1]])-height[top] #(2.1.3) ans += (distance * high) #(2.1.4) stack.append(cur) #(2.2) cur += 1 #(2.3) return ans
43. Multiply Strings (Medium)
https://leetcode.com/problems/multiply-strings/
Topic Description
Multiplication of two strings results in the output of strings
Input: num1 = "2", num2 = "3" Output: "6"
Thoughts on Problem Solving
Java
"" //Use built-in functions quickly but interview is not recommended. //Using the most basic vertical multiplication. "" class Solution { public String multiply(String num1, String num2) { int len1 = num1.length(), len2 = num2.length(); int carry = 0; int[] pos = new int[len1 + len2]; // num1 is down, num2 is up for(int i=len1-1; i >= 0; i--){ for(int j=len2-1; j>=0; j--){ int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0'); int p1 = i + j, p2 = i + j + 1; int sum = mul + pos[p2]; pos[p2] = sum % 10; // Number position pos[p1] += sum / 10; } } StringBuilder sb = new StringBuilder(); for(int p : pos) if(!(sb.length() == 0 && p == 0)) sb.append(p); return sb.length() == 0 ? "0" : sb.toString(); } }
46. Permutations (Medium)
https://leetcode.com/problems/permutations/
Topic Description
Given an array, output all possible permutations. There are no duplicate characters in the array.
Input: [1,1,2] Output: [ [1,1,2], [1,2,1], [2,1,1] ]
Thoughts on Problem Solving
Method 1: Recursion
class Solution: def permuteUnique(self, nums: List[int]) -> List[List[int]]: res = [] self.merge(nums, [], res) return res def merge(self, nums, path, res): if nums == []: if path not in res: res.append(path) return for i in range(len(nums)): # Remove the number of position i and add path self.merge(nums[:i]+nums[i+1:], path+[nums[i]], res)
non-recursive
class Solution: def permuteUnique(self, nums: List[int]) -> List[List[int]]: ans = [[]] # for n in nums: new_ans = [] # Remove each list in ans and insert n at all insertible locations in each list for arr in ans: # For each arr in ans, there is len(arr)+1 position to fill in n # When len(arr)==0, there is only one position. That is [n]. for i in range(len(arr)+1): new_ans.append(arr[:i]+[n]+arr[i:]) ans = new_ans return ans
47. Permutations II (Medium)
https://leetcode.com/problems/permutations-ii/
Method 1: Recursion
class Solution: def permuteUnique(self, nums: List[int]) -> List[List[int]]: res = [] self.merge(nums, [], res) return res def merge(self, nums, path, res): if nums == []: if path not in res: res.append(path) return for i in range(len(nums)): # Remove the number of position i and add path self.merge(nums[:i]+nums[i+1:], path+[nums[i]], res)
non-recursive
Just one if I < len (arr) and arr [i]==n: break was added to the previous question.
""" It should be noted here that there are repetitive elements in the processing of permutation, which causes the problem of getting repetitive permutation. The solution is that when you first encounter a duplicate element, place the duplicate element you encounter in front of the existing element, and then jump out of the loop. Prevent repetitive elements from rearranging to other positions of existing elements. For example, [1,1,2,1], after one round, [[1], The second round starts with a 1, which is put at the front, and then break s the loop. Then you may encounter a 1 and do the same. Initialization ans=[[]] In turn, the elements n in nums are removed: In turn, each list in the pre-existing ans is taken out: Insert n at insertible locations in each list If the current insertible location element equals n, break loops to prevent element duplication Add all the resulting permutations to the ans """ class Solution: def permuteUnique(self, nums: List[int]) -> List[List[int]]: ans = [[]] # for n in nums: new_ans = [] # Remove each list in ans and insert n at all insertible locations in each list for arr in ans: # For each arr in ans, there is len(arr)+1 position to fill in n # When len(arr)==0, there is only one position. That is [n]. for i in range(len(arr)+1): new_ans.append(arr[:i]+[n]+arr[i:]) # handles duplication # If this cycle adds duplicate numbers, place them at the beginning and break them. if i<len(arr) and arr[i]==n: break ans = new_ans return ans
48. Rotate Image (Medium)
https://leetcode.com/problems/rotate-image/
Topic Description
Given an n*n matrix, the output matrix rotates 90 degrees clockwise.
Given input matrix = [ [1,2,3], [4,5,6], [7,8,9]], rotate the input matrix in-place such that it becomes: [ [7,4,1], [8,5,2], [9,6,3]]
Thoughts on Problem Solving
""" clockwise rotate first reverse up to down, then swap the symmetry 1 2 3 7 8 9 7 4 1 4 5 6 => 4 5 6 => 8 5 2 7 8 9 1 2 3 9 6 3 """ class Solution: def rotate(self, matrix: List[List[int]]) -> None: matrix.reverse() for i in range(len(matrix)): for j in range(i+1, len(matrix[0])): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
49. Group Anagrams (Medium)
https://leetcode.com/problems/group-anagrams/
Topic Description
Given an array containing strings, group all strings containing the same letters.
Input: ["eat", "tea", "tan", "ate", "nat", "bat"], Output: [ ["ate","eat","tea"], ["nat","tan"], ["bat"] ]
Thoughts on Problem Solving
""" //Use dictionaries to improve retrieval efficiency. //Each word is sorted alphabetically to get string as key. """ class Solution: def groupAnagrams(self, strs: List[str]) -> List[List[str]]: dic = {} for word in strs: key = ''.join(sorted(word)) if key not in dic: dic[key] = [word] else: dic[key].append(word) ans = [] for key in dic.keys(): ans.append(dic[key]) return ans
54. Spiral Matrix (Medium)
https://leetcode.com/problems/spiral-matrix/
Topic Description
Give an array of mxn, spiral output.
Input: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] Output: [1,2,3,6,9,8,7,4,5]
Thoughts on Problem Solving
Note:
If you use the string'right'to mark direction, you should pay attention to that strings are immutable objects like tuples, so you can't use direct = left to assign values, but use direct = direct.replace('right','right') to change values. It's troublesome, so you still use integers to represent parties. Xiang.
""" //The program is mainly divided into three modules: 1. visit Current Point: //If the current point is not explored, output to res, mark that point has not been explored. //If the current point has been explored, turn and return the coordinates to the previous point. 2. To turn to: //There's nothing to tell 3. Go one step ahead, Encounter boundary turning: //Change the coordinates according to the current direction. If you encounter a boundary, turn and change the coordinates. //Exploration termination condition: when res length equals the number of digits in matrix. """ class Solution: def spiralOrder(self, matrix): # four direction right->down->left-> up -> roop # 0 -> 1 -> 2 -> 3 -> roop if len(matrix) == 0: return [] if len(matrix) == 1: return matrix[0] direct = 0 x, y, lastX, lastY= 0, 0, 0, 0 row, col= len(matrix), len(matrix[0]) res = [] while len(res) < row * col: # The flag'x'indicates that it has passed. # Go straight. if matrix[x][y] != 'x': res.append(matrix[x][y]) matrix[x][y] = 'x' elif matrix[x][y] == 'x': # turn the direction direct = self.turnDirect(direct) # Now that the current point has been explored, go back to the previous point x, y = lastX, lastY # Go in one direction. # If you go right to the end, y can't + 1, instead go down, x+1 lastX, lastY = x, y x, y, direct = self.walk(x, y, row, col, direct) return res def turnDirect(self, direct): if direct == 0: return 1 elif direct == 1: return 2 elif direct == 2: return 3 elif direct == 3: return 0 def walk(self, x, y, row, col, direct): if direct == 0: y += 1 if y == n: y -= 1 direct = 1 x += 1 elif direct == 1: x += 1 if x == row: x -= 1 direct = 2 y -= 1 elif direct == 2: y -= 1 if y < 0: y += 1 direct = 3 x -= 1 elif direct == 3: x -= 1 if x < 0: x += 1 direct = 0 y += 1 return x, y, direct
59. Spiral Matrix II (Medium)
https://leetcode.com/problems/spiral-matrix-ii/
Topic Description
Input n, output corresponding N*N spiral array.
Input: 3 Output: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
Thoughts on Problem Solving
Python's two-dimensional group suggests using a list generator: matrix = [[0 for I I N range (n)] for J in range (n)].
""" //Similar to the previous question. //Just change the input two-dimensional array into an all-zero array, change the current value when encountering zero, and turn direction when encountering non-zero. //The rest is no different. """ class Solution: def generateMatrix(self, n: int) -> List[List[int]]: if n == 0: return [] if n == 1: return [[1]] matrix = [[0 for i in range(n)] for j in range(n)] self.spiralOrder(matrix) return matrix def spiralOrder(self, matrix): # four direction right->down->left-> up -> roop # 0 -> 1 -> 2 -> 3 -> roop direct = 0 x, y, lastX, lastY= 0, 0, 0, 0 n = len(matrix) res = [] num = 1 while num <= n * n: # The flag'x'indicates that it has passed. # Go straight. if matrix[x][y] == 0: matrix[x][y] = num num += 1 elif matrix[x][y] != 0: # turn the direction direct = self.turnDirect(direct) # Now that the current point has been explored, go back to the previous point x, y = lastX, lastY # Go in one direction. # If you go right to the end, y can't + 1, instead go down, x+1 lastX, lastY = x, y x, y, direct = self.walk(x, y, n, direct) def turnDirect(self, direct): if direct == 0: return 1 elif direct == 1: return 2 elif direct == 2: return 3 elif direct == 3: return 0 def walk(self, x, y, n, direct): if direct == 0: y += 1 if y == n: y -= 1 direct = 1 x += 1 elif direct == 1: x += 1 if x == n: x -= 1 direct = 2 y -= 1 elif direct == 2: y -= 1 if y < 0: y += 1 direct = 3 x -= 1 elif direct == 3: x -= 1 if x < 0: x += 1 direct = 0 y += 1 return x, y, direct
55. Jump Game (Medium)
https://leetcode.com/problems/jump-game/
Topic Description
Thoughts on Problem Solving
You can use recursion to solve the problem in the same way as before. But here it will be overtime.
""" //Time complexity O(N), traverse the array once. As long as it can satisfy the need to skip all 0. //Think of how far you can jump per grid as how much energy you can store up. Reduce energy by 1 per grid, if you can jump before you reach the end. energy For 0, Represents failure. This reduces the energy and does not increase when you go to zero., 0 If the number of lattices is greater than or equal to //The energy reserved in the past means that it will be exhausted. """ class Solution: def canJump(self, nums): if len(nums) == 1: return True if nums[0] == 0: return False energy = nums[0] for i in range(1,len(nums)): energy -= 1 if nums[i] != 0 and energy < nums[i]: energy= nums[i] if energy == 0 and i != len(nums)-1: return False return True
56. Merge Intervals (Medium)
https://leetcode.com/problems/merge-intervals/
Similar topics
https://blog.csdn.net/bigtree_3721/article/details/89911532
Topic Description
Give a collection containing intervals and merge all duplicate intervals.
Input: [[1,3],[2,6],[8,10],[15,18]] Output: [[1,6],[8,10],[15,18]] Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
Thoughts on Problem Solving
# Definition for an interval. # class Interval: # def __init__(self, s=0, e=0): # self.start = s # self.end = e # Learn to use lambda to sort elements first class Solution: def merge(self, intervals: List[Interval]) -> List[Interval]: if len(intervals) == 0: return [] # Sort by start value intervals = sorted(intervals, key = lambda x: x.start) res = [intervals[0]] for i in intervals[1:]: # If the starting point of i is less than the end point of res[-1], the end point of res[-1] is the end point of i and the maximum of itself. if i.start <= res[-1].end : res[-1].end = max(res[-1].end, i.end) else: res.append(i) return res
60. Permutation Sequence (Medium)
https://leetcode.com/problems/permutation-sequence/
Topic Description
Thoughts on Problem Solving
Briefly take (n,k) = (4,21) for example, in the first iteration we divide the solution set into 4 groups: "1xxx", "2xxx", "3xxx", and "4xxx", while each group has 3! = 6 members.
From 21/6 = 3...3, we know that the 21th element is the 3rd element in the (3+1)th group. In this group, we can divide it into 3 sub-groups again: "41xx", "42xx" and "43xx", and each group has 2!=2 members.
Then, we calculate 3/2 and get 1...1, so it's the 1st element of (1+1)nd sub-group - "421x", and now it reach the base case with only one possibility - "4213".
Anyone pass the problem with different ideas?
class Solution: # @return a string def getPermutation(self, n, k): ll = [str(i) for i in range(1,n+1)] # build a list of ["1","2",..."n"] divisor = 1 for i in range(1,n): # calculate 1*2*3*...*(n-1) divisor *= i answer = "" while k>0 and k<=divisor*n: # there are only (divisor*n) solutions in total group_num = k//divisor k %= divisor if k>0: # it's kth element of (group_num+1)th group choose = ll.pop(group_num) answer += choose else: # it's last element of (group_num)th group choose = ll.pop(group_num-1) answer += choose ll.reverse() # reverse the list to get DESC order for the last element to_add = "".join(ll) answer += to_add break divisor //= len(ll) return answer
61. Rotate List (Medium)
https://leetcode.com/problems/rotate-list/
Topic Description
Given a linked list, rotate the list to the right by k places, where k is non-negative.
Example 1:
Input: 1->2->3->4->5->NULL, k = 2 Output: 4->5->1->2->3->NULL Explanation: rotate 1 steps to the right: 5->1->2->3->4->NULL rotate 2 steps to the right: 4->5->1->2->3->NULL
Thoughts on Problem Solving
""" //Inspired by previous 24. Swap Nodes in Pairs. low, fast Pointer, fast Advance k Location, When fast By the end, Stop traversal. //At this point [low:fast] is a list that needs to be moved. //Move to the head of the list. """ class Solution: def rotateRight(self, head: ListNode, k: int) -> ListNode: if head == None: return None node = head lenth = 0 while node: node = node.next lenth += 1 dummy = ListNode(0) dummy.next = head low, fast = head, head pre = k % lenth if pre == 0: return head for i in range(pre): fast = fast.next while fast.next: low = low.next fast = fast.next dummy = ListNode(0) dummy.next = low.next fast.next = head low.next = None return dummy.next
62. Unique Paths (Medium)
https://leetcode.com/problems/unique-paths/
Topic Description
Given an m*n chessboard, robots are only allowed to walk right and down. There are several ways to get to the end.
This is a 7x3 chessboard, m=7, n=3
Example: Input: m = 3, n = 2 Output: 3 Explanation: From the top-left corner, there are a total of 3 ways to reach the bottom-right corner: 1. Right -> Right -> Down 2. Right -> Down -> Right 3. Down -> Right -> Right
Thoughts on Problem Solving
The time complexity of recursive violent solution is too high to be compiled. Using a two-dimensional array lab, the values indicate how many ways to reach the current coordinates in the graph.
The walking number of each lattice is equal to the sum of the walking number of one lattice on the left and one lattice on the top. It is similar to frog jumping.
""" """ class Solution: def uniquePaths(self, m, n): if not m or not n: # M x n matrix, m is x column number, n is y row number return 0 # By default, the first column, the first line of the method is 1 (only one way to go). lab = [[1 for i in range(m)] for j in range(n)] # So traverse the subscripts from 1, skipping the first column of the first row. for i in range(1, n): for j in range(1, m): lab[i][j] = lab[i-1][j] + lab[i][j-1] #The number of methods to reach each lattice is the sum of the first two lattices. return lab[-1][-1]
63. Unique Paths II (Medium)
https://leetcode.com/problems/unique-paths-ii/
Topic Description
Given an m*n chessboard, where there is an obstacle somewhere, the robot is only allowed to go right and down. There are several ways to get to the end.
Example: Input: [ [0,0,0], [0,1,0], [0,0,0] ] Output: 2 Explanation: There is one obstacle in the middle of the 3x3 grid above. There are two ways to reach the bottom-right corner: 1. Right -> Right -> Down -> Down 2. Down -> Down -> Right -> Right
Thoughts on Problem Solving
class Solution: def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: if not obstacleGrid: return 0 n = len(obstacleGrid) m = len(obstacleGrid[0]) # Setting the number of all lattice methods to 1 does not mean that the default first row and first column of the previous question is a way of walking. # Because obstacles may appear in the first row or column. All lattices are set to zero. lab = [[0 for i in range(m)] for j in range(n)] for i in range(n): for j in range(m): # If the first case is not an obstacle, set it to 1. if i == 0 and j == 0 and obstacleGrid[i][j] != 1: lab[i][j] = 1 continue # If the coordinate map is an obstacle, the current method number is set at 0. if obstacleGrid[i][j] == 1: lab[i][j] = 0 else: # Pay attention to boundary conditions. if i - 1 < 0: lab[i][j] = lab[i][j-1] elif j - 1 < 0: lab[i][j] = lab[i-1][j] else: lab[i][j] = lab[i-1][j] + lab[i][j-1] #The number of methods to reach each lattice is the sum of the first two lattices. return lab[-1][-1]
64. Minimum Path Sum (Medium)
https://leetcode.com/problems/minimum-path-sum/
Topic Description
It's a bit like a robot walking on a chessboard. Given an m*n chessboard, go from left to right and find the minimum path.
Input: [ [1,3,1], [1,5,1], [4,2,1] ] Output: 7 Explanation: Because the path 1→3→1→1→1 minimizes the sum.
Thoughts on Problem Solving
""" //The way to solve the problem is the same, but lab does not store the total number of methods, but the minimum sum accumulated at the current point. lab[i][j] = min(lab[i-1][j], lab[i][j-1]) """ # You can modify it directly at grid without opening up a two-dimensional array of lab. class Solution: def minPathSum(self, grid: List[List[int]]) -> int: if not grid: return 0 n = len(grid) m = len(grid[0]) # A two-dimensional array that holds the minimum sum currently available. lab = [[0 for i in range(m)] for j in range(n)] for i in range(n): for j in range(m): if i == 0 and j == 0: lab[i][j] = grid[i][j] continue # Pay attention to boundary conditions. if i - 1 < 0: lab[i][j] = grid[i][j] + lab[i][j-1] elif j - 1 < 0: lab[i][j] = grid[i][j] + lab[i-1][j] else: lab[i][j] = grid[i][j] + min(lab[i-1][j],lab[i][j-1]) #The number of methods to reach each lattice is the sum of the first two lattices. return lab[-1][-1]
71. Simplify Path (Medium)
https://leetcode.com/problems/simplify-path/
Topic Description
Example 1: Input: "/home/" Output: "/home" Explanation: Note that there is no trailing slash after the last directory name. Example 2: Input: "/../" Output: "/" Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go. Example 3: Input: "/home//foo/" Output: "/home/foo" Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one. Example 4: Input: "/a/./b/../../c/" Output: "/c" Example 5: Input: "/a/../../b/../c//.//" Output: "/c" Example 6: Input: "/a//b////c/d//././/.." Output: "/a/b/c"
Thoughts on Problem Solving
Note:
Symbols other than numbers or letters (spaces, semicolons, etc.) are all False.
isalnum() must be a mixture of numbers and letters
isalpha() is case-insensitive
class Solution: def simplifyPath(self, path): # Save the file directory with the stack. stack = [] for token in path.split('/'): # The empty character "" appears after split ting the array. if token in ('', '.'): pass elif token == '..': if stack: stack.pop() else: stack.append(token) return '/' + '/'.join(stack)
73. Set Matrix Zeroes (Medium)
https://leetcode.com/problems/set-matrix-zeroes/
Topic Description
Given an m*n matrix, if it is at a position of 0, then all rows and columns are set at 0.
Do it in-place.
Thoughts on Problem Solving
Note:
in-place algorithm does not depend on additional resources or a few additional resources, but only on output to cover the input of an algorithm operation.
""" //Similar to the question of number of islands. If you encounter zero, you can't immediately change the rank to zero, which will affect the follow-up judgment. //All you need to do is "mark" it. After you finish the first round of traversal, go through the array again, and put everything in it. //Change the number marked to 0. """ class Solution: def setZeroes(self, matrix: List[List[int]]) -> None: height = len(matrix) if(height ==0): return width = len(matrix[0]) for i in range(height): for j in range(width): if matrix[i][j] == 0: for tmp in range(height): if matrix[tmp][j] != 0: matrix[tmp][j] = None for tmp in range(width): if matrix[i][tmp] != 0: matrix[i][tmp] = None for i in range(height): for j in range(width): if matrix[i][j] == None: matrix[i][j] = 0
74. Search a 2D Matrix (Medium)
https://leetcode.com/problems/search-a-2d-matrix/
Topic Description
Find target in an ordered two-dimensional array.
Input: matrix = [ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ] target = 3 Output: true
Thoughts on Problem Solving
""" //Dichotomy is the first method to find + order, which has low time complexity. //In a multi-step transformation, mid is converted to index, where m is the number of rows in a two-dimensional array. midi = mid // m midj = mid % m //The rest is no different. """ class Solution: def searchMatrix(self, matrix: List[List[int]], target: int) -> bool: n = len(matrix) if n == 0: return False m = len(matrix[0]) if m == 0: return False left, right= 0, m * n - 1 while left <= right: mid = (left + right)//2 # get the real index of mid in 2D array. midi = mid // m midj = mid % m if matrix[midi][midj] > target: right = mid - 1 elif matrix[midi][midj] < target: left = mid + 1 if matrix[midi][midj] == target: return True return False
77. Combinations (Medium)
https://leetcode.com/problems/combinations/
Topic Description
Given two integers n and k return all possible combinations of k numbers out of 1 ... n. Example: Input: n = 4, k = 2 Output: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
Thoughts on Problem Solving
""" //The idea of universal dfs can also be used. But the time efficiency is too low. """ class Solution: def combine(self, n, k): res = [] self.dfs(range(1,n+1), k, 0, [], res) return res def dfs(self, nums, k, index, path, res): #if k < 0: #backtracking #return if k == 0: res.append(path) return # backtracking for i in range(index, len(nums)): self.dfs(nums, k-1, i+1, path+[nums[i]], res)
78. Subsets (Medium)
https://leetcode.com/problems/subsets/
Topic Description
Thoughts on Problem Solving
class Solution: def subsets(self, nums): nums.sort() result = [[]] for num in nums: result += [i + [num] for i in result] return result
90. Subsets II (Medium)
https://leetcode.com/problems/subsets-ii/
Topic Description
In the same question, only repetitive elements may exist in the given array.
Thoughts on Problem Solving
Method 1: The method is the same as the previous one. It is time-consuming to judge whether a list is repeated or not.
class Solution: def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: nums.sort() result = [[]] for num in nums: for j in [i + [num] for i in result]: if j not in result: result.append(j) return result
Method 2: Use DFS to do it.
# DFS def subsetsWithDup(self, nums): res = [] nums.sort() self.dfs(nums, 0, [], res) return res def dfs(self, nums, index, path, res): res.append(path) for i in range(index, len(nums)): if i > index and nums[i] == nums[i-1]: continue self.dfs(nums, i+1, path+[nums[i]], res)
79. Word Search (Medium)
https://leetcode.com/problems/word-search/
Topic Description
Thoughts on Problem Solving
""" search grid type, dfs Explore multiple directions, Recursive call, When touching the boundary or meeting the requirement, the current recursion ends. """ class Solution: def exist(self, board, word): if not board: return False for i in range(len(board)): for j in range(len(board[0])): if self.dfs(board, i, j, word): return True return False # check whether can find word, start at (i,j) position def dfs(self, board, i, j, word): if len(word) == 0: # all the characters are checked return True if i<0 or i>=len(board) or j<0 or j>=len(board[0]) or word[0]!=board[i][j]: return False tmp = board[i][j] # first character is found, check the remaining part board[i][j] = "#" # avoid visit agian # check whether can find "word" along one direction res = self.dfs(board, i+1, j, word[1:]) or self.dfs(board, i-1, j, word[1:]) \ or self.dfs(board, i, j+1, word[1:]) or self.dfs(board, i, j-1, word[1:]) board[i][j] = tmp return res
80. Remove Duplicates from Sorted Array II (Medium)
https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/
Topic Description
Thoughts on Problem Solving
class Solution: def removeDuplicates(self, nums): if nums==[]: return 0 i = 0 count = 1 while i < len(nums) - 1: # If the count is equal to 2 and the next number is still repeated, the next number is removed. if count == 2 and nums[i] == nums[i+1]: nums.pop(i+1) #i -= 1 # If the count is equal to 2 and the next number is different, the count is zero. Move the pointer down one bit. elif count == 2 and nums[i] != nums[i+1]: #nums.pop(i) i += 1 count = 1 elif count != 2 and nums[i] == nums[i+1]: if count < 2: i += 1 count += 1 # If the count is full of 2, the pointer cannot go any further. else: i += 1 # Processing the last number. return len(nums)
82. Remove Duplicates from Sorted List II (Medium)
https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/
Topic Description
Delete all duplicate nodes in an ordered list.
Thoughts on Problem Solving
""" //When a duplicate node is encountered, a pointer is used to point to the parent of the first duplicate node. //Link it to the next node of the last duplicate node """ class Solution: def deleteDuplicates(self, head: ListNode) -> ListNode: dummy = ListNode(0) dummy.next = head # Save the new node. pre = dummy cur = dummy.next while cur: if cur.next and cur.val == cur.next.val: #Traversing to cur.next value is no longer repeated while cur.next and cur.val == cur.next.val: cur = cur.next #Link the parent node to the next non-repetitive value pre.next = cur.next #Pointer moves to next cur = pre.next else: pre = cur cur = cur.next return dummy.next
86. Partition List (Medium)
https://leetcode.com/problems/partition-list/
Topic Description
Thoughts on Problem Solving
""" //Simple. Prepare two pointers, one smaller than 3, the other larger than 3, and link them together. """ class Solution: def partition(self, head: ListNode, x: int) -> ListNode: p1, p2 = ListNode(0), ListNode(0) head1, head2 = p1, p2 while head: if head.val < x: p1.next = head p1 = p1.next else: p2.next = head p2 = p2.next head = head.next p2.next = None p1.next = head2.next return head1.next
89. Gray Code (Medium)
https://leetcode.com/problems/gray-code/
Topic Description
Given n n n, from 0000 onwards, only one position changes to get a new binary number. Find all the binary numbers available.
Input: 2 Output: [0,1,3,2] Explanation: 00 - 0 01 - 1 11 - 3 10 - 2 For a given n, a gray code sequence may not be uniquely defined. For example, [0,2,3,1] is also a valid gray code sequence. 00 - 0 10 - 2 11 - 3 01 - 1
Thoughts on Problem Solving
""" Not every path leads to the complete combination. eg. (n = 3) 000 -> 001 -> 011 -> 111 -> 110 -> 100 -> 101 -> X The goal is to find a path which reaches the level == 2^n Revert bit one at a time (always from the right most one) and append to the ans list if it is not already. If the len(ans) == target, stop. """ class Solution(object): def grayCode(self, n): targetLevel = 2**n ans = [] self.dfs(n, ans, 0, 1, targetLevel) # Start with number = 0 (000), level = 1 return ans def dfs(self, n, ans, num, level, targetLevel): if num in ans: return ans.append(num) if level == targetLevel: return for i in range(0, n): self.dfs(n, ans, num ^ (1 << i), level+1, targetLevel) # num ^ (1 << i): revert a bit at a time if len(ans) == targetLevel: return # result found. Stop.
91. Decode Ways (Medium) **
https://leetcode.com/problems/decode-ways/
Topic Description
A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given a non-empty string containing only digits, determine the total number of ways to decode it. Example 1: Input: "12" Output: 2 Explanation: It could be decoded as "AB" (1 2) or "L" (12). Example 2: Input: "226" Output: 3 Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
Similar issues
62. Unique Paths
70. Climbing Stairs
93. Restore IP Addresses (Medium)
509. Fibonacci Number
You can practice it together.
Thoughts on Problem Solving
""" I used a dp array of size n + 1 to save subproblem solutions. dp[0] means an empty string will have one way to decode, dp[1] means the way to decode a string of size 1. I then check one digit and two digit combination and save the results along the way. In the end, dp[n] will be the end result. """ public class Solution { public int numDecodings(String s) { if(s == null || s.length() == 0) { return 0; } int n = s.length(); int[] dp = new int[n+1]; dp[0] = 1; dp[1] = s.charAt(0) != '0' ? 1 : 0; for(int i = 2; i <= n; i++) { int first = Integer.valueOf(s.substring(i-1, i)); int second = Integer.valueOf(s.substring(i-2, i)); if(first >= 1 && first <= 9) { dp[i] += dp[i-1]; } if(second >= 10 && second <= 26) { dp[i] += dp[i-2]; } } return dp[n]; } }
92. Reverse Linked List II (Medium)
https://leetcode.com/problems/reverse-linked-list-ii/
Topic Description
Reverse a linked list from position m to n. Do it in one-pass. Note: 1 ≤ m ≤ n ≤ length of list. Example: Input: 1->2->3->4->5->NULL, m = 2, n = 4 Output: 1->4->3->2->5->NULL
Thoughts on Problem Solving
/* */ public ListNode reverseBetween(ListNode head, int m, int n) { if(head == null) return null; ListNode dummy = new ListNode(0); // create a dummy node to mark the head of this list dummy.next = head; ListNode pre = dummy; // make a pointer pre as a marker for the node before reversing for(int i = 0; i<m-1; i++) pre = pre.next; ListNode start = pre.next; // a pointer to the beginning of a sub-list that will be reversed ListNode then = start.next; // a pointer to a node that will be reversed // 1 - 2 -3 - 4 - 5 ; m=2; n =4 ---> pre = 1, start = 2, then = 3 // dummy-> 1 -> 2 -> 3 -> 4 -> 5 for(int i=0; i<n-m; i++) { start.next = then.next; then.next = pre.next; pre.next = then; then = start.next; } // first reversing : dummy->1 - 3 - 2 - 4 - 5; pre = 1, start = 2, then = 4 // second reversing: dummy->1 - 4 - 3 - 2 - 5; pre = 1, start = 2, then = 5 (finish) return dummy.next; }
93. Restore IP Addresses (Medium)
https://leetcode.com/problems/restore-ip-addresses/
Topic Description
Enter a numeric string and output all possible valid IP.
Example: Input: "25525511135" Output: ["255.255.11.135", "255.255.111.35"]
Thoughts on Problem Solving
First, let's look at what a valid definition of ip is:
- The length of the ip without '.' should be equal to the length of s;
- The digit order of ip should be same as the digit order of s;
- Each part separated by the '.' should not start with '0' except only '0';
- Each part separared by the '.' should not larger than 255;
Solve the problem with DFS.
class Solution: def restoreIpAddresses(self, s): res = [] self.dfs(s, 0, "", res) return res def dfs(self, s, index, path, res): if index == 4: if not s: res.append(path[:-1]) return # backtracking for i in xrange(1, 4): # the digits we choose should no more than the length of s if i <= len(s): #choose one digit if i == 1: self.dfs(s[i:], index+1, path+s[:i]+".", res) #choose two digits, the first one should not be "0" elif i == 2 and s[0] != "0": self.dfs(s[i:], index+1, path+s[:i]+".", res) #choose three digits, the first one should not be "0", and should less than 256 elif i == 3 and s[0] != "0" and int(s[:3]) <= 255: self.dfs(s[i:], index+1, path+s[:i]+".", res)
94. Binary Tree Inorder Traversal (Medium)
https://leetcode.com/problems/binary-tree-inorder-traversal/
Topic Description
Iteratively traverse arrays in order. left - > Middle - > right
Because the node on the left has to output first, and then it's the root node.
- All left nodes on the left side of the root node are stacked (until the last node without the left subtree).
- Pop up the top of the stack, read the data from the top of the stack (in this case, the top node is the root node without the left node), then put the right node on the top of the stack into the stack, treat the right node as a new root node, repeat 1 until the empty stack.
Thoughts on Problem Solving
""" //Intermediate traversal is implemented iteratively. """ class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: stack, ans = [], [] while True: while root: stack.append(root) root = root.left if not stack: return ans node = stack.pop() ans.append(node.val) root = node.right return ans
96. Unique Binary Search Trees (Medium)
https://leetcode.com/problems/unique-binary-search-trees/
Topic Description
Input n, output the number of all possible binary lookup trees consisting of N numbers
Input: 3 Output: 5 Explanation: The above output corresponds to the 5 unique BST's shown below: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
Thoughts on Problem Solving
Divide and conquer problems.
input | root node | Left node | Right node | Number of possible cases |
---|---|---|---|---|
1 | 1 | 0 | 0 | 1 |
Total | 1 | |||
2 | 1 | 0 | 1 | 1 |
- | 2 | 1 | 0 | 1 |
Total | 2 | |||
3 | 1 | 0 | 2 | 1 x 2 |
- | 2 | 1 | 1 | 1 x 1 |
- | 3 | 2 | 0 | 2 x 1 |
Total | 2 + 1 + 2 = 5 | |||
4 | 1 | 0 | 3 | 1 x 5 |
- | 2 | 1 | 2 | 1 x 2 |
- | 3 | 2 | 1 | 2 x 1 |
- | 4 | 3 | 0 | 5 x 1 |
Total | 5 + 2 + 2 + 5 = 14 |
Take the case of input 4 as an explanation. When we take the root node as 1, we can put three numbers on the right side. Then when the input is 3, we know that there are five kinds of arrangement, so we can get that when the root node is 1, there are five kinds of arrangement.
When the root node is 2, there can be one number on the left and two numbers on the right. The result is 1 x 2 = 2, so when the root node is 2, there are two kinds of arrangements.
So the equation of state transition is obtained as follows:
f(1) = 1
f(2) = 2
f(n) = Σ0n−1\Sigma_0^{n-1}Σ0n−1 f(j) * f(n-1-j)
""" //Instead of recursive writing, you use arrays. //Each value represents a state. The value of a state is also calculated from the previous state. """ class Solution: def numTrees(self, n: int) -> int: if n == 0 or n == 1: return 1 if n == 2: return 2 num = [1, 1, 2] for i in range(3, n+1): s = 0 for j in range(i): s += num[j]*num[i-1-j] num.append(s) return num[-1]
95. Unique Binary Search Trees II (Medium)
https://leetcode.com/problems/unique-binary-search-trees-ii/
Topic Description
Input n, output a set of all possible binary search trees consisting of n numbers.
Input: 3 Output: [ [1,null,3,2], [3,2,null,1], [3,1,null,null,2], [2,1,3], [1,null,2,null,3] ] Explanation: The above output corresponds to the 5 unique BST's shown below: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
Thoughts on Problem Solving
class Solution(object): def generateTrees(self, n): """ :type n: int :rtype: List[TreeNode] """ if n == 0: return [[]] return self.dfs(1, n+1) def dfs(self, start, end): if start == end: return None result = [] for i in xrange(start, end): for l in self.dfs(start, i) or [None]: for r in self.dfs(i+1, end) or [None]: node = TreeNode(i) node.left, node.right = l, r result.append(node) return result
98. Validate Binary Search Tree (Medium)
https://leetcode.com/problems/validate-binary-search-tree/
Topic Description
Determine whether a tree is a binary search tree.
Thoughts on Problem Solving
1. Recursive method:
class Solution: def isValidBST(self, root: TreeNode) -> bool: if root == None: return True tree = [] self.inOrder(root, tree) if len(tree) == 1: return True for i in range(len(tree)-1): if tree[i] >= tree[i+1]: return False return True def inOrder(self, root, tree): if root == None: return if root.left: self.inOrder(root.left, tree) tree.append(root.val) if root.right: self.inOrder(root.right, tree)
2. Iterative method:
""" Record the precursor node prev. Record and stack the right node of each visit node. The order of visiting nodes is left - > Middle - > right, and the numerical value is incremental. Therefore, the order of visiting nodes is left - > Middle - > right. At each visit, the current value must not be <=prev. The root node a visit s when there is no left node, and then goes to the right node of the stack. At this time, prev is the root node a. The right node also cannot visit until it traverses to the leftmost node, and its value is greater than the value of prev. If the right node There is no such thing as the root node of a, which should be larger than the value of A. """ class Solution: def isValidBST(self, root: TreeNode) -> bool: if root == None: return True stack, ans = [], [] prev = None # while True: while root: stack.append(root) root = root.left if not stack: return ans node = stack.pop() ### if prev != None and node.val <= prev.val: return False prev = node ### ans.append(node.val) root = node.right return True