本文章用来记录自己第二次刷题遇到的各种问题
面试题03. 数组中重复的数字
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
解题思路:一开始想到哈希表。然后看视频发现可以原地交换,具体思路为:
遍历列表,如果nums[i] 不在 i位置上,判断nums[i]是否等于nums[nums[i]],如果相等,就返回,不相等, 把nums[i] 放到 i位置上,继续找下一个。
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
for i in range(len(nums)):
if nums[i] != i:
if nums[i] == nums[nums[i]]:
return nums[i]
else:
nums[nums[i]],nums[i] = nums[i],nums[nums[i]]
# nums[i],nums[nums[i]] = nums[nums[i]],nums[i]
注意:Python 中, a, b = c, d 操作的原理是先暂存元组 (c, d) ,然后 “按顺序” 赋值给 a 和 b 。因此,若写为 nums[i], nums[nums[i]] = nums[nums[i]], nums[i] ,则 nums[i] 先被赋值,之后 nums[nums[i]] 指向的元素则会出错。
面试题04. 二维数组中的查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
解题思路: 第一种方法:遍历,时间复杂度 O(n)
第二种,和右上角的比较,比他大就往下走,比他小就往左走
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
if matrix == []:return False
row = len(matrix)
cloumn = len(matrix[0])
if row == 1 and cloumn == 1:
return True if matrix[0][0] == target else False
i = 0
j = cloumn - 1
while 0 <= i < row and 0 <= j < cloumn:
if matrix[i][j] == target:
return True
elif matrix[i][j] > target:
j -= 1
else:
i += 1
return False
面试题05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
class Solution:
def replaceSpace(self, s: str) -> str:
b = ''
for i in s:
if i == ' ':
b = b + '%20'
else:
b = b + i
return b
面试题06. 从尾到头打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
#第一种方法,递归,第二种,辅助栈
# return self.reversePrint(head.next) + [head.val] if head else []
stack = []
while head:
stack.append(head.val)
head = head.next
res = []
while stack:
res.append(stack.pop())
return res
面试题07. 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not preorder or not inorder:return None
root = TreeNode(preorder[0])
index = inorder.index(preorder[0])
root.left = self.buildTree(preorder[1:index+1],inorder[:index])
root.right = self.buildTree(preorder[index+1:],inorder[index+1:])
return root
面试题09. 用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
解题思路:没啥好说的,就是干!
class CQueue:
def __init__(self):
self.input_stack = []
self.output_stack = []
def appendTail(self, value: int) -> None:
self.input_stack.append(value)
def deleteHead(self) -> int:
if self.output_stack == []:
while self.input_stack:
self.output_stack.append(self.input_stack.pop())
if self.output_stack:
return self.output_stack.pop()
else:
return -1
面试题10- I. 斐波那契数列
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
class Solution:
def fib(self, n: int) -> int:
if n == 0:return 0
if n == 1:return 1
# 这种方法TLE,因为有太多重复计算
# return (self.fib(n-1) + self.fib(n-2))%1000000007
a = 0
b = 1
for i in range(2,n+1):
c = a + b
a = b
b = c
return c%1000000007
面试题10- II. 青蛙跳台阶问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
解题思路:DP动态规划, 可继续优化
class Solution:
def numWays(self, n: int) -> int:
if n == 0:return 1
if n == 1:return 1
if n == 2:return 2
dp = [0 for i in range(n+1)]
dp[0] = 1
dp[1] = 1
dp[2] = 2
for i in range(3,n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[-1]%1000000007
面试题11. 旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
解题思路:二分法的变体,难点为考虑 left 和 mid 相等的情况时, 是左加1还是右减1
class Solution:
def minArray(self, numbers: List[int]) -> int:
# 二分查找的变体
if not numbers:return None
left = 0
right = len(numbers) - 1
if numbers[left] < numbers[right]:
return numbers[0]
while left < right:
mid = (left + right) //2
if numbers[left] < numbers[mid]:
left = mid + 1
elif numbers[left] > numbers[mid]:
right = mid
else:
left += 1
return numbers[left]
面试题12. 矩阵中的路径
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。
[[“a”,“b”,“c”,“e”],
[“s”,“f”,“c”,“s”],
[“a”,“d”,“e”,“e”]]
但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
解题思路: 深度优先算法,走过的标记为1,没走的标记为0
第一遍答案
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
n = len(board[0])
m = len(board)
if m == 0:
return False
mark = [[0 for _ in range(n)] for _ in range(m)]
for i in range(m):
for j in range(n):
if mark[i][j] == 0 and board[i][j] == word[0]:
mark[i][j] = 1
if self.backtrack(i,j,mark,board,word[1:]) == True:
return True
else:
mark[i][j] = 0
return False
directions = [(0,1),(0,-1),(1,0),(-1,0)]
def backtrack(self,i,j,mark,board,word):
if len(word) == 0:
return True
n = len(board[0])
m = len(board)
for direction in self.directions:
cur_i = i + direction[0]
cur_j = j + direction[1]
if 0 <= cur_i < m and 0 <= cur_j < n and board[cur_i][cur_j] == word[0]:
if mark[cur_i][cur_j] == 0:
mark[cur_i][cur_j] = 1
if self.backtrack(cur_i,cur_j,mark,board,word[1:]) == True:
return True
else:
mark[cur_i][cur_j] = 0
return False
第二遍答案
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
def dfs(i,j,k):
if not 0 <= i < len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]:
return False
temp,board[i][j] = board[i][j], '/'
res = dfs(i-1,j,k+1) or dfs(i+1,j,k+1) or dfs(i,j-1,k+1) or dfs(i,j+1,k+1)
board[i][j] = temp
return res
for i in range(len(board)):
for j in range(len(board[0])):
if dfs(i,j,0):return True
return False
面试题13. 机器人的运动范围
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
第一遍答案
class Solution:
def movingCount(self, m: int, n: int, k: int) -> int:
# bfs
directions = [(0,1),(0,-1),(1,0),(-1,0)]
count = 1
queue = [(0,0)]
res = [(0,0)]
while queue:
cur = queue.pop(0)
for x,y in directions:
summ = 0
cur_x = cur[0] + x
cur_y = cur[1] + y
if (cur_x,cur_y) in res:
continue
res.append((cur_x,cur_y))
if 0 <= cur_x < m and 0 <= cur_y < n:
while cur_x > 0:
summ += cur_x % 10
cur_x //= 10
while cur_y > 0:
summ += cur_y % 10
cur_y //= 10
if 0 < summ <= k:
queue.append((cur[0] + x ,cur[1] + y))
count += 1
return count
第二遍答案 dfs
class Solution:
def movingCount(self, m: int, n: int, k: int) -> int:
# dfs
def summ(x,y):
summer = 0
while x > 0:
summer += x % 10
x //= 10
while y > 0:
summer += y % 10
y //= 10
return summer
def dfs(i,j):
if not 0 <= i < m or not 0 <= j < n or (i,j) in marked or summ(i,j) > k:
return
else:
marked.add((i,j))
dfs(i+1,j)
dfs(i,j+1)
marked = set()
dfs(0,0)
return len(marked)
面试题14- I. 剪绳子
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
解题思路: 这个最小的只能分成2或3,求最值,果断动态规划。
class Solution:
def cuttingRope(self, n: int) -> int:
dp = [0 for i in range(n + 1)]
dp[1] = 1
dp[2] = 1
for i in range(3,n+1):
for j in range(i):
# max中的dp[i] 为 上一次循环中的最大值
dp[i] = max(dp[j]*(i-j),dp[i-j]*j,(i-j)*j,dp[i])
return dp[-1]
面试题14- II. 剪绳子 II
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m] 。请问 k[0]k[1]…*k[m] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
class Solution:
def cuttingRope(self, n: int) -> int:
dp = [0 for i in range(n+1)]
dp[1] = dp[2] = 1
for i in range(3,n+1):
for j in range(i):
dp[i] = max((i-j)*j,dp[i-j]*j,dp[j]*(i-j),dp[i])
return dp[-1] % 1000000007
面试题15. 二进制中1的个数
请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
解题思路:第一遍:每次右移一位。第二遍,和n-1作比较,每次可以去掉最后一个1.
第一遍
class Solution:
def hammingWeight(self, n: int) -> int:
res = 0
while n:
res += n & 1
n >>= 1
return res
第二遍
class Solution:
def hammingWeight(self, n: int) -> int:
count = 0
if n < 0:
n = n&0xffffffff
while n:
n = n&(n-1)
count += 1
return count
面试题16. 数值的整数次方
实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
解题思路: 如果一个一个乘,会超时。因此考虑二分法。n为奇数就和res相乘,为偶数就和自己相乘。然后n在整除2
class Solution:
def myPow(self, x: float, n: int) -> float:
if x == 0:
return 0
if n < 0:
x = 1/x
n = n*-1
res = 1
while n:
if n%2 == 1:
res *= x
x *= x
n //= 2
return res
面试题17. 打印从1到最大的n位数
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
解题思路: 此题我的解法不正确。并没有充分理解出题人的意图
class Solution:
def printNumbers(self, n: int) -> List[int]:
return [i for i in range(1,10**n)]
面试题18. 删除链表的节点
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意:此题对比原题有改动
解题思路: 最简单的双指针,注意虚拟节点
class Solution:
def deleteNode(self, head: ListNode, val: int) -> ListNode:
# 双指针一前一后
if not head:return []
dummy = ListNode(None)
dummy.next = head
pre = dummy
cur = head
while cur:
if cur.val == val:
pre.next = cur.next
pre = pre.next
cur = cur.next
return dummy.next
面试题19. 正则表达式匹配
请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。
解题思路: 通过翻阅题解,发现可用二维动态规划,然而还用一种递归解法,遗憾的是笔者并未做过多的了解。
class Solution:
def isMatch(self, s: str, p: str) -> bool:
if not p:return not s
if not s and len(p) == 1:return False
dp = [[False for i in range(len(s)+1)] for j in range(len(p)+1)]
dp[0][0] = True
dp[1][0] = False
for i in range(2,len(p)+1):
if p[i-1] == '*':
dp[i][0] = dp[i-2][0]
for i in range(1,len(s)+1):
dp[0][i] = False
for i in range(1,len(p)+1):
for j in range(1,len(s)+1):
if p[i-1] == s[j-1]:
dp[i][j] = dp[i-1][j-1]
elif p[i-1] == '.':
dp[i][j] = dp[i-1][j-1]
elif p[i-1] == '*':
if p[i-2] == s[j-1]:
dp[i][j] = dp[i-2][j] or dp[i][j-1]
elif p[i-2] == '.':
dp[i][j] = dp[i-2][j] or dp[i][j-1]
else:
dp[i][j] = dp[i-2][j]
else:
dp[i][j] = False
# print(dp)
return dp[-1][-1]
面试题20. 表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、“±5”、"-1E-16"及"12e+5.4"都不是。
解题思路: 注意几个限制条件,重点为将几个值设置为False
class Solution:
def isNumber(self, s: str) -> bool:
# 1.加减只能在开始或者e后面第一位
# 2.e 只能出现一次,且后面必须跟数字
# 3.e后面不能有小数点
# 4.e前面不能没有数字
# 5.空格只能在两端
s = s.strip()
nums = [str(i) for i in range(10)]
n = len(s)
e_showup = False
e_dot = False
dot_showup = False
num_showup = False
num_after_e = False
for i in range(n):
c = s[i]
if c in nums:
num_showup = True
num_after_e = True
elif c in ('+','-'):
if i > 0 and s[i-1] != 'e':
return False
elif c == '.':
if e_showup or dot_showup:
return False
dot_showup = True
elif c == 'e':
if e_showup or not num_showup:
return False
e_showup = True
num_showup = False
else:
return False
return num_showup and num_after_e
面试题21. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
解题思路:左右两个指针,一趟遍历。
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
left = 0
right = len(nums) - 1
while left < right :
while nums[left] % 2 == 1 and left < right:
left += 1
while nums[right] % 2 == 0 and left < right:
right -= 1
temp = nums[left]
nums[left] = nums[right]
nums[right] = temp
left += 1
right -= 1
return nums
面试题22. 链表中倒数第k个节点
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。
解题思路:快慢指针,加个虚拟头结点。
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
#快慢指针,快指针前进k步,快指针指向最后一个时,慢指针的下一个就是倒数第k个节点
if not head:
return None
dummy = ListNode(None)
dummy.next = head
fast,slow = dummy,dummy
count = 0
while count <= k:
count += 1
fast = fast.next
while fast:
fast = fast.next
slow = slow.next
return slow.next
面试题24. 反转链表
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
解题思路:双指针掉头
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if not head:
return None
# 双指针
pre = None
cur = head
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
面试题25. 合并两个排序的链表
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if not l1 and not l2:
return None
dummy = ListNode(-1)
p = dummy
while l1 and l2:
if l1.val < l2.val:
p.next = l1
p = p.next
l1 = l1.next
else:
p.next = l2
p = p.next
l2 = l2.next
while l1:
p.next = l1
p = p.next
l1 = l1.next
while l2:
p.next = l2
p = p.next
l2 = l2.next
return dummy.next
面试题26. 树的子结构
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
解题思路:先定义一个匹配方法,然后分别将当前节点、当前节点的两个子节点与B进行比较,只要有一个为True
即可。
class Solution:
def match(self,A,B):
if not B:return True
if not A:return False
if A.val != B.val:return False
return self.match(A.left,B.left) and self.match(A.right,B.right)
def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
if A and B:
return self.isSubStructure(A.left,B) or self.isSubStructure(A.right,B) or self.match(A,B)
else:
return False
面试题27. 二叉树的镜像(不熟练)
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
解题思路:最主要为hlper
函数的创建,先将两个子节点互换位置,再递归。
class Solution:
def mirrorTree(self, root: TreeNode) -> TreeNode:
if not root:return root
def helper(root):
if not root:return
root.left,root.right = root.right,root.left
helper(root.left)
helper(root.right)
helper(root)
return root
面试题29. 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
解题思路:一圈一圈循环即可,值得注意的是,不能在最后再执行上下左右缩小一圈,如果这样做,即使找到最后一个点,也会循环完本次。应当在上方遍历完后,立即加一,然后判断上是否大于下。
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix:return []
left = 0
right = len(matrix[0]) - 1
up = 0
down = len(matrix) - 1
ans = []
while left <= right and up <= down :
# 每次循环一圈
for i in range(left,right+1):
ans.append(matrix[up][i])
# print(matrix[up][i])
up += 1
if up > down:break
for i in range(up,down+1):
ans.append(matrix[i][right])
# print(matrix[i][right])
right -= 1
if left > right:break
for i in range(right,left-1,-1):
ans.append(matrix[down][i])
print(right,left-1)
print(matrix[down][i])
down -= 1
if up > down:break
for i in range(down,up-1,-1):
ans.append(matrix[i][left])
# print(matrix[i][left])
left += 1
# left += 1
# right -= 1
# up += 1
# down -= 1
# print(ans)
# print(left,right,up,down)
return ans
面试题30. 包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
解题思路:太简单,奥利给!
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.stack = []
self.min_stack = []
def push(self, x: int) -> None:
self.stack.append(x)
if len(self.stack) == 1:
self.min_stack.append(x)
else:
if x < self.min_stack[-1]:
self.min_stack.append(x)
else:
self.min_stack.append(self.min_stack[-1])
# print(self.stack,self.min_stack)
def pop(self) -> None:
self.min_stack.pop()
return self.stack.pop()
def top(self) -> int:
return self.stack[-1]
def min(self) -> int:
return self.min_stack[-1]
面试题31. 栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
解题思路:模仿栈的操作。
class Solution:
def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
stack = []
i = 0
for num in pushed:
stack.append(num)
while stack and stack[-1] == popped[i]:
i += 1
stack.pop()
return not stack
面试题32 - I. 从上到下打印二叉树
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
class Solution:
def levelOrder(self, root: TreeNode) -> List[int]:
if not root:return []
#层次遍历
cur_layer = [root]
ans = []
while cur_layer:
next_layer = []
for cur in cur_layer:
ans.append(cur.val)
if cur.left:
next_layer.append(cur.left)
if cur.right:
next_layer.append(cur.right)
cur_layer = next_layer
return ans
面试题32 - II. 从上到下打印二叉树 II
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
ans = []
cur_level = [root]
while cur_level:
cur_val = []
next_level = []
for cur in cur_level:
cur_val.append(cur.val)
if cur.left:
next_level.append(cur.left)
if cur.right:
next_level.append(cur.right)
ans.append(cur_val)
cur_level = next_level
return ans
面试题32 - III. 从上到下打印二叉树 III
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:return []
ans = []
cur_level = [root]
count = 1
while cur_level:
cur_val = []
next_level = []
for cur in cur_level:
if count % 2 != 0:
cur_val.append(cur.val)
else:
cur_val.insert(0,cur.val)
if cur.left:
next_level.append(cur.left)
if cur.right:
next_level.append(cur.right)
count += 1
ans.append(cur_val)
cur_level = next_level
return ans
面试题33. 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
解题思路:找到第一个大于n
的值,如果后面有小于n
的值,判定为假。
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
#递归解决
if not postorder:return True
n = postorder[-1]
index = 0
for i in range(len(postorder)-1):
if postorder[i] < n:
index += 1
else:
break
for i in range(index+1,len(postorder)):
if postorder[i] < n:
return False
return self.verifyPostorder(postorder[:index]) and self.verifyPostorder(postorder[index:len(postorder)-1])
面试题34. 二叉树中和为某一值的路径
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
ans = []
path = []
def dfs(node,target):
if not node:return
target -= node.val
path.append(node.val)
if target == 0 and not node.left and not node.right:
ans.append(list(path))
dfs(node.left,target)
dfs(node.right,target)
path.pop()
dfs(root,sum)
return ans
面试题35. 复杂链表的复制(不熟,有更好的解法)
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
解题思路:建一个哈希表,如果没有就放进去,如果有就取出来。此题有更优秀的解法,建议反复做。
bfs
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
visited = {}
def bfs(node):
if not node:return
copy = Node(node.val,None,None )
queue = []
queue.append(node)
visited[node] =copy
while queue:
temp = queue.pop()
if temp.next and temp.next not in visited:
visited[temp.next] = Node(temp.next.val, None ,None )
queue.append(temp.next)
if temp.random and temp.random not in visited:
visited[temp.random] = Node(temp.random.val ,None ,None )
queue.append(temp.random)
visited[temp].next = visited.get(temp.next)
visited[temp].random = visited.get(temp.random)
return copy
return bfs(head)
dfs
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
visited = {}
def dfs(node):
if not node:return
if node in visited:return visited[node]
copy = Node(node.val,None,None)
visited[node] = copy
copy.next = bfs(node.next)
copy.random = bfs(node.random)
return copy
return dfs(head)
面试题36. 二叉搜索树与双向链表(不熟)
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
解题思路:深度优先遍历,先找到最左边的点,成为头结点。
用栈
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
if not root:return
stack = []
head = None
last = None
node = root
while node or stack:
while node:
stack.append(node)
node = node.left
node = stack.pop()
if not head:
head = node
else:
node.left = last
last.right = node
last = node
node = node.right
head.left = last
last.right = head
return head
递归
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
def dfs(cur):
if not cur:return
dfs(cur.left)
if self.pre:
self.pre.right = cur
cur.left = self.pre
else:
self.head = cur
self.pre = cur
dfs(cur.right)
if not root:return
self.pre = None
dfs(root)
self.head.left = self.pre
self.pre.right = self.head
return self.head