一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情。
剑指 Offer 53 - II. 0~n-1中缺失的数字
思路
(二分) O(logn)
假设数组中第一个缺失的数是 x,那么数组中的数如下所示:
从中可以看出,数组左边蓝色部分都满足nums[i] == i,数组右边橙色部分都不满足nums[i] == i,因此我们可以二分出分界点 x的值。
具体过程如下:
1、初始化l = 0, r = nums.size() - 1,二分nums[i] !=i的最左边界。
2、当nums[mid] != mid , 说明答案在左半部分,往左边区域找,则r = mid。
3、当nums[mid] == mid , 说明答案在右半部分,往右边区域找,则l = mid + 1。
4、当只剩下一个数时,就是缺失数字,我们返回r。
实现细节:
当所有数都满足nums[i] == i时,表示缺失的是 n。
时间复杂度分析: 二分的时间复杂度是 O(logn)。
c++代码
class Solution {
public:
int missingNumber(vector<int>& nums) {
int l = 0, r = nums.size() - 1;
while(l < r){
int mid = (l + r) / 2;
if(nums[mid] != mid) r = mid;
else l = mid + 1;
}
if(nums[r] == r) r++; //缺失的是n
return r;
}
};
剑指 Offer 54. 二叉搜索树的第k大节点
思路
(dfs) O(n)
什么是二叉搜索树 ?
二叉搜索树是一棵有序的二叉树,所以我们也可以称它为二叉排序树。具有以下性质的二叉树我们称之为二叉搜索树:若它的左子树不为空,那么左子树上的所有值均小于它的根节点;若它的右子树不为空,那么右子树上所有值均大于它的根节点。它的左子树和右子树分别也为二叉搜索树。
二叉搜索树的中序遍历是:左=>根=>右; 二叉搜索树的中序遍历从小到大是有序的。
中序遍历模板
//打印中序遍历
void dfs(TreeNode* root )
{
if(!root) return;
dfs(root->left); //左
print(root->val); //根
dfs(root->right); //右
}
如图所示
因此求二叉搜索树第 k大的节点” 可转化为求 “二叉搜索树的中序遍历倒序的第k 个节点”。
过程如下:
- 1、按照右->根->左的顺序(中序遍历倒序)遍历二叉树
- 2、我们每次遍历一个节点的时候就让
k--,当k减为0时,我们就找到了第k大的节点。
具体实现细节看代码。
时间复杂度分析: 每个节点最多只会被遍历1次,因此n个节点,时间复杂度为O(n) 。
c++代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int res;
int kthLargest(TreeNode* root, int k) {
dfs(root,k);
return res;
}
void dfs(TreeNode* root ,int &k) //传引用 这里需要保证所有dfs函数共用一个k
{
if(!root) return;
dfs(root->right,k);
k--;
if(!k) res = root->val;
dfs(root->left,k);
}
};
剑指 Offer 55 - I. 二叉树的深度
思路
(递归) O(n)
一棵二叉树的最大深度 == max(左子树最大深度, 右子树最大深度) + 1。
时间复杂度分析: O(n)
c++代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
//一棵二叉树的最大深度 == max(左子树最大深度, 右子树最大深度) + 1
int maxDepth(TreeNode* root) {
if(!root) return 0;
int lh = maxDepth(root->left), rh = maxDepth(root->right);
return max(lh, rh) + 1;
}
};