classSolution: defmaxArea(self, height: List[int]) -> int: n = len(height) left = 0# 左指针 right = n - 1# 右指针 max_s = 0# 面积最大值 s = 0# 面积 l = 0# 边长 while right > left: if height[left] > height[right]: l = height[right] else: l = height[left] s = (right - left) * l if s > max_s: max_s = s if height[left] > height[right]: right = right - 1 else: left = left + 1 return max_s
classSolution: defthreeSum(self, nums: List[int]) -> List[List[int]]: nums.sort() n = len(nums) ans = list() for i inrange(n): # 固定其中一个元素 if i == 0or nums[i] != nums[i - 1]: k = n - 1 j = i + 1 while k > j: # 进行双指针遍历 if k != n - 1and nums[k] == nums[k + 1]: # 如果右指针之前出现过就跳过 k = k - 1 continue if j != i + 1and nums[j] == nums[j - 1]: # 如果左指针之前出现过就跳过 j = j + 1 continue s = nums[i] + nums[j] + nums[k] if s == 0: ans.append([nums[i], nums[j], nums[k]]) k = k - 1 j = j + 1 elif s > 0: k = k - 1 elif s < 0: j = j + 1 return ans
classSolution: defthreeSumClosest(self, nums: List[int], target: int) -> int: n = len(nums) nums.sort() min_num = 10**9 ans = 0 for i inrange(n): if i != 0and nums[i] == nums[i - 1]: continue k = n - 1 j = i + 1 while k > j: s = nums[i] + nums[j] + nums[k] if s == target: return s if s > target: if s - target < min_num: min_num = s - target ans = s k = k - 1 elif s < target: if target - s < min_num: min_num = target - s ans = s j = j + 1 return ans
classSolution: deffourSum(self, nums: List[int], target: int) -> List[List[int]]: n = len(nums) if nums == [] or n < 4: return [] nums.sort() ans = list() for i inrange(n - 3): if i != 0and nums[i] == nums[i - 1]: continue if nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target: break if nums[i] + nums[n - 1] + nums[n - 2] + nums[n - 3] < target: continue for j inrange(i + 1, n - 2): if j != i + 1and nums[j] == nums[j - 1]: continue if nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target: break if nums[i] + nums[n - 1] + nums[n - 2] + nums[n - 3] < target: continue k = j + 1 l = n - 1 while k < l: sum = nums[i] + nums[j] + nums[k] + nums[l] ifsum < target: k = k + 1 elifsum > target: l = l - 1 elifsum == target: ans.append([nums[i], nums[j], nums[k], nums[l]]) while k < l and nums[k] == nums[k + 1]: k = k + 1 k = k + 1 while k < l and nums[l] == nums[l - 1]: l = l - 1 l = l - 1
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next classSolution: defremoveNthFromEnd(self, head: ListNode, n: int) -> ListNode: right = head left = head for i inrange(n): right = right.next if right == None: # 如果要删除的是头结点 left = left.next return left while right.next != None: left = left.next right = right.next left.next = left.next.next return head
26、删除有序数组中的重复项
1 2 3 4 5 6 7 8 9 10 11 12
classSolution: defremoveDuplicates(self, nums: List[int]) -> int: if nums == []: return0 n = len(nums) left, right = 1, 1 while right < n: if nums[right] != nums[right - 1]: nums[left] = nums[right] left = left + 1 right = right + 1 return left
classSolution: defmerge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: """ Do not return anything, modify nums1 in-place instead. """ i = m - 1 j = n - 1 k = m + n - 1 while i >= 0and j >= 0: if nums1[i] >= nums2[j]: nums1[k] = nums1[i] i -= 1 k -= 1 else: nums1[k] = nums2[j] j -= 1 k -= 1 if i >= 0: while i >= 0: nums1[k] = nums1[i] i -= 1 k -= 1 if j >= 0: while j >= 0: nums1[k] = nums2[j] j -= 1 k -= 1
142、环形链表
对于链表找环路的问题,有一个通用的解法——快慢指针(Floyd
判圈法)。给定两个指针, 分别命名为 slow 和
fast,起始位置在链表的开头。每次 fast 前进两步,slow 前进一步。如果 fast
可以走到尽头,那么说明没有环路;如果 fast
可以无限走下去,那么说明一定有环路,且一定存 在一个时刻 slow 和 fast
相遇。当 slow 和 fast 第一次相遇时,我们将 fast 重新移动到链表开头,并
让 slow 和 fast 每次都前进一步。当 slow 和 fast
第二次相遇时,相遇的节点即为环路的开始点。
# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None
classSolution: defdetectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: slow, fast = head, head whileTrue: ifnot fast ornot fast.next: return slow = slow.next fast = fast.next.next if slow == fast: break fast = head whileTrue: if slow == fast: return fast slow = slow.next fast = fast.next
76、最小覆盖子串
本题使用滑动窗口求解,即两个指针 start 和 end
都是从最左端向最右端移动,且 start 的位置一定在 end
的左边或重合。注意本题虽然在 for 循环里出现了一个 while 循环,但是因为
while 循环负责移动 start 指针,且 start
只会从左到右移动一次,因此总时间复杂度仍然是
O(n)。本题使用了t_disk字典代表t中各个字符的数量,window_disk字典代表目前左右指针指向的子串中各个字符的数量。
classSolution: defminWindow(self, s: str, t: str) -> str: t_disk, window_disk = {}, {} for i inrange(len(t)): if t[i] in t_disk: t_disk[t[i]] += 1 else: t_disk[t[i]] = 1
for key in t_disk: window_disk[key] = 0
start, res, min_len = 0, '', float('inf')
for end inrange(len(s)): if s[end] in window_disk: window_disk[s[end]] += 1 else: window_disk[s[end]] = 1
while self.check_windows(t_disk, window_disk): if min_len > end - start + 1: min_len = end - start + 1 res = s[start: end + 1] window_disk[s[start]] -= 1 start += 1
return res
defcheck_windows(self, s, t): for key in s: if s[key] > t[key]: returnFalse returnTrue