知识点【二分查找】
二分查找【递归】
二分查找【循环】
有回溯时候最好递归
两种代码模式要掌握会写!
一,插入位置
LeetCode 35. Search Insert Position
1.处理边界
2.二分基本框架
3.别忘了更新区间
4.循环判断的越界条件一定要放在最开头【重点】
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int index=-1;
int begin=0;
int end=nums.size()-1;
while(index==-1)
{
int mid=(begin+end)/2;
if(nums[mid]==target)
{
index=mid;
}
else if(target<nums[mid])
{
if(mid==0||target>nums[mid-1])
{
index=mid;
}
end=mid-1;//别忘了更新区间啊
}
else if(target>nums[mid])
{
if(mid==nums.size()-1||target<nums[mid+1])
{
index=mid+1;
}
begin=mid+1;
}
}
return index;
}
};
作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/search-insert-position/solution/cha-ru-wei-zhi-by-xia-mu-lao-zhang-ren-90l1/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
二,区间查找
LeetCode 34. Search for a Range
1.把求区间【拆解】成左右端点
2.处理边界
3.给二分查找加限制条件
4.函数内部不能定义函数,之前写在类的内部了
int right_bound(vector<int>&nums,int target){
int begin=0;
int end=nums.size()-1;
while(begin<=end)
{
int mid=(begin+end)/2;
if(nums[mid]==target)
{
if(mid==nums.size()-1||nums[mid+1]>target)//限制条件,边界写前面,防止越界
{
return mid;
}
begin=mid+1;//重要一步给忘了【紧随其后调整】
}
else if(target<nums[mid])
{
end=mid-1;
}
else if(target>nums[mid])
{
begin=mid+1;
}
}
return -1;
}
int left_bound(vector<int>&nums,int target){
int begin=0;
int end=nums.size()-1;
while(begin<=end)
{
int mid=(begin+end)/2;
if(nums[mid]==target)
{
if(mid==0||nums[mid-1]<target)
{
return mid;
}
end=mid-1;//重要一步
}
else if(target<nums[mid])
{
end=mid-1;
}
else if(target>nums[mid])
{
begin=mid+1;
}
}
return -1;
}
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int>result;
result.push_back(left_bound(nums,target));
result.push_back(right_bound(nums,target));
return result;
}
};
作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/cha-zhao-qu-jian-by-xia-mu-lao-zhang-ren-fjwq/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三,旋转数组查找【没理解】
LeetCode 33. Search in Rotated Sorted Array
两个接上?》首尾相连
判断旋转区间
边界情况
情况很多很复杂
4.【精髓】将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。
此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。就这样循环
class Solution {
public:
int search(vector<int>& nums, int target) {
int n=nums.size();
int begin=0;
int end=n-1;
if(!n){
return -1;
}
if(n==1){
return nums[0]==target?0:-1;
}
while(begin<=end){
int mid=(begin+end)/2;
if(target==nums[mid]){
return mid;
}
if(nums[0]<=nums[mid]){//左半边有序
if(target>=nums[0]&&target<nums[mid]){//target在左半边
end=mid-1;
}
else//在右半边
begin=mid+1;
}
else//右半边有序
{
if(target>nums[mid]&&target<=nums[end]){
begin=mid+1;
}
else
end=mid-1;
}
}
return -1;
}
};
作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/sou-suo-xuan-zhuan-shu-zu-by-xia-mu-lao-dcfpo/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【知识点】二叉查找(排序)树
1.中序遍历是从小到大的
2.如何插入结点插入到二叉查找树中
3.二叉树查找数值
五,二叉查找数的编码和解码
LeetCode 449. Serialize and Deserialize BST
1.二叉查找树前序遍历与复原
2.整形转为字符串
3.字符串拆解整型
4.结点的创建和初始化
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
void changt_int_to_string(int val,string &str_val){
string tmp;
while(val){//一个结点数据
tmp+=val%10+'0';
val=val/10;
}
for(int i=tmp.length()-1;i>=0;i--){
str_val+=tmp[i];
}
str_val+='#';
}
void BST_preorder(TreeNode*node,string &data){
if(!node){
return;
}
string str_val;
changt_int_to_string(node->val,str_val);
data+=str_val;
BST_preorder(node->left,data);
BST_preorder(node->right,data);
}
void BST_insert(TreeNode*node,TreeNode*insert_node){
if(insert_node->val<node->val){
if(node->left){
BST_insert(node->left,insert_node);
}
else{
node->left=insert_node;
}
}
else{
if (node->right){
BST_insert(node->right,insert_node);
}
else{
node->right=insert_node;
}
}
}
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string data;
BST_preorder(root,data);
return data;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
if(data.length()==0){
return NULL;
}
vector<TreeNode*>node_vec;
int val=0;
for(int i=0;i<data.length();i++){
if(data[i]=='#'){
node_vec.push_back(new TreeNode(val));//有多少#,加多少结点,上一个的val初始化他
val=0;//初始为0
}
else{
val=val*10+data[i]-'0';
}
}
for(int i=1;i<node_vec.size();i++){
BST_insert(node_vec[0],node_vec[i]);
}
return node_vec[0];
}
};
// Your Codec object will be instantiated and called as such:
// Codec* ser = new Codec();
// Codec* deser = new Codec();
// string tree = ser->serialize(root);
// TreeNode* ans = deser->deserialize(tree);
// return ans;
作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/serialize-and-deserialize-bst/solution/er-cha-shu-bian-ma-yu-zhuan-ma-by-xia-mu-ppyk/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
六,逆序数(用归并做过)【未解决,超时了】
LeetCode 315. Count of Smaller Numbers After Self
1.分治思想
2.记录左子树数量二叉查找树
3.将元素按照原数组逆置后的顺序插入到二叉查找树中,如何在元素插入时,计算已有多少个元素比当前插入元素小?
struct BSNode{
int val;
int count;//二叉树中左子树的个数
BSNode*left;
BSNode*right;
BSNode(int x):val(x),left(NULL),right(NULL),count(0){}
};
void BST_insert(BSNode*node,BSNode*insert_node,int &count_small)//当前结点,插入的结点,二叉树中比insert_node小的结点个数
{
if(insert_node->val<=node->val)
{
node->count++;
if(node->left)
{
BST_insert(node->left,insert_node,count_small);
}
else
{
node->left=insert_node;
}
}
else
{
count_small+=node->count+1;//跑右边去了,把左边的都加上,【带上根结点】
if(node->right)
{
BST_insert(node->right,insert_node,count_small);
}
else
{
node->right=insert_node;
}
}
}
class Solution {
public:
vector<int> countSmaller(vector<int>& nums) {
vector<int>result;
vector<BSNode*>node_vec;
vector<int>count;
for(int i=nums.size()-1;i>=0;i--)
{
node_vec.push_back(new BSNode( nums[i]));//逆置nums数组//【新创建】
}
count.push_back(0);//第一个结点count_small=0
for(int i=1;i<node_vec.size();i++)//从第二个结点开始插
{
int count_small=0;
BST_insert(node_vec[0],node_vec[i],count_small);//从第一个结点开始比较,向下递归
count.push_back(count_small);//count是记录count_small结果的数组
}
for(int i=node_vec.size()-1;i>=0;i--)
{
delete node_vec[i];
result.push_back(count[i]);
}
return result;
}
};