Leetcode-递归

文章目录

    • q21 合并两个有序链表
    • q101 对称二叉树
    • q104 二叉树的最大深度
    • q226 翻转二叉树
    • q236 二叉树的最近公共祖先
    • 剑指 Offer 10- I. 斐波那契数列
    • 剑指 Offer 10- II. 青蛙跳台阶问题


q21 合并两个有序链表


题目传送门


题解

可以使用递归和迭代两种方法进行求解,两种方法都比较简单。

递归:

func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
	if l1 == nil {
		return l2
	} else if l2 == nil {
		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
	}
}

迭代:

func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
	L := &ListNode{}
	curr := L
	var next *ListNode
	for l1 != nil && l2 != nil {
		if l1.Val < l2.Val {
			next = l1.Next
			curr.Next = l1
			l1.Next = nil
			l1 = next
		} else {
			next = l2.Next
			curr.Next = l2
			l2.Next = nil
			l2 = next
		}
		curr = curr.Next
	}
	if l1 != nil {
		curr.Next = l1
	}
	if l2 != nil {
		curr.Next = l2
	}
	return L.Next

q101 对称二叉树


题目传送门


题解

这道题使用递归来求解,首先判断边界条件,如果两者同时为nil,就返回真,如果不同时为nil,返回假,最后判断p和q节点的值是否相等,以及递归判断它们的孩子节点是否相等。

func isSymmetric(root *TreeNode) bool {
	var check func(p, q *TreeNode) bool
	check = func(p, q *TreeNode) bool {
		if p == nil && q == nil {
			return true
		}
		if p == nil || q == nil {
			return false
		}
		return p.Val == q.Val && check(p.Left, q.Right) && check(p.Right, q.Left)
	}
	return check(root, root)
}

q104 二叉树的最大深度


题目传送门


题解

用递归的方式来求解,定义一个递归函数,首先判断L是不是nil,如果是nil直接返回0;否则,递归得到左右子树的高度,然后判断左右子树的高度,返回高的那个+1。

func maxDepth(root *TreeNode) int {
	var Count func(L *TreeNode) int
	Count = func(L *TreeNode) int {
		if L == nil {
			return 0
		} else {
			lChild := Count(L.Left)
			rChild := Count(L.Right)
			if lChild > rChild {
				return lChild + 1
			} else {
				return rChild + 1
			}
		}
	}
	return Count(root)
}

q226 翻转二叉树


题目传送门


题解

还是利用递归的思想,首先从根节点开始,递归遍历树,并从叶子节点开始翻转,然后逐级向上翻转,最后翻转root节点的左右子树。
翻转策略是这样的,遍历到一个节点时,首先判断该节点是否为nil,如果是直接返回nil,否则首先递归翻转左子树,然后递归翻转右子树,最后交换左右子树即可。

func invertTree(root *TreeNode) *TreeNode {
	if root == nil {
		return nil
	} else {
		left := invertTree(root.Left)
		right := invertTree(root.Right)
		root.Left = right
		root.Right = left
	}
	return root
}

q236 二叉树的最近公共祖先


题目传送门


题解

存在三种情况:

  1. root为p,q中的一个,这个时候公共祖先为root
  2. p和q分别在root的左右子树上,这个公共组先也为root
  3. p和q只在左子树或者右子树上,这个时候就需要递归遍历左子树或者右子树来找
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
	if root == nil {
		return nil
	}
	// root为p或q中的一个
	if root == p || root == q {
		return root
	}
	// 递归遍历左子树和右子树
	left := lowestCommonAncestor(root.Left, p, q)
	right := lowestCommonAncestor(root.Right, p, q)
	// 如果分别在左右子树中,公共祖先就是root
	if left != nil && right != nil {
		return root
		// 都分布在左子树中
	} else if left != nil {
		return left
		// 都分布在右子树中
	} else {
		return right
	}
}

代码中如果p,q全都分布在左子树或者右子树上就直接返回left或right,这个时候能不能保证是最近公共祖先呢?其实是可以的,因为递归遍历以后,最终return是从叶子节点开始return的。


剑指 Offer 10- I. 斐波那契数列


题目传送门


题解

这道题用递归可能会爆栈,所以我用递推,要注意,题目要求结果对1000000007,所以测试数据可能会很大超出int范围,所以需要对循环中进行的计算结果进行取模。

func fib(n int) int {
	if n < 2 {
		return n
	}
	f0, f1 := 0, 1
	var f2 int
	for i := 0; i < n-1; i++ {
		f2 = (f0 + f1) % 1000000007
		f0 = f1
		f1 = f2
	}
	return f1
}

剑指 Offer 10- II. 青蛙跳台阶问题


题目传送门


题解

这道题的解法与斐波那契数列是一样的,需要用递归的思路去解决,假如现在有n级台阶,因为有跳一步与跳两步两种跳法,所以n级台阶的跳法就是n-1级的跳法与n-2级跳法之和。所以要知道高级数台阶的跳法就得知道低级数台阶的跳法,因此我们从3级台阶的跳法往后开始递推。

func numWays(n int) int {
    if n == 0 {
        return 1
    }
	if n < 3 {
		return n
	}
	f1, f2 := 1, 2
	var f3 int
	for i := 0; i < n-2; i++ {
		f3 = (f1 + f2) % 1000000007
		f1 = f2
		f2 = f3
	}
	return f2
}

你可能感兴趣的:(LeetCode,leetcode)