class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
visited = set()
for num in nums:
if num in visited:
return num
visited.add(num)
站在右上角看
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
if not matrix:
return False
m, n = len(matrix), len(matrix[0])
i, j = 0, n - 1
while 0 <= i < m and 0 <= j < n:
if matrix[i][j] == target:
return True
elif matrix[i][j] > target:
j -= 1
elif matrix[i][j] < target:
i += 1
return False
二分法的话可以对每一行二分,但是还不如按照二叉搜索树来找。
class Solution:
def replaceSpace(self, s: str) -> str:
words = s.split(' ')
return '%20'.join(words)
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
nums = []
cur = head
while cur:
nums.append(cur.val)
cur = cur.next
return nums[::-1]
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
def recur(root, left, right):
'''
root: 先序遍历中的根节点坐标
left: 中序遍历中左子树的左边界
right: 中序遍历中右子树的右边界
'''
if left > right: return
# 建立根节点
node = TreeNode(preorder[root])
i = dic[preorder[root]] # 找到根节点在中序遍历中的位置
node.left = recur(root + 1, left, i-1) # 重建左子树
node.right = recur(i - left + root + 1, i+1, right) # 重建右子树
return node
dic = {}
for i, num in enumerate(inorder):
dic[num] = i
return recur(0, 0, len(inorder) - 1)
class CQueue:
def __init__(self):
self.stack1 = []
self.stack2 = []
def appendTail(self, value: int) -> None:
self.stack1.append(value)
def deleteHead(self) -> int:
if self.stack2:
return self.stack2.pop()
while self.stack1:
self.stack2.append(self.stack1.pop())
if self.stack2:
return self.stack2.pop()
return -1
class CQueue:
def __init__(self):
self.stack1 = []
self.stack2 = []
def appendTail(self, value: int) -> None:
self.stack1.append(value)
def deleteHead(self) -> int:
if self.stack2:
return self.stack2.pop()
if not self.stack1: return -1
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2.pop()
class Solution:
def fib(self, n: int) -> int:
# 迭代
if n < 2: return n
a, b = 0, 1
for _ in range(n-1):
c = int((a + b) % (1e9+7))
a = b
b = c
return c
class Solution:
def fib(self, n: int) -> int:
# 强行递归,会超时
if n < 2: return n
return (self.fib(n-1) + self.fib(n-2)) % (1e9+7)
class Solution:
@lru_cache
def fib(self, n: int) -> int:
# 强行递归,会超时
if n < 2: return n
return int((self.fib(n-1) + self.fib(n-2)) % (1e9+7))
自己实现LRU_Cache
import collections
class LRU_Cache:
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if args in self.cache:
return self.cache[args]
else:
self.cache[args] = self.func(*args)
return self.cache[args]
def fib(n):
if n < 2: return n
return fib(n-1) + fib(n-2)
print(fib(10))
class Solution:
def numWays(self, n: int) -> int:
if n == 0: return 1
if n <= 2: return n
a, b = 1, 1
for _ in range(n-1):
c = int((a + b) % (1e9 + 7))
a = b
b = c
return c
class Solution:
def minArray(self, numbers: List[int]) -> int:
# 二分法
n = len(numbers)
l, r = 0, n - 1
while l < r:
mid = l + (r - l) // 2
# 后半段是无序, 最小值肯定在前半段
if numbers[mid] < numbers[r]:
r = mid
# 后半段是有序的,但是不能确定最小值一定在后半段
elif numbers[mid] > numbers[r]:
l = mid + 1
else:
r -= 1
return numbers[l]
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
def dfs(i, j, k):
if k >= len(word): return True
if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or board[i][j] != word[k]:
return False
if not board[i][j]: return False
board[i][j] = ''
up = dfs(i-1, j, k+1)
down = dfs(i+1, j, k+1)
left = dfs(i, j-1, k+1)
right = dfs(i, j+1, k+1)
board[i][j] = word[k] # 取消操作
return up or down or left or right
m, n = len(board), len(board[0])
visited = [[False] * n for _ in range(m)]
for i in range(m):
for j in range(n):
if board[i][j] == word[0]:
res = dfs(i, j, 0)
if res: return True
return False
class Solution:
def cuttingRope(self, n: int) -> int:
# 拆成2,3就行了
# 因为2只能拆成1+1,而1x1=1<2
# 3只能拆成2+1或者1+1+1,乘积都小于3,而4就开始不一样了
if n == 2: return 1
if n == 3: return 2
three_nums = n // 3
left = n % 3
if left == 1:
three_nums -= 1
left += 3
elif left == 0:
left = 1
return 3 ** three_nums * left
class Solution:
def cuttingRope(self, n: int) -> int:
# 本题不可以先拆再直接算,因为中间有些值可能过大,需要取模
if n == 2: return 1
if n == 3: return 2
res = 1
while n > 0:
if 2 <= n <= 4:
break
n = n - 3
res = int((res * 3) % (1e9+7))
return int((res * n) % (1e9+7))
class Solution:
def hammingWeight(self, n: int) -> int:
res = 0
while n:
res += n & 1
n = n >> 1
return res
递归,但是递归会出现超出最大递归深度。
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0: return 1
if n > 0: return self.myPow(x, n-1) * x
else: return 1 / (self.myPow(x, abs(n)-1) * x)
class Solution:
def myPow(self, x: float, n: int) -> float:
# 快速幂解法
def quickMul(x, N):
if N == 0: return 1
y = quickMul(x, N // 2)
return y * y if N % 2 == 0 else y * y * x
return quickMul(x, n) if n > 0 else 1 / quickMul(x, abs(n))
主要是考大数问题,不考虑大数问题的话就过于简单了。
class Solution:
def printNumbers(self, n: int) -> List[int]:
# 直接计算最大的n位数是多少
n = int('9' * n)
return list(range(1, n+1))
class Solution:
def deleteNode(self, head: ListNode, val: int) -> ListNode:
dummy = ListNode(-1, head)
pre = dummy
cur = head
while cur and cur.val != val:
pre = cur
cur = cur.next
if cur:
pre.next = cur.next
else:
return head
return dummy.next
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
l = 0
n = len(nums)
for r in range(n):
if nums[r] % 2 == 1:
nums[l], nums[r] = nums[r], nums[l]
l += 1
return nums
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
slow, fast = head, head
for _ in range(k):
fast = fast.next
while fast:
slow = slow.next
fast = fast.next
return slow
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
pre = None
cur = head
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
dummy = ListNode(-1)
cur = dummy
while l1 and l2:
if l1.val < l2.val:
cur.next = ListNode(l1.val)
l1 = l1.next
else:
cur.next = ListNode(l2.val)
l2 = l2.next
cur = cur.next
if l1: cur.next = l1
elif l2: cur.next = l2
return dummy.next
class Solution:
def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
def recur(A, B):
if not B: return True
if not A or A.val != B.val: return False
left = recur(A.left, B.left)
right = recur(A.right, B.right)
return left and right
return bool(A and B) and (recur(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))
class Solution:
def mirrorTree(self, root: TreeNode) -> TreeNode:
# 不断反转左右子树
def recur(root):
if not root: return
root.left, root.right = root.right, root.left
recur(root.left)
recur(root.right)
return root
return recur(root)
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root: return True
def recur(left, right):
if not left and not right: return True
if (left and not right) or (not left and right) or (left.val != right.val): return False
# 如果是叶子节点,并且两个节点的值一样,才返回true
if (left and not left.left and not left.right) and (right and right.left and right.right):
if left.val == right.val: return True
outer = recur(left.left, right.right)
inner = recur(left.right, right.left)
return outer and inner
return recur(root.left, root.right)
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root: return True
queue = [root.left, root.right]
while queue:
inner, outer = queue.pop(0), queue.pop(0)
# 判断不对称
if (inner and not outer) or (not inner and outer): return False
if inner and outer and inner.val != outer.val: return False
if inner and outer:
queue.append(inner.left)
queue.append(outer.right)
queue.append(inner.right)
queue.append(outer.left)
return True
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
# 给每一个数加一个最小值的元素就行
self.data = []
def push(self, x: int) -> None:
if self.data:
top_num, min_num = self.data[-1]
min_num = min(min_num, x)
self.data.append((x, min_num))
else:
self.data.append((x, x))
def pop(self) -> None:
tmp, _ = self.data.pop()
return tmp
def top(self) -> int:
tmp, _ = self.data[-1]
return tmp
def min(self) -> int:
_, tmp = self.data[-1]
return tmp
用一个栈进行模拟,每次从pushed进行入栈,如果栈顶元素等于popped第一个元素,就不断对栈进行pop,最后看popped有没有走到头
class Solution:
def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
stack = []
j = 0
for num in pushed:
stack.append(num)
while stack and stack[-1] == popped[j]:
stack.pop()
j += 1
if j == len(popped): return True
return False
class Solution:
def levelOrder(self, root: TreeNode) -> List[int]:
res = []
if not root: return res
queue = [root]
while queue:
n = len(queue)
for _ in range(n):
node = queue.pop(0)
res.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
return res
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
res = []
if not root: return res
queue = [root]
while queue:
n = len(queue)
tmp = []
for _ in range(n):
node = queue.pop(0)
tmp.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
res.append(tmp)
return res
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
res = []
if not root: return res
queue = [root]
flag = True
while queue:
n = len(queue)
tmp = []
for _ in range(n):
node = queue.pop(0)
tmp.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
if flag: res.append(tmp)
else: res.append(tmp[::-1])
flag = not flag
return res
后序遍历的结果为:[左子树|右子树|根节点]
。根节点一定在最后,左子树一定比根节点小,右子树一定比根节点大。因此每次递归找到第一个比根节点大的值作为左右子树的分界点,然后按照左子树,右子树分开递归。
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
def recur(i, j):
if i >= j: return True
p = i
while postorder[p] < postorder[j]: p += 1
m = p
while postorder[p] > postorder[j]: p += 1
return p == j and recur(i, m-1) and recur(m, j-1)
return recur(0, len(postorder) - 1)
class Solution:
def pathSum(self, root: TreeNode, target: int) -> List[List[int]]:
paths, path = [], []
def recur(root, target):
if not root: return
target -= root.val
path.append(root.val)
if target == 0 and not root.left and not root.right:
paths.append(path[:])
recur(root.left, target)
recur(root.right, target)
target += root.val
path.pop()
recur(root, target)
return paths
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
# 先把当前链表中的所有节点的值复制到新链表上,然后再复制指针
if not head: return head
dic = {}
cur = head
while cur:
dic[cur] = Node(cur.val)
cur = cur.next
# 复制指针
cur = head
while cur:
dic[cur].next = dic.get(cur.next)
dic[cur].random = dic.get(cur.random)
cur = cur.next
return dic[head]
class Solution:
def permutation(self, s: str) -> List[str]:
paths = []
if not s: return paths
path = ''
used = [False] * len(s)
def backtracking(s, path, used):
if len(path) == len(s):
paths.append(path)
return
for i in range(len(s)):
if not used[i]:
if i > 0 and s[i-1] == s[i] and not used[i-1]:
continue
used[i] = True
path += s[i]
backtracking(s, path, used)
path = path[:-1]
used[i] = False
s = sorted(s)
backtracking(s, path, used)
return paths
class Solution:
def majorityElement(self, nums: List[int]) -> int:
if len(nums) < 3: return nums[0]
nums.sort()
return nums[len(nums) // 2]
用哈希表最好
class Solution:
def majorityElement(self, nums: List[int]) -> int:
dic = {}
for num in nums:
if num not in dic:
dic[num] = 0
else:
dic[num] += 1
for k, v in dic.items():
if v >= len(nums) // 2:
return k
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
arr.sort()
return arr[:k]
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
nums = self.quickSort(arr, 0, len(arr) - 1)
return nums[:k]
def quickSort(self, nums, i, j):
# 快排一定要记住
# https://zhuanlan.zhihu.com/p/63227573
if i > j: return
pivot = nums[i]
low = i
high = j
while i < j:
while i < j and nums[j] > pivot:
j -= 1
nums[i] = nums[j]
while i < j and nums[i] <= pivot:
i += 1
nums[j] = nums[i]
nums[j] = pivot
self.quickSort(nums, low, i-1)
self.quickSort(nums, i+1, high)
return nums
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
if n < 2: return sum(nums)
dp = [0] * n
dp[0] = nums[0]
for i in range(1, len(nums)):
dp[i] = max(dp[i-1] + nums[i], nums[i])
return max(dp)
class Solution:
def translateNum(self, num: int) -> int:
# 就是看怎么划分,可以使每一个数都处在0到25之间
s = str(num)
n = len(s)
if n < 2: return 1
dp = [0] * n
dp[0] = 1
if s[0] == '0':
dp[1] = 1
else:
dp[1] = 2 if int(s[:2]) < 26 else 1
for i in range(2, len(s)):
if s[i-1] == '0':
dp[i] = dp[i-1]
else:
dp[i] = dp[i-1] + dp[i-2] if int(s[i-1:i+1]) < 26 else dp[i-1]
return dp[-1]
class Solution:
def maxValue(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
if m == 1 or n == 1:
res = 0
for i in range(m):
for j in range(n):
res += grid[i][j]
return res
dp = [[0] * n for _ in range(m)]
dp[0][0] = grid[0][0]
for i in range(1, n):
dp[0][i] = dp[0][i-1] + grid[0][i]
for i in range(1, m):
dp[i][0] = dp[i-1][0] + grid[i][0]
for i in range(1, m):
for j in range(1, n):
dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + grid[i][j]
return dp[-1][-1]
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
if n < 2: return n
dic = {}
max_length = -1
i = -1
for j, c in enumerate(s):
if c in dic:
i = max(dic[c], i)
dic[c] = j
max_length = max(max_length, j-i)
return max_length
class Solution:
def firstUniqChar(self, s: str) -> str:
if not s: return ' '
dic = {}
for c in s:
if c not in dic:
dic[c] = 1
else:
dic[c] += 1
for c in s:
if dic[c] == 1:
return c
return ' '
class Solution:
def getIntersectionNode(self, l1: ListNode, l2: ListNode) -> ListNode:
p1, p2 = l1, l2
while p1 != p2:
p1 = p1.next if p1 else l2
p2 = p2.next if p2 else l1
return p1
class Solution:
def trap(self, height: List[int]) -> int:
# 双指针多次遍历
n = len(height)
# 先找到位置i+1左边最高的柱子,虽然我们dp的时候求的是第i列左边,含第i列最大的柱子,但是实际上使用的时候是看i+1列
maxLeft = [0] * n
maxLeft[0] = height[0]
for i in range(1, n):
maxLeft[i] = max(maxLeft[i-1], height[i])
# 再找到i-1列右边最高的柱子
maxRight = [0] * n
maxRight[-1] = height[-1]
for i in range(n-2, -1, -1):
maxRight[i] = max(maxRight[i+1], height[i])
# 求和
res = 0
for i in range(1, n-1):
tmp = min(maxLeft[i-1], maxRight[i+1]) - height[i]
res += tmp if tmp > 0 else 0
return res
小红书推荐算法面试题,不难,dp很容易做。
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
# 2
# 3 4
# 5 6 7
# 8 9 10 11
m = len(triangle)
if m < 2: return triangle[0][0]
dp = []
for i in range(m):
if i == 0:
dp.append([triangle[0][0]])
else:
tmp = [0] * (i+1)
for j in range(i+1):
if j == 0:
tmp[j] = dp[i-1][0] + triangle[i][0]
elif j == i:
tmp[j] = dp[i-1][-1] + triangle[i][-1]
else:
tmp[j] = min(dp[i-1][j-1], dp[i-1][j]) + triangle[i][j]
dp.append(tmp[:])
return min(dp[-1])
优化一下:
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
n = len(triangle)
dp = [[0] * i for i in range(1, n+1)]
dp[0][0] = triangle[0][0]
for i in range(1, n):
dp[i][0] = triangle[i][0] + dp[i-1][0]
for j in range(1, i):
dp[i][j] = min(dp[i-1][j], dp[i-1][j-1]) + triangle[i][j]
dp[i][-1] = triangle[i][-1] + dp[i-1][-1]
return min(dp[-1])
class Solution:
def search(self, nums: List[int], target: int) -> int:
dic = collections.Counter(nums)
return dic[target]
很明显不是最优解,因为原始数组是有序的,因此肯定可以使用二分,二分找出左右边界,然后求差即可。
class Solution:
def search(self, nums: List[int], target: int) -> int:
# 使用二分查到target出现的左边界和有边界
# 之后左右边界之差加上1就行了
if not nums: return 0
leftBorder, rightBorder = self.searchLeft(nums, target), self.searchRight(nums, target)
if leftBorder == -2 or rightBorder == -2: return 0
if nums[leftBorder+1] != nums[rightBorder-1]: return 0
return rightBorder - leftBorder - 1
def searchRight(self, nums, target):
l, r = 0, len(nums) - 1
rightBorder = -2
while l <= r:
mid = l + (r - l) // 2
if nums[mid] <= target:
l = mid + 1
rightBorder = l
else:
r = mid - 1
return rightBorder
def searchLeft(self, nums, target):
l, r = 0, len(nums) - 1
leftBorder = -2
while l <= r:
mid = l + (r - l) // 2
if nums[mid] < target:
l = mid + 1
else:
r = mid - 1
leftBorder = r
return leftBorder
此外,因为是排序数组,因此最直接的方法就是双指针,首先两个指针一起走,遇到taregt之后,左指针固定,右指针继续走,直到右指针指到不等于target的值。
class Solution:
def search(self, nums: List[int], target: int) -> int:
if len(nums) == 1: return 1 if nums[0] == target else 0
l, r = 0, 0
for i, num in enumerate(nums):
if l == r and nums[r] != target:
l += 1
r += 1
elif nums[r] == target:
r += 1
elif l != r and nums[r] != target:
return r - l
if r == len(nums): return r - l
return 0
笨方法,哈希表。
class Solution:
def missingNumber(self, nums: List[int]) -> int:
dic = collections.Counter(nums)
for i in range(len(nums)+1):
if i not in dic:
return i
二分法,二分的关键是看当前位置的数等不等于下标,等于下标的话就说明缺失的值在右边,否则就在左边。
class Solution:
def missingNumber(self, nums: List[int]) -> int:
l, r = 0, len(nums) - 1
while l <= r:
m = l + (r - l) // 2
if nums[m] == m: l = m + 1
else: r = m - 1
return l
class Solution:
def __init__(self):
self.cnt = 0
self.ans = 0
def kthLargest(self, root: TreeNode, k: int) -> int:
# 中序遍历是一个递增数列
# 最暴力的方法就是先中序遍历,之后按下标找第k个元素即可
# 最好的做法时一次性递归,维护一个计数器,记录是不是走到了第k个数
def dfs(root):
if not root: return
dfs(root.right)
self.cnt += 1
if self.cnt == k:
self.ans = root.val
return
dfs(root.left)
dfs(root)
return self.ans
class Solution:
def maxDepth(self, root: TreeNode) -> int:
def dfs(root):
if not root: return 0
leftDepth = dfs(root.left)
rightDepth = dfs(root.right)
depth = max(leftDepth, rightDepth) + 1
return depth
return dfs(root)
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
#
def recur(root):
if not root: return 0
left = recur(root.left)
if left == -1: return -1
right = recur(root.right)
if right == -1: return -1
return max(left, right) + 1 if abs(right - left) <= 1 else -1
return recur(root) != -1
更易想到的解法:
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
if not root: return True
left_depth = self.getDepth(root.left)
right_depth = self.getDepth(root.right)
return abs(right_depth - left_depth) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)
def getDepth(self, root):
if not root: return 0
return max(self.getDepth(root.left), self.getDepth(root.right)) + 1
class Solution:
def singleNumbers(self, nums: List[int]) -> List[int]:
# x ^ x == 0
# x ^ 0 = x
n = 0
for num in nums:
n = n ^ num
# 因为有两个只出现过一次的数,因此一次异或得到的结果只是x^y
# 因为x,y不一样,所以x与y必然至少有一个不一样,因此找到其中一位
m = 1
while n & m == 0:
m <<= 1
# 找到m后,按照m可以将原数组分成两份,分别是与m进行&之后是0的,和是1的
x, y = 0, 0
for num in nums:
if num & m: x ^= num
else: y ^= num
return x, y
class Solution:
def singleNumber(self, nums: List[int]) -> int:
dic = collections.Counter(nums)
for k, v in dic.items():
if v == 1: return k
其他题解
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dic = {}
for i, num in enumerate(nums):
if target - num in dic:
return [num, target - num]
else:
dic[num] = i
return [-1, -1]
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
l, r = 0, len(nums) - 1
while l < r:
s = nums[l] + nums[r]
if s > target:
r -= 1
elif s < target:
l += 1
else:
return [nums[l], nums[r]]
return [-1, -1]
class Solution:
def findContinuousSequence(self, target: int) -> List[List[int]]:
# 因为都是正数,所以在一个区间内去掉一个数和必然会减小,加上一个数和必然会增加
l, r = 1, 2
s = 3
res = []
while l < r:
if s == target:
res.append(list(range(l, r+1)))
if s < target:
r += 1
s += r
# 之所以在s==target的时候也继续移动左指针,是因为可能多移动几次,在移动一次右指针又满足条件了
# 比如:[2,3,4]和[4,5]
elif s >= target:
s -= l
l += 1
return res
class Solution:
def reverseWords(self, s: str) -> str:
# 删除前缀空格和后缀空格
s = s.strip()
words = s.split()
return ' '.join(words[::-1])
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
return s[n:] + s[:n]
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
if not nums: return []
deque = collections.deque()
# 先构造一个初始的队列
for i in range(k):
while deque and deque[-1] < nums[i]: deque.pop()
deque.append(nums[i])
res = [deque[0]]
for i in range(k, len(nums)):
if nums[i-k] == deque[0]:
deque.popleft()
while deque and deque[-1] < nums[i]:deque.pop()
deque.append(nums[i])
res.append(deque[0])
return res
使用队列来模拟约瑟夫环,效率比较低,因此会超时。
class Solution:
def lastRemaining(self, n: int, m: int) -> int:
deque = collections.deque()
for i in range(n):
deque.append(i)
while len(deque) > 1:
for _ in range(m % n):
tmp = deque.popleft()
deque.append(tmp)
deque.pop()
return deque[0]
递归法:
class Solution:
def lastRemaining(self, n: int, m: int) -> int:
def dfs(n, m):
if n == 1: return 0
x = dfs(n-1, m)
return (x + m) % n
return dfs(n, m)
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if not prices: return 0
res = 0
min_price = prices[0]
for price in prices:
if price < min_price:
min_price = price
else:
res = max(res, price - min_price)
return res
class Solution:
def sumNums(self, n: int) -> int:
def recur(n, s):
if n == 1: return s + 1
return recur(n-1, s) + n
return recur(n, 0)
class Solution:
def sumNums(self, n: int) -> int:
# 因为不能使用循环,因此只能使用递归来实现
# 但是递归需要有终止条件,终止条件通常都是if语句
# 所以,还需要解决if语句代替问题,在python中,当and前为false时,后面的运算会自动终止
# 因此,可以使用and来代替
return n and (n + self.sumNums(n-1))
class Solution:
def constructArr(self, a: List[int]) -> List[int]:
n = len(a)
if n < 2: return a
dp_left, dp_right = [1] * n, [1] * n
for i in range(1, n-1):
dp_left[i] = dp_left[i-1] * a[i-1]
dp_right[n-i-1] = dp_right[n-i] * a[n-i]
dp_left[-1] = dp_left[-2] * a[-2]
dp_right[0] = dp_right[1] * a[1]
b = []
for i in range(n):
b.append(dp_left[i] * dp_right[i])
return b
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root: return
if p.val <= root.val and q.val >= root.val:
return root
if p.val >= root.val and q.val <= root.val:
return root
if p.val < root.val and q.val < root.val:
return self.lowestCommonAncestor(root.left, p, q)
elif p.val > root.val and q.val > root.val:
return self.lowestCommonAncestor(root.right, p, q)
只要 p , q p,q p,q存在于当前子树上,返回值就不为空。
class Solution:
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
if not root or root.val == p.val or root.val == q.val: return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if not left and not right: return # 左右都为空,没有p,q
if not left and right: return right # pq走在右侧
if not right and left: return left, # pq都在左侧
return root # 左右都不为空,说明pq在异侧
这题稍微有点问题,max操作不可能是 O ( 1 ) O(1) O(1)的
class MaxQueue:
def __init__(self):
self.data = []
self.deque = collections.deque()
def max_value(self) -> int:
if not self.deque:
return -1
return self.deque[0]
def push_back(self, value: int) -> None:
while self.deque and self.deque[-1] < value:
self.deque.pop()
self.data.append(value)
self.deque.append(value)
def pop_front(self) -> int:
if not self.data:
return -1
ans = self.data.pop(0)
if ans == self.deque[0]:
self.deque.popleft()
return ans
class Solution:
def isStraight(self, nums: List[int]) -> bool:
repeat = set()
mi, ma = float('inf'), -float('inf')
for num in nums:
if num == 0: continue
ma = max(ma, num)
mi = min(mi, num)
if num in repeat: return False
repeat.add(num)
return True if ma - mi < 5 else False