剑指 Offer 64. 求1+2+…+n
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
我用了if的代码:
def sumNums(self, n: int) -> int:
if n == 1: return 1
return n + self.sumNums(n-1)
下面是大佬没有用if的思路和代码。。。。
根据大佬思路,修改的代码,写的不对。。。
def sumNums(self, n: int) -> int:
res = n > 1 and n + self.sumNums(n-1)
res += 1
return res
还是看下大佬的代码吧。。。
大佬代码:
class Solution:
def __init__(self):
self.res = 0
def sumNums(self, n: int) -> int:
n > 1 and self.sumNums(n - 1)
self.res += n
return self.res
剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
DFS代码:自己写的,把路径找出来,然后求路径的交集最后一个。但是我发现它这个函数最后需要return一个TreeNode类型。所以我的代码最后老报错。
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
res, path = [], []
def dfs(root):
if not root: return
path.append(root.val)
if root.left: dfs(root.left)
if root.right: dfs(root.right)
if not root.left and not root.right: res.append(list(path))
path.pop()
dfs(root)
res_p, res_q = [], []
for path in res:
for i in range(len(path)):
if path[i] == p.val:
res_p = path[:i]
if path[i] == q.val:
res_q = path[:i]
([i for i in res_p if i in res_q][-1])
看下大佬的思路和代码吧。
照着大佬的思路,写出来的代码:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
queue = collections.deque()
queue.append(root)
while queue:
node = queue.popleft()
if node.val < p.val and node.val < q.val: queue.append(node.right)
if node.val > p.val and node.val > q.val: queue.append(node.left)
if node.val > p.val and node.val < q.val: return node
elif node.val < p.val and node.val > q.val: return node
if node.val == p.val: return node
if node.val == q.val: return node
接下来是大佬的代码:
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
while root:
if root.val < p.val and root.val < q.val: # p,q 都在 root 的右子树中
root = root.right # 遍历至右子节点
elif root.val > p.val and root.val > q.val: # p,q 都在 root 的左子树中
root = root.left # 遍历至左子节点
else: break
return root
优化:若可保证 p.val < q.valp.val<q.val ,则在循环中可减少判断条件。
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if p.val > q.val: p, q = q, p # 保证 p.val < q.val
while root:
if root.val < p.val: # p,q 都在 root 的右子树中
root = root.right # 遍历至右子节点
elif root.val > q.val: # p,q 都在 root 的左子树中
root = root.left # 遍历至左子节点
else: break
return root
总结:学习了BFS便利到下一层,可以不用queue,而是直接通过root=root.left/root.right实现,妙啊。另外再判断公共祖先的时候,p和q位置可以交换,因为他们的爹只有一个。所以第二种优化方法在速度上有了明显提升,但是空间复杂度为什么会降低那么多,我没想通。
照着大佬思路写的代码,其实不是很明白。。。
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if root.val < p.val and root.val < q.val:
return self.lowestCommonAncestor(root.right, p, q)
if root.val > p.val and root.val > q.val:
return self.lowestCommonAncestor(root.left, p, q)
return root
应该是用的DFS的思想,速度比BFS要快。
下面是大佬代码,和我写的一样:
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if root.val < p.val and root.val < q.val:
return self.lowestCommonAncestor(root.right, p, q)
if root.val > p.val and root.val > q.val:
return self.lowestCommonAncestor(root.left, p, q)
return root
剑指 Offer 68 - II. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
这题是我之前理解的68-I的题,还是没有想到node节点如何存储问题。我觉得应该还是通过递归的方法来解决。直接看大佬题解吧:
这里的判断条件和我想的一样。考虑通过递归对二叉树进行先序遍历,当遇到节点 p 或 q 时返回。从底至顶回溯,当节点 p, q 在节点 root 的异侧时,节点 root 即为最近公共祖先,则向上返回 root。
红线部分理解看下图:
接下来是全部的动态展示:
看完动态展示,才能更好的理解递归和回溯。
根据大佬思路,写的代码:
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
if not root: return None
if root.val == p.val: return root
elif 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 None
elif left and right: return root
elif not left and right: return right
elif left and not right: return left
BFS其实速度很快。
下面是大佬的代码:太精简了。。。。
class Solution:
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
if not root or root == p or root == q: return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if not left: return right
if not right: return left
return root