遇到的问题:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hash_map = dict()
for i, x in enumerate(nums):
for j, y in enumerate(nums):
if x + y == target and i != j:
return [i, j]
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hash_map = dict()
for i, x in enumerate(nums):
if hash_map.get(target-x) is not None:
return [hash_map.get(target-x), i]
hash_map[x] = i
更新时间:2022-11-30
遇到的问题:
class Solution:
def maximumProduct(self, nums: List[int]) -> int:
nums.sort()
return max(nums[0]*nums[1]*nums[-1], nums[-1]*nums[-2]*nums[-3])
class Solution:
def maximumProduct(self, nums: List[int]) -> int:
max1, max2, max3 = -inf, -inf, -inf
min1, min2 = inf, inf
for i in nums:
if i > max1:
max3 = max2
max2 = max1
max1 = i
elif i > max2:
max3 = max2
max2 = i
elif i > max3:
max3 = i
if i < min1:
min2 = min1
min1 = i
elif i < min2:
min2 = i
return max(max1*max2*max3, max1*min1*min2)
遇到的问题:
迭代: 无
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
prev = None
while head:
temp = head.next
head.next = prev
prev = head
head = temp
return prev
头递归: 每次迭代后的结果也需要返回,而最后为 None 的返回只是结束条件。需要复习!! (2022-12-02 已重温)
class Solution:
def reverse(self, prev, node):
if node is None:
return prev
temp = node.next
node.next = prev
return self.reverse(node, temp)
def reverseList(self, head: ListNode) -> ListNode:
return self.reverse(None, head)
尾递归: 只记得递归函数是自己的下下个节点指向自己,自己的下个节点指向None,忘记需要使用新的节点来保留递归结果,以及递归需要在反转链表逻辑之前。需要复习!! (2022-12-02 已重温)
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head is None or head.next is None:
return head
new_head = self.reverseList(head.next)
head.next.next = head
head.next = None
return new_head
更新时间:2022-12-01
遇到的问题:
二分查找: 无
class Solution:
def mySqrt(self, x: int) -> int:
left = 0
right = x
while left <= right:
mid = int((left+right)/2)
if mid*mid <= x:
left = mid + 1
else:
right = mid - 1
return left - 1
牛顿递归: 牛顿迭代公式为: x k − 1 = − f ( x k ) f ′ ( x k ) + x k x_{k-1}=-\frac{f(x_k)}{f'(x_k)}+x_k xk−1=−f′(xk)f(xk)+xk,把 r e s 2 − x = 0 res^2 - x = 0 res2−x=0 带入推导就行,记得写代码的时候运算顺序要加括号…
class Solution:
def mySqrt(self, x: int) -> int:
res = x
while abs(res*res - x) > 0.01:
res = res - (res*res - x)/(2*res)
return int(res)
更新时间:2022-12-02
遇到的问题:
单指针: 无
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
left, sums = 0, sum(nums)
for i, x in enumerate(nums):
if left*2 + x == sums:
return i
left += x
return -1
双指针: 无
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
left, right = 0, sum(nums)
for i, x in enumerate(nums):
left += x
if left == right:
return i
right -= x
return -1
更新时间:2022-12-03
遇到的问题:
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
left = 0
for x in nums[1:]:
if nums[left] != x:
left += 1
nums[left] = x
return left + 1
更新时间:2022-12-04
遇到的问题:
暴力算法: 无
class Solution:
def countPrimes(self, n: int) -> int:
def Primes(x):
if x < 2:
return False
for i in range(2, x):
if i * i > x:
break
if x % i == 0:
return False
return True
res = 0
for i in range(n):
if Primes(i) is True:
res += 1
return res
埃氏筛:可以定一个变量来统计质数的数量,避免最后的求和,以及 n 小于 2 的判定,但是理论上没什么区别。
class Solution:
def countPrimes(self, n: int) -> int:
if n < 2:
return 0
res = [1]*n
for i in range(2, n):
if res[i]:
num = i*i
while num < n:
res[num] = 0
num += i
return sum(res) - 2
更新时间:2022-12-07
遇到的问题:
二分查找:无
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
for i in range(len(numbers)):
l, r = i + 1, len(numbers) - 1
target_num = target - numbers[i]
while l <= r:
mid = int((l+r)/2)
if numbers[mid] < target_num:
l = mid + 1
elif numbers[mid] > target_num:
r = mid - 1
else:
return i+1, mid+1
前后指针:无
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
l, r = 0, len(numbers) - 1
while l < r:
if numbers[l] + numbers[r] > target:
r -= 1
elif numbers[l] + numbers[r] < target:
l += 1
else:
return l + 1, r + 1
更新时间:2022-12-07
遇到的问题:
暴力递归:很难想到,一般人可能不这么写这道题目…
class Solution:
def fib(self, n: int) -> int:
if n < 2:
return n
return (self.fib(n-1) + self.fib(n-2)) % 1000000007
去重递归:去重后速度还行,相当于时间复杂度优化为 O ( n ) O(n) O(n) 了,但是空间复杂度也是 O ( n ) O(n) O(n),感觉正常人不会这么写,明显双指针更好想到。
class Solution:
save_res = {0:0, 1:1}
def fib(self, n: int) -> int:
if self.save_res.get(n) is not None:
return self.save_res[n]
self.save_res[n] = (self.fib(n-1) + self.fib(n-2)) % 1000000007
return self.save_res[n]
双指针迭代:最优解以及最容易想到的操作。
class Solution:
def fib(self, n: int) -> int:
if n < 2:
return n
p1, p2 = 0, 1
for _ in range(n-1):
p3 = p2
p2 = p1 + p3
p1 = p3
return p2 % 1000000007
更新时间:2022-12-07
遇到的问题:
暴力迭代: 相比之前程序做优化。快指针不需要知道下标位置,直接对数组遍历即可。
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
left = 0
for x in nums[1:]:
if nums[left] != x:
left += 1
nums[left] = x
return left + 1
二分查找: 需要查找到最后,最后返回左指针的前一个,因为不论是等于还是小于最终都会变成 左指针 = 能够满足的行数 + 1
class Solution:
def arrangeCoins(self, n: int) -> int:
l, r = 0, n
while l <= r:
mid = int((l+r)/2)
if (mid+mid*mid)/2 > n:
r = mid - 1
else:
l = mid + 1
return l - 1
牛顿迭代: 记着牛顿迭代公式: x k − 1 = − f ( x k ) f ′ ( x k ) + x k x_{k-1}=-\frac{f(x_k)}{f'(x_k)}+x_k xk−1=−f′(xk)f(xk)+xk
class Solution:
def arrangeCoins(self, n: int) -> int:
x = n
while abs(x+x*x - 2*n) > 1e-5:
x = (x*x+2*n)/(1+2*x)
return int(x)
数学推导: 解方程,等差数列求和,牛顿迭代也需要, S n = n ( a 1 + a n ) 2 Sn=\frac{n(a1+an)}{2} Sn=2n(a1+an)
class Solution:
def arrangeCoins(self, n: int) -> int:
return int(pow((2*n+1/4),0.5)-1/2)
更新时间:2022-12-08
遇到的问题:
哈希表: 利用对走过的指针进行存储,每次都判断在不在哈希表里,如果在就是环形,不在就添加进去,直到为空。
node_dict = dict()
while head:
if not node_dict.get(head):
node_dict[head] = True
head = head.next
else:
return True
return False
快慢指针: 主要思路就是慢指针一次走一步,快指针一次走两步,利用步长不相同的特点,如果是环形快指针早晚会追上慢指针的思路进行判断。
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
if head is None:
return False
s, q = head, head.next
while q:
if s == q:
return True
if q is None or q.next is None:
return False
s = s.next
q = q.next.next
单指针: 应该叫过河拆桥解法,指针遍历到自己下一个的时候,使用中间变量把之前过来的路断掉,用破坏链表结构的方式来判断是否为环形链表。
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
if head is None:
return False
while head:
if head == 1:
return True
if head is None or head.next is None:
return False
tmp = head.next
head.next = 1
head = tmp
更新时间:2022-12-09
遇到的问题:
直接合并后排序: python可以直接用 nums1[m:] = nums2 替换某几个值。
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
for i, x in enumerate(nums2):
nums1[m+i] = x
nums1.sort()
双指针: 需要开辟额外的存储空间,因为知道了逆向双指针,这个就不太容易想到了,毕竟不是最优解法。
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
res = nums1[:m]
p1, p2 = 0, 0
while p1 != m and p2 != n:
if res[p1] > nums2[p2]:
nums1[p1+p2] = nums2[p2]
p2 += 1
else:
nums1[p1+p2] = res[p1]
p1 += 1
if p1 != m:
nums1[p1+p2:] = res[p1:]
else:
nums1[p1+p2:] = nums2[p2:]
逆向双指针: 最后 列表2 中可能 有值也可能没值,但是不论有没有都可以直接把剩余的赋值到 列表1 中,不用写判断条件。
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
length = n + m
while m != 0 and n != 0:
if nums1[m-1] > nums2[n-1]:
nums1[length-1] = nums1[m-1]
m -= 1
else:
nums1[length-1] = nums2[n-1]
n -= 1
length -= 1
nums1[:n] = nums2[:n]
更新时间:2022-12-10
遇到的问题:
class Solution:
def findMaxAverage(self, nums: List[int], k: int) -> float:
res = -inf
for i in range(len(nums)-k+1):
if sum(nums[i:i+k])/k > res:
res = sum(nums[i:i+k])/k
return res
class Solution:
def findMaxAverage(self, nums: List[int], k: int) -> float:
roll_mean = sum(nums[:k])/k
res = roll_mean
for i in range(len(nums)-k):
roll_mean += (nums[i+k] - nums[i])/k
res = max(res, roll_mean)
return res
更新时间:2022-12-11
遇到的问题:
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if root:
if root.left is None and root.right is None:
return 1
l_depth, r_depth = inf, inf
if root.left:
l_depth = self.minDepth(root.left)
if root.right:
r_depth = self.minDepth(root.right)
return min(l_depth, r_depth) + 1
return 0
import collections
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
quene = collections.deque([[root, 1]])
while quene:
node = quene.popleft()
if node[0]:
if node[0].left is None and node[0].right is None:
return node[1]
quene.append([node[0].left, node[1] + 1])
quene.append([node[0].right, node[1] + 1])
return 0
更新时间:2022-12-12
遇到的问题:
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
res, now_length = 1, 1
for i, j in zip(nums[:-1], nums[1:]):
now_length = now_length + 1 if i < j else 1
res = max(res, now_length)
return res
更新时间:2022-12-13
遇到的问题:
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
dollar_5, dollar_10 = 0, 0
for i in bills:
if i == 5:
dollar_5 += 1
elif i == 10:
if dollar_5 > 0:
dollar_5 -= 1
dollar_10 += 1
else:
return False
else:
if dollar_5 > 0 and dollar_10 > 0:
dollar_5 -= 1
dollar_10 -= 1
elif dollar_5 > 2:
dollar_5 -= 3
else:
return False
return True
更新时间:2022-12-14
遇到的问题:
class Solution:
def largestPerimeter(self, nums: List[int]) -> int:
nums.sort()
for i in range(len(nums)-3, -1, -1):
if nums[i] + nums[i+1] > nums[i+2]:
return sum(nums[i:i+3])
return 0
更新时间:2022-12-15
遇到的问题:
维护后缀最小值: 忘记了,这种算法是为了维持除了当前数值的下一个不可能还有数比现在的数要小,改进了一下写法,感觉这种更好写一点,倒序去做是为了能够一直维护最小值的变量。需要复习!! (2022-12-20 已重温)
class Solution:
def isIdealPermutation(self, nums: List[int]) -> bool:
min_num = inf
for i in range(len(nums)-1, 1, -1):
min_num = min(min_num, nums[i])
if min_num < nums[i-2]:
return False
return True
相同含义的写法,只不过是暴力的,不能优化重复计算最小值,导致超时,这里要注意,上面的做法之所以是倒序是因为正序遍历去判断是没办法获取到最小值的,因为有没遍历到的值,但是倒叙就可以:
class Solution:
def isIdealPermutation(self, nums: List[int]) -> bool:
for i in range(len(nums)-2):
if nums[i] > min(nums[i+2:]):
return False
return True
归纳证明: 想到了当时力扣官方题解的原理,当前下标不能和当前数值相差超过1…
class Solution:
def isIdealPermutation(self, nums: List[int]) -> bool:
for i, x in enumerate(nums):
if abs(i-x) > 1:
return False
return True
更新时间:2022-12-16
遇到的问题:
class Solution:
def recurse(self, root, res):
if root is None:
return res
res.append(root.val)
self.recurse(root.left, res)
self.recurse(root.right, res)
return res
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
return self.recurse(root, [])
更新时间:2022-12-17
遇到的问题:
class Solution:
def recurse(self, root, res):
if root is None:
return res
self.recurse(root.left, res)
res.append(root.val)
self.recurse(root.right, res)
return res
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
return self.recurse(root, [])
遇到的问题:
class Solution:
def recurse(self, root, res):
if root is None:
return res
self.recurse(root.left, res)
self.recurse(root.right, res)
res.append(root.val)
return res
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
return self.recurse(root, [])
更新时间:2022-12-18
遇到的问题:
class Solution:
def recurse(self, root, res, deep):
if root is None:
return res
if len(res) == deep:
res.append([])
res[deep].append(root.val)
self.recurse(root.left, res, deep+1)
self.recurse(root.right, res, deep+1)
return res
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
return self.recurse(root, [], 0)
更新时间:2022-12-19
遇到的问题:
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = []
stack = [root]
while stack:
node = stack.pop()
if node is not None:
res.append(node.val)
stack.append(node.right)
stack.append(node.left)
return res
遇到的问题:
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res, stack = [], []
node = root
while stack or node:
while node:
stack.append(node)
node = node.left
node = stack.pop()
res.append(node.val)
node = node.right
return res
更新时间:2022-12-20
遇到的问题:
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
prev = None
res, stack = [], []
while root or stack:
while root:
stack.append(root)
root = root.left
root = stack.pop()
if root.right is None or root.right == prev:
res.append(root.val)
prev = root
root = None
else:
stack.append(root)
root = root.right
return res
更新时间:2022-12-21
遇到的问题:
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
stack = [[root, 0]]
res = []
while stack:
node, deep = stack.pop()
if node:
if len(res) < deep+1:
res.append([])
res[deep].append(node.val)
stack.append([node.right, deep+1])
stack.append([node.left, deep+1])
return res
更新时间:2022-12-22
遇到的问题:
class Solution:
def countBalls(self, lowLimit: int, highLimit: int) -> int:
res, box_counts = 0, {}
for i in range(lowLimit, highLimit + 1):
box, value = 0, i
while value != 0:
box += value % 10
value //= 10
if box_counts.get(box):
box_counts[box] += 1
else:
box_counts[box] = 1
res = max(box_counts[box], res)
return res
更新时间:2023-01-03
遇到的问题:
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = []
while root:
mostright = root.left
if mostright:
while mostright.right and mostright.right != root:
mostright = mostright.right
if mostright.right is None:
mostright.right = root
res.append(root.val)
root = root.left
continue
else:
mostright.right = None
else:
res.append(root.val)
root = root.right
return res
遇到的问题:
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = []
while root:
mostright = root.left
if mostright:
while mostright.right and mostright.right != root:
mostright = mostright.right
if mostright.right is None:
mostright.right = root
root = root.left
continue
else:
mostright.right = None
res.append(root.val)
root = root.right
return res
更新时间:2023-01-04
遇到的问题:
class Solution:
def reversal(self, node):
prev = None
while node:
temp = node.right
node.right = prev
prev = node
node = temp
return prev
def nodeprint(self, node, res):
node = self.reversal(node)
mid = node
while mid:
res.append(mid.val)
mid = mid.right
self.reversal(node)
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
node, res = root, []
while root:
rightnode = root.left
if rightnode:
while rightnode.right and rightnode.right != root:
rightnode = rightnode.right
if rightnode.right is None:
rightnode.right = root
root = root.left
continue
else:
rightnode.right = None
self.nodeprint(root.left, res)
root = root.right
self.nodeprint(node, res)
return res
更新时间:2023-01-05
遇到的问题:
class Solution:
def dfs(self, i, length, isConnected, visit_map):
for j in range(length):
if isConnected[i][j] == 1 and visit_map[j]:
visit_map[j] = False
self.dfs(j, length, isConnected, visit_map)
def findCircleNum(self, isConnected: List[List[int]]) -> int:
length, res = len(isConnected), 0
visit_map = [True] * length
for i in range(length):
if visit_map[i]:
self.dfs(i, length, isConnected, visit_map)
res += 1
return res
更新时间:2023-01-06
遇到的问题:
class Solution:
def findCircleNum(self, isConnected: List[List[int]]) -> int:
length, res = len(isConnected), 0
visit_map = [True] * length
for i in range(length):
if visit_map[i]:
citys = [i]
while citys:
now_city = citys.pop()
visit_map[now_city] = False
for j in range(length):
if visit_map[j] and isConnected[now_city][j]:
citys.append(j)
res += 1
return res
更新时间:2023-01-07
遇到的问题:
class Solution:
def findCircleNum(self, isConnected: List[List[int]]) -> int:
def find(i):
if root[i] != i:
root[i] = find(root[i])
return root[i]
def merge(i, j):
roota, rootb = find(i), find(j)
if roota != rootb:
# 根节点改变,需要注意是 root[roota] = rootb,而不是 root[i] = rootb
root[roota] = rootb
length = len(isConnected)
root = list(range(length))
for i in range(length):
for j in range(i+1, length):
if isConnected[i][j] == 1:
merge(i, j)
return sum(i == root[i] for i in range(length))
更新时间:2023-01-08
遇到的问题:
class Solution:
def minOperations(self, s: str) -> int:
q1, q2 = 0, 0
for i in range(len(s)):
if i % 2 != 1:
if s[i] == "0":
q1 += 1
else:
q2 += 1
else:
if s[i] == "0":
q2 += 1
else:
q1 +=1
return min(q1, q2)
class Solution:
def minOperations(self, s: str) -> int:
res = sum(i % 2 == int(x) for i, x in enumerate(s))
return min(res, len(s) - res)
更新时间:2023-01-09