diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index eea3ba7a..1af8787b 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -151,7 +151,7 @@ public int[] twoSum(int[] nums, int target) { ``` Python: - +(版本一) 使用字典 ```python class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: @@ -163,6 +163,53 @@ class Solution: records[value] = index # 遍历当前元素,并在map中寻找是否有匹配的key return [] ``` +(版本二)使用集合 +```python +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + #创建一个集合来存储我们目前看到的数字 + seen = set() + for i, num in enumerate(nums): + complement = target - num + if complement in seen: + return [nums.index(complement), i] + seen.add(num) +``` +(版本三)使用双指针 +```python +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + # 对输入列表进行排序 + nums_sorted = sorted(nums) + + # 使用双指针 + left = 0 + right = len(nums_sorted) - 1 + while left < right: + current_sum = nums_sorted[left] + nums_sorted[right] + if current_sum == target: + # 如果和等于目标数,则返回两个数的下标 + left_index = nums.index(nums_sorted[left]) + right_index = nums.index(nums_sorted[right]) + if left_index == right_index: + right_index = nums[left_index+1:].index(nums_sorted[right]) + left_index + 1 + return [left_index, right_index] + elif current_sum < target: + # 如果总和小于目标,则将左侧指针向右移动 + left += 1 + else: + # 如果总和大于目标值,则将右指针向左移动 + right -= 1 +``` +(版本四)暴力法 +```python +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + for i in range(len(nums)): + for j in range(i+1, len(nums)): + if nums[i] + nums[j] == target: + return [i,j] +``` Go: diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index 26c9eaa2..9cca779b 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -298,61 +298,72 @@ class Solution { ``` Python: +(版本一) 双指针 ```Python class Solution: - def threeSum(self, nums): - ans = [] - n = len(nums) + def threeSum(self, nums: List[int]) -> List[List[int]]: + result = [] nums.sort() - # 找出a + b + c = 0 - # a = nums[i], b = nums[left], c = nums[right] - for i in range(n): - left = i + 1 - right = n - 1 - # 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 - if nums[i] > 0: - break - if i >= 1 and nums[i] == nums[i - 1]: # 去重a + + for i in range(len(nums)): + # 如果第一个元素已经大于0,不需要进一步检查 + if nums[i] > 0: + return result + + # 跳过相同的元素以避免重复 + if i > 0 and nums[i] == nums[i - 1]: continue - while left < right: - total = nums[i] + nums[left] + nums[right] - if total > 0: - right -= 1 - elif total < 0: + + left = i + 1 + right = len(nums) - 1 + + while right > left: + sum_ = nums[i] + nums[left] + nums[right] + + if sum_ < 0: left += 1 + elif sum_ > 0: + right -= 1 else: - ans.append([nums[i], nums[left], nums[right]]) - # 去重逻辑应该放在找到一个三元组之后,对b 和 c去重 - while left != right and nums[left] == nums[left + 1]: left += 1 - while left != right and nums[right] == nums[right - 1]: right -= 1 - left += 1 + result.append([nums[i], nums[left], nums[right]]) + + # 跳过相同的元素以避免重复 + while right > left and nums[right] == nums[right - 1]: + right -= 1 + while right > left and nums[left] == nums[left + 1]: + left += 1 + right -= 1 - return ans + left += 1 + + return result ``` -Python (v3): +(版本二) 使用字典 ```python class Solution: def threeSum(self, nums: List[int]) -> List[List[int]]: - if len(nums) < 3: return [] - nums, res = sorted(nums), [] - for i in range(len(nums) - 2): - cur, l, r = nums[i], i + 1, len(nums) - 1 - if res != [] and res[-1][0] == cur: continue # Drop duplicates for the first time. - - while l < r: - if cur + nums[l] + nums[r] == 0: - res.append([cur, nums[l], nums[r]]) - # Drop duplicates for the second time in interation of l & r. Only used when target situation occurs, because that is the reason for dropping duplicates. - while l < r - 1 and nums[l] == nums[l + 1]: - l += 1 - while r > l + 1 and nums[r] == nums[r - 1]: - r -= 1 - if cur + nums[l] + nums[r] > 0: - r -= 1 + result = [] + nums.sort() + # 找出a + b + c = 0 + # a = nums[i], b = nums[j], c = -(a + b) + for i in range(len(nums)): + # 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 + if nums[i] > 0: + break + if i > 0 and nums[i] == nums[i - 1]: #三元组元素a去重 + continue + d = {} + for j in range(i + 1, len(nums)): + if j > i + 2 and nums[j] == nums[j-1] == nums[j-2]: # 三元组元素b去重 + continue + c = 0 - (nums[i] + nums[j]) + if c in d: + result.append([nums[i], nums[j], c]) + d.pop(c) # 三元组元素c去重 else: - l += 1 - return res + d[nums[j]] = j + return result ``` Go: diff --git a/problems/0018.四数之和.md b/problems/0018.四数之和.md index 5f4c2ec9..a4d41d9b 100644 --- a/problems/0018.四数之和.md +++ b/problems/0018.四数之和.md @@ -207,35 +207,44 @@ class Solution { ``` Python: +(版本一) 双指针 ```python -# 双指针法 class Solution: def fourSum(self, nums: List[int], target: int) -> List[List[int]]: - nums.sort() n = len(nums) - res = [] - for i in range(n): - if i > 0 and nums[i] == nums[i - 1]: continue # 对nums[i]去重 - for k in range(i+1, n): - if k > i + 1 and nums[k] == nums[k-1]: continue # 对nums[k]去重 - p = k + 1 - q = n - 1 - - while p < q: - if nums[i] + nums[k] + nums[p] + nums[q] > target: q -= 1 - elif nums[i] + nums[k] + nums[p] + nums[q] < target: p += 1 + result = [] + for i in range(n): + if nums[i] > target and nums[i] > 0 and target > 0:# 剪枝(可省) + break + if i > 0 and nums[i] == nums[i-1]:# 去重 + continue + for j in range(i+1, n): + if nums[i] + nums[j] > target and target > 0: #剪枝(可省) + break + if j > i+1 and nums[j] == nums[j-1]: # 去重 + continue + left, right = j+1, n-1 + while left < right: + s = nums[i] + nums[j] + nums[left] + nums[right] + if s == target: + result.append([nums[i], nums[j], nums[left], nums[right]]) + while left < right and nums[left] == nums[left+1]: + left += 1 + while left < right and nums[right] == nums[right-1]: + right -= 1 + left += 1 + right -= 1 + elif s < target: + left += 1 else: - res.append([nums[i], nums[k], nums[p], nums[q]]) - # 对nums[p]和nums[q]去重 - while p < q and nums[p] == nums[p + 1]: p += 1 - while p < q and nums[q] == nums[q - 1]: q -= 1 - p += 1 - q -= 1 - return res + right -= 1 + return result + ``` +(版本二) 使用字典 + ```python -# 哈希表法 class Solution(object): def fourSum(self, nums, target): """ @@ -243,36 +252,25 @@ class Solution(object): :type target: int :rtype: List[List[int]] """ - # use a dict to store value:showtimes - hashmap = dict() - for n in nums: - if n in hashmap: - hashmap[n] += 1 - else: - hashmap[n] = 1 + # 创建一个字典来存储输入列表中每个数字的频率 + freq = {} + for num in nums: + freq[num] = freq.get(num, 0) + 1 - # good thing about using python is you can use set to drop duplicates. + # 创建一个集合来存储最终答案,并遍历4个数字的所有唯一组合 ans = set() - # ans = [] # save results by list() for i in range(len(nums)): for j in range(i + 1, len(nums)): for k in range(j + 1, len(nums)): val = target - (nums[i] + nums[j] + nums[k]) - if val in hashmap: - # make sure no duplicates. + if val in freq: + # 确保没有重复 count = (nums[i] == val) + (nums[j] == val) + (nums[k] == val) - if hashmap[val] > count: - ans_tmp = tuple(sorted([nums[i], nums[j], nums[k], val])) - ans.add(ans_tmp) - # Avoiding duplication in list manner but it cause time complexity increases - # if ans_tmp not in ans: - # ans.append(ans_tmp) - else: - continue - return list(ans) - # if used list() to save results, just - # return ans + if freq[val] > count: + ans.add(tuple(sorted([nums[i], nums[j], nums[k], val]))) + return [list(x) for x in ans] + ``` Go: diff --git a/problems/0028.实现strStr.md b/problems/0028.实现strStr.md index 263c1689..86308b47 100644 --- a/problems/0028.实现strStr.md +++ b/problems/0028.实现strStr.md @@ -692,8 +692,67 @@ class Solution { ``` Python3: +(版本一)前缀表(减一) +```python +class Solution: + def getNext(self, next, s): + j = -1 + next[0] = j + for i in range(1, len(s)): + while j >= 0 and s[i] != s[j+1]: + j = next[j] + if s[i] == s[j+1]: + j += 1 + next[i] = j + + def strStr(self, haystack: str, needle: str) -> int: + if not needle: + return 0 + next = [0] * len(needle) + self.getNext(next, needle) + j = -1 + for i in range(len(haystack)): + while j >= 0 and haystack[i] != needle[j+1]: + j = next[j] + if haystack[i] == needle[j+1]: + j += 1 + if j == len(needle) - 1: + return i - len(needle) + 1 + return -1 +``` +(版本二)前缀表(不减一) + +```python +class Solution: + def getNext(self, next: List[int], s: str) -> None: + j = 0 + next[0] = 0 + for i in range(1, len(s)): + while j > 0 and s[i] != s[j]: + j = next[j - 1] + if s[i] == s[j]: + j += 1 + next[i] = j + + def strStr(self, haystack: str, needle: str) -> int: + if len(needle) == 0: + return 0 + next = [0] * len(needle) + self.getNext(next, needle) + j = 0 + for i in range(len(haystack)): + while j > 0 and haystack[i] != needle[j]: + j = next[j - 1] + if haystack[i] == needle[j]: + j += 1 + if j == len(needle): + return i - len(needle) + 1 + return -1 +``` + + +(版本三)暴力法 ```python -//暴力解法: class Solution(object): def strStr(self, haystack, needle): """ @@ -707,102 +766,22 @@ class Solution(object): return i return -1 ``` +(版本四)使用 index ```python -// 方法一 class Solution: def strStr(self, haystack: str, needle: str) -> int: - a = len(needle) - b = len(haystack) - if a == 0: - return 0 - next = self.getnext(a,needle) - p=-1 - for j in range(b): - while p >= 0 and needle[p+1] != haystack[j]: - p = next[p] - if needle[p+1] == haystack[j]: - p += 1 - if p == a-1: - return j-a+1 - return -1 - - def getnext(self,a,needle): - next = ['' for i in range(a)] - k = -1 - next[0] = k - for i in range(1, len(needle)): - while (k > -1 and needle[k+1] != needle[i]): - k = next[k] - if needle[k+1] == needle[i]: - k += 1 - next[i] = k - return next -``` - -```python -// 方法二 -class Solution: - def strStr(self, haystack: str, needle: str) -> int: - a = len(needle) - b = len(haystack) - if a == 0: - return 0 - i = j = 0 - next = self.getnext(a, needle) - while(i < b and j < a): - if j == -1 or needle[j] == haystack[i]: - i += 1 - j += 1 - else: - j = next[j] - if j == a: - return i-j - else: + try: + return haystack.index(needle) + except ValueError: return -1 - - def getnext(self, a, needle): - next = ['' for i in range(a)] - j, k = 0, -1 - next[0] = k - while(j < a-1): - if k == -1 or needle[k] == needle[j]: - k += 1 - j += 1 - next[j] = k - else: - k = next[k] - return next ``` - +(版本五)使用 find ```python -// 前缀表(不减一)Python实现 class Solution: def strStr(self, haystack: str, needle: str) -> int: - if len(needle) == 0: - return 0 - next = self.getNext(needle) - j = 0 - for i in range(len(haystack)): - while j >= 1 and haystack[i] != needle[j]: - j = next[j-1] - if haystack[i] == needle[j]: - j += 1 - if j == len(needle): - return i - len(needle) + 1 - return -1 - - def getNext(self, needle): - next = [0] * len(needle) - j = 0 - next[0] = j - for i in range(1, len(needle)): - while j >= 1 and needle[i] != needle[j]: - j = next[j-1] - if needle[i] == needle[j]: - j += 1 - next[i] = j - return next -``` + return haystack.find(needle) + +``` Go: diff --git a/problems/0110.平衡二叉树.md b/problems/0110.平衡二叉树.md index 804c95eb..a3bc77fb 100644 --- a/problems/0110.平衡二叉树.md +++ b/problems/0110.平衡二叉树.md @@ -532,6 +532,24 @@ class Solution: else: return 1 + max(left_height, right_height) ``` +递归法精简版: + +```python +class Solution: + def isBalanced(self, root: TreeNode) -> bool: + return self.height(root) != -1 + def height(self, node: TreeNode) -> int: + if not node: + return 0 + left = self.height(node.left) + if left == -1: + return -1 + right = self.height(node.right) + if right == -1 or abs(left - right) > 1: + return -1 + return max(left, right) + 1 +``` + 迭代法: diff --git a/problems/0151.翻转字符串里的单词.md b/problems/0151.翻转字符串里的单词.md index 8fa7c77c..4474f1c6 100644 --- a/problems/0151.翻转字符串里的单词.md +++ b/problems/0151.翻转字符串里的单词.md @@ -434,134 +434,40 @@ class Solution { ``` python: - +(版本一)先删除空白,然后整个反转,最后单词反转。 +**因为字符串是不可变类型,所以反转单词的时候,需要将其转换成列表,然后通过join函数再将其转换成列表,所以空间复杂度不是O(1)** ```Python class Solution: - #1.去除多余的空格 - def trim_spaces(self, s): - n = len(s) - left = 0 - right = n-1 - - while left <= right and s[left] == ' ': #去除开头的空格 - left += 1 - while left <= right and s[right] == ' ': #去除结尾的空格 - right -= 1 - tmp = [] - while left <= right: #去除单词中间多余的空格 - if s[left] != ' ': - tmp.append(s[left]) - elif tmp[-1] != ' ': #当前位置是空格,但是相邻的上一个位置不是空格,则该空格是合理的 - tmp.append(s[left]) - left += 1 - return tmp - - #2.翻转字符数组 - def reverse_string(self, nums, left, right): - while left < right: - nums[left], nums[right] = nums[right], nums[left] - left += 1 - right -= 1 - return None - - #3.翻转每个单词 - def reverse_each_word(self, nums): - start = 0 - end = 0 - n = len(nums) - while start < n: - while end < n and nums[end] != ' ': - end += 1 - self.reverse_string(nums, start, end-1) - start = end + 1 - end += 1 - return None - -#4.翻转字符串里的单词 - def reverseWords(self, s): #测试用例:"the sky is blue" - l = self.trim_spaces(s) #输出:['t', 'h', 'e', ' ', 's', 'k', 'y', ' ', 'i', 's', ' ', 'b', 'l', 'u', 'e' - self.reverse_string(l, 0, len(l)-1) #输出:['e', 'u', 'l', 'b', ' ', 's', 'i', ' ', 'y', 'k', 's', ' ', 'e', 'h', 't'] - self.reverse_each_word(l) #输出:['b', 'l', 'u', 'e', ' ', 'i', 's', ' ', 's', 'k', 'y', ' ', 't', 'h', 'e'] - return ''.join(l) #输出:blue is sky the - + def reverseWords(self, s: str) -> str: + # 删除前后空白 + s = s.strip() + # 反转整个字符串 + s = s[::-1] + # 将字符串拆分为单词,并反转每个单词 + s = ' '.join(word[::-1] for word in s.split()) + return s ``` +(版本二)使用双指针 ```python class Solution: def reverseWords(self, s: str) -> str: - # method 1 - Rude but work & efficient method. - s_list = [i for i in s.split(" ") if len(i) > 0] - return " ".join(s_list[::-1]) + # 将字符串拆分为单词,即转换成列表类型 + words = s.split() - # method 2 - Carlo's idea - def trim_head_tail_space(ss: str): - p = 0 - while p < len(ss) and ss[p] == " ": - p += 1 - return ss[p:] + # 反转单词 + left, right = 0, len(words) - 1 + while left < right: + words[left], words[right] = words[right], words[left] + left += 1 + right -= 1 - # Trim the head and tail space - s = trim_head_tail_space(s) - s = trim_head_tail_space(s[::-1])[::-1] - - pf, ps, s = 0, 0, s[::-1] # Reverse the string. - while pf < len(s): - if s[pf] == " ": - # Will not excede. Because we have clean the tail space. - if s[pf] == s[pf + 1]: - s = s[:pf] + s[pf + 1:] - continue - else: - s = s[:ps] + s[ps: pf][::-1] + s[pf:] - ps, pf = pf + 1, pf + 2 - else: - pf += 1 - return s[:ps] + s[ps:][::-1] # Must do the last step, because the last word is omit though the pointers are on the correct positions, + # 将列表转换成字符串 + return " ".join(words) ``` -```python -class Solution: # 使用双指针法移除空格 - def reverseWords(self, s: str) -> str: - - def removeextraspace(s): - start = 0; end = len(s)-1 - while s[start]==' ': - start+=1 - while s[end]==' ': - end-=1 - news = list(s[start:end+1]) - slow = fast = 0 - while fast0 and news[fast]==news[fast-1]==' ': - fast+=1 - news[slow]=news[fast] - slow+=1; fast+=1 - #return "".join(news[:slow]) - return news[:slow] - def reversestr(s): - left,right = 0,len(s)-1 - news = list(s) - while left bool: - def calculate_happy(num): - sum_ = 0 - - # 从个位开始依次取,平方求和 - while num: - sum_ += (num % 10) ** 2 - num = num // 10 - return sum_ - - # 记录中间结果 + def isHappy(self, n: int) -> bool: record = set() while True: - n = calculate_happy(n) + n = self.get_sum(n) if n == 1: return True @@ -134,21 +125,86 @@ class Solution: else: record.add(n) -# python的另一种写法 - 通过字符串来计算各位平方和 + def get_sum(self,n: int) -> int: + new_num = 0 + while n: + n, r = divmod(n, 10) + new_num += r ** 2 + return new_num + ``` + (版本二)使用集合 + ```python +class Solution: + def isHappy(self, n: int) -> bool: + record = set() + while n not in record: + record.add(n) + new_num = 0 + n_str = str(n) + for i in n_str: + new_num+=int(i)**2 + if new_num==1: return True + else: n = new_num + return False +``` + (版本三)使用数组 + ```python class Solution: def isHappy(self, n: int) -> bool: record = [] while n not in record: record.append(n) - newn = 0 - nn = str(n) - for i in nn: - newn+=int(i)**2 - if newn==1: return True - n = newn + new_num = 0 + n_str = str(n) + for i in n_str: + new_num+=int(i)**2 + if new_num==1: return True + else: n = new_num return False ``` - + (版本四)使用快慢指针 + ```python +class Solution: + def isHappy(self, n: int) -> bool: + slow = n + fast = n + while self.get_sum(fast) != 1 and self.get_sum(self.get_sum(fast)): + slow = self.get_sum(slow) + fast = self.get_sum(self.get_sum(fast)) + if slow == fast: + return False + return True + def get_sum(self,n: int) -> int: + new_num = 0 + while n: + n, r = divmod(n, 10) + new_num += r ** 2 + return new_num +``` + (版本五)使用集合+精简 + ```python +class Solution: + def isHappy(self, n: int) -> bool: + seen = set() + while n != 1: + n = sum(int(i) ** 2 for i in str(n)) + if n in seen: + return False + seen.add(n) + return True +``` + (版本六)使用数组+精简 + ```python +class Solution: + def isHappy(self, n: int) -> bool: + seen = [] + while n != 1: + n = sum(int(i) ** 2 for i in str(n)) + if n in seen: + return False + seen.append(n) + return True +``` Go: ```go func isHappy(n int) bool { diff --git a/problems/0242.有效的字母异位词.md b/problems/0242.有效的字母异位词.md index ba802bbd..101dd6f2 100644 --- a/problems/0242.有效的字母异位词.md +++ b/problems/0242.有效的字母异位词.md @@ -122,6 +122,7 @@ class Solution { ``` Python: + ```python class Solution: def isAnagram(self, s: str, t: str) -> bool: @@ -137,7 +138,6 @@ class Solution: return False return True ``` - Python写法二(没有使用数组作为哈希表,只是介绍defaultdict这样一种解题思路): ```python @@ -147,13 +147,11 @@ class Solution: s_dict = defaultdict(int) t_dict = defaultdict(int) - for x in s: s_dict[x] += 1 for x in t: t_dict[x] += 1 - return s_dict == t_dict ``` Python写法三(没有使用数组作为哈希表,只是介绍Counter这种更方便的解题思路): @@ -165,7 +163,6 @@ class Solution(object): a_count = Counter(s) b_count = Counter(t) return a_count == b_count -``` Go: diff --git a/problems/0257.二叉树的所有路径.md b/problems/0257.二叉树的所有路径.md index 8c542cea..c396f4a0 100644 --- a/problems/0257.二叉树的所有路径.md +++ b/problems/0257.二叉树的所有路径.md @@ -468,6 +468,71 @@ class Solution { ``` --- ## Python: + + +递归法+回溯(版本一) +```Python +# 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 +import copy +from typing import List, Optional + +class Solution: + def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]: + if not root: + return [] + result = [] + self.generate_paths(root, [], result) + return result + + def generate_paths(self, node: TreeNode, path: List[int], result: List[str]) -> None: + path.append(node.val) + if not node.left and not node.right: + result.append('->'.join(map(str, path))) + if node.left: + self.generate_paths(node.left, copy.copy(path), result) + if node.right: + self.generate_paths(node.right, copy.copy(path), result) + path.pop() + + +``` +递归法+回溯(版本二) +```Python +# 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 +import copy +from typing import List, Optional + +class Solution: + def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]: + if not root: + return [] + result = [] + self.generate_paths(root, [], result) + return result + + def generate_paths(self, node: TreeNode, path: List[int], result: List[str]) -> None: + if not node: + return + path.append(node.val) + if not node.left and not node.right: + result.append('->'.join(map(str, path))) + else: + self.generate_paths(node.left, copy.copy(path), result) + self.generate_paths(node.right, copy.copy(path), result) + path.pop() + +``` + 递归法+隐形回溯 ```Python # Definition for a binary tree node. diff --git a/problems/0344.反转字符串.md b/problems/0344.反转字符串.md index 775cfc58..1c74f9aa 100644 --- a/problems/0344.反转字符串.md +++ b/problems/0344.反转字符串.md @@ -174,6 +174,7 @@ class Solution { ``` Python: +(版本一) 双指针 ```python class Solution: def reverseString(self, s: List[str]) -> None: @@ -182,15 +183,70 @@ class Solution: """ left, right = 0, len(s) - 1 - # 该方法已经不需要判断奇偶数,经测试后时间空间复杂度比用 for i in range(right//2)更低 - # 推荐该写法,更加通俗易懂 + # 该方法已经不需要判断奇偶数,经测试后时间空间复杂度比用 for i in range(len(s)//2)更低 + # 因为while每次循环需要进行条件判断,而range函数不需要,直接生成数字,因此时间复杂度更低。推荐使用range while left < right: s[left], s[right] = s[right], s[left] left += 1 right -= 1 ``` - +(版本二) 使用栈 +```python +class Solution: + def reverseString(self, s: List[str]) -> None: + """ + Do not return anything, modify s in-place instead. + """ + stack = [] + for char in s: + stack.append(char) + for i in range(len(s)): + s[i] = stack.pop() + +``` +(版本三) 使用range +```python +class Solution: + def reverseString(self, s: List[str]) -> None: + """ + Do not return anything, modify s in-place instead. + """ + n = len(s) + for i in range(n // 2): + s[i], s[n - i - 1] = s[n - i - 1], s[i] + +``` +(版本四) 使用reversed +```python +class Solution: + def reverseString(self, s: List[str]) -> None: + """ + Do not return anything, modify s in-place instead. + """ + s[:] = reversed(s) + +``` +(版本五) 使用切片 +```python +class Solution: + def reverseString(self, s: List[str]) -> None: + """ + Do not return anything, modify s in-place instead. + """ + s[:] = s[::-1] + +``` +(版本六) 使用列表推导 +```python +class Solution: + def reverseString(self, s: List[str]) -> None: + """ + Do not return anything, modify s in-place instead. + """ + s[:] = [s[i] for i in range(len(s) - 1, -1, -1)] + +``` Go: ```Go func reverseString(s []byte) { diff --git a/problems/0349.两个数组的交集.md b/problems/0349.两个数组的交集.md index 0da0e30c..c2f6ef46 100644 --- a/problems/0349.两个数组的交集.md +++ b/problems/0349.两个数组的交集.md @@ -160,22 +160,29 @@ class Solution { ``` Python3: +(版本一) 使用字典和集合 ```python class Solution: def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]: - val_dict = {} - ans = [] + # 使用哈希表存储一个数组中的所有元素 + table = {} for num in nums1: - val_dict[num] = 1 - - for num in nums2: - if num in val_dict.keys() and val_dict[num] == 1: - ans.append(num) - val_dict[num] = 0 + table[num] = table.get(num, 0) + 1 - return ans + # 使用集合存储结果 + res = set() + for num in nums2: + if num in table: + res.add(num) + del table[num] + + return list(res) +``` +(版本二) 使用数组 + +```python -class Solution: # 使用数组方法 +class Solution: def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]: count1 = [0]*1001 count2 = [0]*1001 @@ -190,7 +197,14 @@ class Solution: # 使用数组方法 return result ``` +(版本三) 使用集合 +```python +class Solution: + def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]: + return list(set(nums1) & set(nums2)) + +``` Go: ```go diff --git a/problems/0383.赎金信.md b/problems/0383.赎金信.md index a3f87d4a..c7469d65 100644 --- a/problems/0383.赎金信.md +++ b/problems/0383.赎金信.md @@ -146,34 +146,27 @@ class Solution { ``` -Python写法一(使用数组作为哈希表): - +(版本一)使用数组 ```python class Solution: def canConstruct(self, ransomNote: str, magazine: str) -> bool: - - arr = [0] * 26 - - for x in magazine: # 记录 magazine里各个字符出现次数 - arr[ord(x) - ord('a')] += 1 - - for x in ransomNote: # 在arr里对应的字符个数做--操作 - if arr[ord(x) - ord('a')] == 0: # 如果没有出现过直接返回 - return False - else: - arr[ord(x) - ord('a')] -= 1 - - return True + ransom_count = [0] * 26 + magazine_count = [0] * 26 + for c in ransomNote: + ransom_count[ord(c) - ord('a')] += 1 + for c in magazine: + magazine_count[ord(c) - ord('a')] += 1 + return all(ransom_count[i] <= magazine_count[i] for i in range(26)) ``` -Python写法二(使用defaultdict): +(版本二)使用defaultdict ```python +from collections import defaultdict + class Solution: def canConstruct(self, ransomNote: str, magazine: str) -> bool: - from collections import defaultdict - hashmap = defaultdict(int) for x in magazine: @@ -181,59 +174,43 @@ class Solution: for x in ransomNote: value = hashmap.get(x) - if value is None or value == 0: + if not value or not value: return False else: hashmap[x] -= 1 return True ``` - -Python写法三: - -```python -class Solution(object): - def canConstruct(self, ransomNote, magazine): - """ - :type ransomNote: str - :type magazine: str - :rtype: bool - """ - - # use a dict to store the number of letter occurance in ransomNote - hashmap = dict() - for s in ransomNote: - if s in hashmap: - hashmap[s] += 1 - else: - hashmap[s] = 1 - - # check if the letter we need can be found in magazine - for l in magazine: - if l in hashmap: - hashmap[l] -= 1 - - for key in hashmap: - if hashmap[key] > 0: - return False - - return True -``` - -Python写法四: +(版本三)使用字典 ```python class Solution: def canConstruct(self, ransomNote: str, magazine: str) -> bool: - c1 = collections.Counter(ransomNote) - c2 = collections.Counter(magazine) - x = c1 - c2 - #x只保留值大于0的符号,当c1里面的符号个数小于c2时,不会被保留 - #所以x只保留下了,magazine不能表达的 - if(len(x)==0): - return True - else: - return False + counts = {} + for c in magazine: + counts[c] = counts.get(c, 0) + 1 + for c in ransomNote: + if c not in counts or counts[c] == 0: + return False + counts[c] -= 1 + return True +``` +(版本四)使用Counter + +```python +from collections import Counter + +class Solution: + def canConstruct(self, ransomNote: str, magazine: str) -> bool: + return not Counter(ransomNote) - Counter(magazine) +``` +(版本五)使用count + +```python +class Solution: + def canConstruct(self, ransomNote: str, magazine: str) -> bool: + return all(ransomNote.count(c) <= magazine.count(c) for c in set(ransomNote)) + ``` Go: diff --git a/problems/0404.左叶子之和.md b/problems/0404.左叶子之和.md index cf5441c4..617978b7 100644 --- a/problems/0404.左叶子之和.md +++ b/problems/0404.左叶子之和.md @@ -250,19 +250,27 @@ class Solution { **递归后序遍历** ```python +# 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 sumOfLeftLeaves(self, root: TreeNode) -> int: - if not root: + def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int: + if not root: return 0 - left_left_leaves_sum = self.sumOfLeftLeaves(root.left) # 左 - right_left_leaves_sum = self.sumOfLeftLeaves(root.right) # 右 - - cur_left_leaf_val = 0 - if root.left and not root.left.left and not root.left.right: - cur_left_leaf_val = root.left.val + # 检查根节点的左子节点是否为叶节点 + if root.left and not root.left.left and not root.left.right: + left_val = root.left.val + else: + left_val = self.sumOfLeftLeaves(root.left) - return cur_left_leaf_val + left_left_leaves_sum + right_left_leaves_sum # 中 + # 递归地计算右子树左叶节点的和 + right_val = self.sumOfLeftLeaves(root.right) + + return left_val + right_val ``` **迭代** diff --git a/problems/0454.四数相加II.md b/problems/0454.四数相加II.md index abfc7c23..4a16d4f4 100644 --- a/problems/0454.四数相加II.md +++ b/problems/0454.四数相加II.md @@ -118,11 +118,11 @@ class Solution { ``` Python: - +(版本一) 使用字典 ```python class Solution(object): def fourSumCount(self, nums1, nums2, nums3, nums4): - # use a dict to store the elements in nums1 and nums2 and their sum + # 使用字典存储nums1和nums2中的元素及其和 hashmap = dict() for n1 in nums1: for n2 in nums2: @@ -131,7 +131,7 @@ class Solution(object): else: hashmap[n1+n2] = 1 - # if the -(a+b) exists in nums3 and nums4, we shall add the count + # 如果 -(n1+n2) 存在于nums3和nums4, 存入结果 count = 0 for n3 in nums3: for n4 in nums4: @@ -142,20 +142,40 @@ class Solution(object): ``` - +(版本二) 使用字典 ```python +class Solution(object): + def fourSumCount(self, nums1, nums2, nums3, nums4): + # 使用字典存储nums1和nums2中的元素及其和 + hashmap = dict() + for n1 in nums1: + for n2 in nums2: + hashmap[n1+n2] = hashmap.get(n1+n2, 0) + 1 + + # 如果 -(n1+n2) 存在于nums3和nums4, 存入结果 + count = 0 + for n3 in nums3: + for n4 in nums4: + key = - n3 - n4 + if key in hashmap: + count += hashmap[key] + return count + + + +``` +(版本三)使用 defaultdict +```python +from collections import defaultdict class Solution: def fourSumCount(self, nums1: list, nums2: list, nums3: list, nums4: list) -> int: - from collections import defaultdict # You may use normal dict instead. rec, cnt = defaultdict(lambda : 0), 0 - # To store the summary of all the possible combinations of nums1 & nums2, together with their frequencies. for i in nums1: for j in nums2: rec[i+j] += 1 - # To add up the frequencies if the corresponding value occurs in the dictionary for i in nums3: for j in nums4: - cnt += rec.get(-(i+j), 0) # No matched key, return 0. + cnt += rec.get(-(i+j), 0) return cnt ``` diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md index 98c02a25..5d56ad18 100644 --- a/problems/0459.重复的子字符串.md +++ b/problems/0459.重复的子字符串.md @@ -264,8 +264,7 @@ class Solution { Python: -这里使用了前缀表统一减一的实现方式 - +(版本一) 前缀表 减一 ```python class Solution: def repeatedSubstringPattern(self, s: str) -> bool: @@ -289,7 +288,7 @@ class Solution: return nxt ``` -前缀表(不减一)的代码实现 +(版本二) 前缀表 不减一 ```python class Solution: @@ -314,6 +313,40 @@ class Solution: return nxt ``` + +(版本三) 使用 find + +```python +class Solution: + def repeatedSubstringPattern(self, s: str) -> bool: + n = len(s) + if n <= 1: + return False + ss = s[1:] + s[:-1] + print(ss.find(s)) + return ss.find(s) != -1 +``` + +(版本四) 暴力法 + +```python +class Solution: + def repeatedSubstringPattern(self, s: str) -> bool: + n = len(s) + if n <= 1: + return False + + substr = "" + for i in range(1, n//2 + 1): + if n % i == 0: + substr = s[:i] + if substr * (n//i) == s: + return True + + return False +``` + + Go: 这里使用了前缀表统一减一的实现方式 diff --git a/problems/0513.找树左下角的值.md b/problems/0513.找树左下角的值.md index 5ff25484..26768c74 100644 --- a/problems/0513.找树左下角的值.md +++ b/problems/0513.找树左下角的值.md @@ -271,52 +271,80 @@ class Solution { ### Python - -递归: +(版本一)递归法 + 回溯 ```python class Solution: def findBottomLeftValue(self, root: TreeNode) -> int: - max_depth = -float("INF") - leftmost_val = 0 + self.max_depth = float('-inf') + self.result = None + self.traversal(root, 0) + return self.result + + def traversal(self, node, depth): + if not node.left and not node.right: + if depth > self.max_depth: + self.max_depth = depth + self.result = node.val + return + + if node.left: + depth += 1 + self.traversal(node.left, depth) + depth -= 1 + if node.right: + depth += 1 + self.traversal(node.right, depth) + depth -= 1 - def __traverse(root, cur_depth): - nonlocal max_depth, leftmost_val - if not root.left and not root.right: - if cur_depth > max_depth: - max_depth = cur_depth - leftmost_val = root.val - if root.left: - cur_depth += 1 - __traverse(root.left, cur_depth) - cur_depth -= 1 - if root.right: - cur_depth += 1 - __traverse(root.right, cur_depth) - cur_depth -= 1 - - __traverse(root, 0) - return leftmost_val ``` -迭代 - 层序遍历: +(版本二)递归法+精简 ```python class Solution: def findBottomLeftValue(self, root: TreeNode) -> int: - queue = deque() - if root: - queue.append(root) - result = 0 - while queue: - q_len = len(queue) - for i in range(q_len): - if i == 0: - result = queue[i].val - cur = queue.popleft() - if cur.left: - queue.append(cur.left) - if cur.right: - queue.append(cur.right) - return result + self.max_depth = float('-inf') + self.result = None + self.traversal(root, 0) + return self.result + + def traversal(self, node, depth): + if not node.left and not node.right: + if depth > self.max_depth: + self.max_depth = depth + self.result = node.val + return + + if node.left: + self.traversal(node.left, depth+1) + if node.right: + self.traversal(node.right, depth+1) +``` + +(版本三) 迭代法 +```python +# 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 findBottomLeftValue(self, root: Optional[TreeNode]) -> int: + queue = deque([root]) + while queue: + size = len(queue) + leftmost = queue[0].val + for i in range(size): + node = queue.popleft() + if node.left: + queue.append(node.left) + if node.right: + queue.append(node.right) + if not queue: + return leftmost + + ``` ### Go diff --git a/problems/剑指Offer05.替换空格.md b/problems/剑指Offer05.替换空格.md index 2e1ee1de..dbad781e 100644 --- a/problems/剑指Offer05.替换空格.md +++ b/problems/剑指Offer05.替换空格.md @@ -266,6 +266,8 @@ func replaceSpace(s string) string { python: +#### 因为字符串是不可变类型,所以操作字符串需要将其转换为列表,因此空间复杂度不可能为O(1) +(版本一)转换成列表,并且添加相匹配的空间,然后进行填充 ```python class Solution: def replaceSpace(self, s: str) -> str: @@ -290,14 +292,22 @@ class Solution: return ''.join(res) ``` - +(版本二)添加空列表,添加匹配的结果 +```python +class Solution: + def replaceSpace(self, s: str) -> str: + res = [] + for i in range(len(s)): + if s[i] == ' ': + res.append('%20') + else: + res.append(s[i]) + return ''.join(res) +``` +(版本三)使用切片 ```python class Solution: def replaceSpace(self, s: str) -> str: - # method 1 - Very rude - return "%20".join(s.split(" ")) - - # method 2 - Reverse the s when counting in for loop, then update from the end. n = len(s) for e, i in enumerate(s[::-1]): print(i, e) @@ -306,7 +316,18 @@ class Solution: print("") return s ``` - +(版本四)使用join + split +```python +class Solution: + def replaceSpace(self, s: str) -> str: + return "%20".join(s.split(" ")) +``` +(版本五)使用replace +```python +class Solution: + def replaceSpace(self, s: str) -> str: + return s.replace(' ', '%20') +``` javaScript: ```js diff --git a/problems/剑指Offer58-II.左旋转字符串.md b/problems/剑指Offer58-II.左旋转字符串.md index f368514f..6cd88456 100644 --- a/problems/剑指Offer58-II.左旋转字符串.md +++ b/problems/剑指Offer58-II.左旋转字符串.md @@ -142,15 +142,16 @@ class Solution { ``` python: +(版本一)使用切片 ```python -# 方法一:可以使用切片方法 class Solution: def reverseLeftWords(self, s: str, n: int) -> str: - return s[n:] + s[0:n] + return s[n:] + s[:n] ``` +(版本二)使用reversed + join + ```python -# 方法二:也可以使用上文描述的方法,有些面试中不允许使用切片,那就使用上文作者提到的方法 class Solution: def reverseLeftWords(self, s: str, n: int) -> str: s = list(s) @@ -161,32 +162,29 @@ class Solution: return "".join(s) ``` +(版本三)自定义reversed函数 ```python -# 方法三:如果连reversed也不让使用,那么自己手写一个 class Solution: - def reverseLeftWords(self, s: str, n: int) -> str: - def reverse_sub(lst, left, right): - while left < right: - lst[left], lst[right] = lst[right], lst[left] - left += 1 - right -= 1 + def reverseLeftWords(self, s: str, n: int) -> str: + s_list = list(s) - res = list(s) - end = len(res) - 1 - reverse_sub(res, 0, n - 1) - reverse_sub(res, n, end) - reverse_sub(res, 0, end) - return ''.join(res) + self.reverse(s_list, 0, n - 1) + self.reverse(s_list, n, len(s_list) - 1) + self.reverse(s_list, 0, len(s_list) - 1) -# 同方法二 -# 时间复杂度:O(n) -# 空间复杂度:O(n),python的string为不可变,需要开辟同样大小的list空间来修改 + return ''.join(s_list) + + def reverse(self, s, start, end): + while start < end: + s[start], s[end] = s[end], s[start] + start += 1 + end -= 1 ``` +(版本四)使用 模 +下标 ```python 3 -#方法四:考虑不能用切片的情况下,利用模+下标实现 class Solution: def reverseLeftWords(self, s: str, n: int) -> str: new_s = '' @@ -196,17 +194,21 @@ class Solution: return new_s ``` +(版本五)使用 模 + 切片 ```python 3 -# 方法五:另类的切片方法 class Solution: def reverseLeftWords(self, s: str, n: int) -> str: - n = len(s) - s = s + s - return s[k : n+k] + l = len(s) + # 复制输入字符串与它自己连接 + s = s + s + + # 计算旋转字符串的起始索引 + k = n % (l * 2) + + # 从连接的字符串中提取旋转后的字符串并返回 + return s[k : k + l] -# 时间复杂度:O(n) -# 空间复杂度:O(n) ``` Go: diff --git a/problems/面试题02.07.链表相交.md b/problems/面试题02.07.链表相交.md index 4bcbd1f9..dda7f2ad 100644 --- a/problems/面试题02.07.链表相交.md +++ b/problems/面试题02.07.链表相交.md @@ -214,7 +214,41 @@ class Solution: return head ``` ```python -(版本三)等比例法 +(版本三)求长度,同时出发 (代码复用 + 精简) +class Solution: + def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: + dis = self.getLength(headA) - self.getLength(headB) + + # 通过移动较长的链表,使两链表长度相等 + if dis > 0: + headA = self.moveForward(headA, dis) + else: + headB = self.moveForward(headB, abs(dis)) + + # 将两个头向前移动,直到它们相交 + while headA and headB: + if headA == headB: + return headA + headA = headA.next + headB = headB.next + + return None + + def getLength(self, head: ListNode) -> int: + length = 0 + while head: + length += 1 + head = head.next + return length + + def moveForward(self, head: ListNode, steps: int) -> ListNode: + while steps > 0: + head = head.next + steps -= 1 + return head +``` +```python +(版本四)等比例法 # Definition for singly-linked list. # class ListNode: # def __init__(self, x):