题目名称
- Median of Two Sorted Arrays(Leetcode #4)
- Long Consecutive Sequence(Leetcode #128)
- 从尾到头打印链表(剑指offer #6)
- 重建二叉树(剑指offer #7)
- 二叉树的下一个节点(剑指offer #8)
Median of Two Sorted Arrays(Leetcode #4)
题目描述
There are two sorted arrays nums1 and nums2 of size m and n respectively.Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).You may assume nums1 and nums2 cannot be both empty.
Example 1:
1 | nums1 = [1, 3] |
Example 2:
1 | nums1 = [1, 2] |
解题思路
笔者直接将问题改造为更一般的通用情况:已知两个有序数组,找到二者所有元素中第k大的元素。思路有以下三种:
- 归并排序,这是最显然的解法。但是无论时间还是空间均有较大消耗。
- 在1的基础上,采用一个计数器记录当前m大的元素,当m==k时终止算法。此时不再具备空间消耗,但时间复杂度不变。
- 在2的基础上我们发现,每一次比较都排除了一个在第k大元素之前的元素。我们可以充分利用数组有序的特性,每一次都删除一半的元素,如此则可实现O(log(m+n))的复杂度。
思路剖析
针对思路3,现有分析如下:
假设数组A与B元素个数均大于k/2,我们将A的第k/2个元素与B的第k/2个元素进行比较,即比较A[k/2-1]、B[k/2-1],比较结果有三种可能(为了简化分析,假设k为偶数,所得结论对于k为奇数亦成立):
- A[k/2-1]==B[k/2-1]
- A[k/2-1]>B[k/2-1]
- A[k/2-1]<B[k/2-1]
若A[k/2-1] < B[k/2-1],则意味着区间[A[0],A[k/2-1]]内的所有元素必然不大于AU
B的top k元素,则可直接舍弃这k/2个元素,对于<的情况亦是如此(证明很简单,令A[k/2-1]=P,则P至多为AU
B的第k-1个元素)。若A[k/2-1]==B[k/2-1],则表明已经找到了第k大的元素。
解题方案
思路二(计数器+归并)
1 | class Solution { |
思路三(二分)
1 | class Solution { |
扩展
对于这种求第k个元素,很容易联想到大顶堆或小顶堆,笔者出于时间原因没有验证,但采用堆必然消耗空间,有兴趣的读者可以自行尝试。
Long Consecutive Sequence(Leetcode #128)
题目描述
Given an unsorted array of integers, find the length of the longest consecutive elements sequence.Your algorithm should run in O(n) complexity.
Example:
1 | Input: [100, 4, 200, 1, 3, 2] |
解题思路
最长连续整数序列,第一反应必然是排序去重求解,但排序不满足O(n)的时间复杂度。因此可采用以空间换取时间的策略,将所有元素存入hashtable,对于每一个元素,以其为中心向两侧扩张,直到不再连续(当然亦可以采用hashset)。
解题方案
方案一(排序)
1 | class Solution { |
方案二(hashtable)
1 | class Solution { |
从尾到头打印链表(剑指offer #6)
解题思路
没什么好说的,从尾到头是标准的先进后出,自然想到了栈。此外,本题采用递归也能实现。
解题方案
方案一(栈)
1 | class Solution { |
方案二(递归)
1 | class Solution { |
重建二叉树(剑指offer #7)
题目描述
以下将探讨如何从前序遍历、中序遍历序列还原二叉树。
解题思路
思路很简单:前序的第一个Node为root,在中序序列中找到root,其左右分别为左子树和右子树。再对左右子树执行递归构建即可。
解题方案
1 | class Solution { |
扩展
利用中序与后序还原二叉树也是类似的思路:
1 | class Solution { |
二叉树的下一个节点(剑指offer #8)
题目描述
求解某二叉树在中序遍历下的下一个节点,struct TreeNode内含有指向父亲的指针。
解题思路
该问题可按照以下步骤求解:
- 若该节点存在右子树,则下一个节点必为其右子树的最左侧节点。
- 在不满足1的条件下,若该节点为左子,则其父为下一节点。
- 在不满足1的条件下,若该节点为右子,上溯至其第一个不为右子的祖先之父。
解题方案
1 | class Solution { |