建立思维 #
理解递归的关键首先还是弄清楚二叉树的先序遍历、中序遍历和后序遍历的递归实现。任何递归可以说都处在这个模型中。
void traverse(TreeNode root) {
if (root == null) {
return;
}
// 前序位置
traverse(root.left);
// 中序位置
traverse(root.right);
// 后序位置
}
如果面试官明确要求不使用递归,那一般就是使用后进先出的栈来代替递归实现,可以参考 二叉树专题 中遍历二叉树的非递归实现。
如何画递归流程? #
时间复杂度怎么计算? #
用子问题个数乘以解决一个子问题需要的时间。
递归的缺点 #
递归可能会有重复计算的问题,进去一遍,出来一遍,尤其动态规划的场景居多。
非递归实现 #
很多递归实现很容易的代码,面试官会要求用非递归实现。解决办法通常是需要用 栈 的出栈和入栈来模拟递归过程。
常见题型 #
链表 #
206. 反转链表 非常典型。
func reverseList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
last := reverseList(head.Next)
head.Next.Next = head
head.Next = nil
return last
}
var mergeTwoLists = function(l1, l2) {
if (l1 === null) {
return l2;
} else if (l2 === null) {
return l1;
} else if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
};
字符串 #
二叉树 #
var diameterOfBinaryTree = function(root) {
let ret = 0
let helper = function(root) {
if (!root) {
return 0
}
let l = helper(root.left)
let r = helper(root.right)
ret = Math.max(ret, l+r)
return Math.max(l, r) + 1
}
helper(root)
return ret
};