示例:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
提示:
你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution { public: int search(vector<int>& nums, int target) { int begin=0,end=nums.size()-1; int mid; while(begin<=end){ mid=(begin+end)/2; if(target==nums[mid]) return mid; else if(target<nums[mid]){ end=mid-1; }else{ begin=mid+1; } } return -1; } };
1.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5
输出: 2
示例 2:
输入: [1,3,5,6], 2
输出: 1
示例 3:
输入: [1,3,5,6], 7
输出: 4
示例 4:
输入: [1,3,5,6], 0
输出: 0
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-insert-position
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution { public: int searchInsert(vector<int>& nums, int target) { int begin=0,end=nums.size()-1; int mid; while(begin<=end){ mid=(begin+end)/2; if(target==nums[mid]) return mid; else if(target<nums[mid]){ end=mid-1; }else{ begin=mid+1; } } if(target<nums[mid]) return mid; else return mid+1; } };
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { int begin=0,end=nums.size()-1; int mid; vector<int> pos(2,-1); pos[0]=bound(nums,target,0); pos[1]=bound(nums,target,1); return pos; } int bound(vector<int>& nums,int target,int b){ int begin=0,end=nums.size()-1; int mid; while(begin<=end){ mid=(begin+end)/2; if(target==nums[mid]){ if(b==0){ if(mid==0 || nums[mid-1]<target){ return mid; } end=mid-1; } if(b==1){ if(mid==nums.size()-1 || nums[mid+1]>target){ return mid; } begin=mid+1; } }else if(target<nums[mid]){ end=mid-1; }else{ begin=mid+1; } } return -1; } };
3.搜索旋转排序数组
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
示例 1:
输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4
示例 2:
输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public:
int search(vector<int>& nums, int target) {
int begin=0,end=nums.size()-1,mid;
while(begin<=end){
mid=(begin+end)/2;
if(target==nums[mid]){
return mid;
}else{
if(nums[mid]>=nums[begin]){
if(target<nums[begin] || target>nums[mid]){
begin=mid+1;
}else{
end=mid-1;
}
}else{
if(target>nums[end] || target<nums[mid]){
end=mid-1;
}else{
begin=mid+1;
}
}
}
}
return -1;
}
};
4.最长上升子序列
给定一个无序的整数数组,找到其中最长上升子序列的长度(严格上升,不必连续)。
示例:
输入:[10,9,2,5,3,7,101,18]
输出: 4 解释: 最长的上升子序列是[2,3,7,101],
它的长度是4
。
说明:
- 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
- 你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?
//寻找第一个大于x的元素下标,返回start. int binary_search(int x, vector<int>& s) { int start = 0; int end = s.size() - 1; int mid; while (start<=end) { mid = (start + end) / 2; if (s[mid] > x) { end = mid - 1; } else if (s[mid] < x) { start = mid + 1; } else { return mid; } } return start; } class Solution{ public: int lengthOfLIS(vector<int>& nums) { int len=nums.size(); if(len==0) return 0; vector<int> stack; stack.push_back(nums[0]); int index=-1; for(int i=1;i<len;i++){ if(nums[i]>stack.back()){ stack.push_back(nums[i]); }else{ index=binary_search(nums[i],stack); stack[index]=nums[i]; } } return stack.size(); } };
若是寻找第一个小于x的元素下标,则返回end
序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。
设计一个算法来序列化和反序列化二叉搜索树。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。
编码的字符串应尽可能紧凑。
注意:不要使用类成员/全局/静态变量来存储状态。 你的序列化和反序列化算法应该是无状态的。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/serialize-and-deserialize-bst
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Codec { public: // Encodes a tree to a single string. string serialize(TreeNode* root) { string data=""; preorder(root,data); return data; } void preorder(TreeNode* root,string& data){ if(!root) return; data+=intToString(root->val); data+='#'; preorder(root->left,data); preorder(root->right,data); } //整数转化为字符串 string intToString(int val) { string s = ""; while (val) { s += val % 10 + '0'; val /= 10; } string res=""; //需要倒序得到正确字符串 for(int i=s.size()-1;i>=0;i--){ res+=s[i]; } return res; } // Decodes your encoded data to tree. TreeNode* deserialize(string data) { TreeNode* root=NULL; int tmp=0; for(int i=0;i<data.size();i++){ while(data[i]!='#'){ tmp=tmp*10+data[i]-'0'; i++; } TreeNode* node=new TreeNode(tmp); if(root==NULL) root=node; else{ insert(root,node); } tmp=0; } return root; } //逐个插入构成二叉排序树 void insert(TreeNode* root,TreeNode* node){ if(node->val<root->val){ if(root->left==nullptr){ root->left=node; }else{ insert(root->left,node); } }else{ if(root->right==nullptr){ root->right=node; }else{ insert(root->right,node); } } } }; // Your Codec object will be instantiated and called as such: // Codec codec; // codec.deserialize(codec.serialize(root));
6. 计算右侧小于当前元素的个数 (逆序数)
给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
示例:
输入: [5,2,6,1]
输出: [2,1,1,0]
解释:
5 的右侧有 2 个更小的元素 (2 和 1).
2 的右侧仅有 1 个更小的元素 (1).
6 的右侧有 1 个更小的元素 (1).
1 的右侧有 0 个更小的元素.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-of-smaller-numbers-after-self
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution { struct TreeNode{ int val; int count; TreeNode* left; TreeNode* right; TreeNode(int x,int c):val(x),count(c),left(NULL),right(NULL){} }; public: vector<int> countSmaller(vector<int>& nums) { TreeNode* root=NULL; vector<TreeNode*> node_vec; vector<int> tmp_res; for(int i=nums.size()-1;i>=0;i--){ int count_smaller=0; TreeNode *node=new TreeNode(nums[i],0); node_vec.push_back(node); if(root==nullptr) { root=node; } else { insert(root,node,count_smaller); } tmp_res.push_back(count_smaller); } vector<int> result; for(int i=nums.size()-1;i>=0;i--){ delete node_vec[i]; result.push_back(tmp_res[i]); } return result; } void insert(TreeNode* root,TreeNode* node,int & count_smaller){ if(node->val<=root->val){ root->count++;//**********记录左子树节点数目************* if(root->left){ insert(root->left,node,count_smaller); }else{ root->left=node; } }else{ count_smaller+=root->count+1; if(root->right){ insert(root->right,node,count_smaller); }else{ root->right=node; } } } };
倒序插入二叉排序树,保证当前插入值的右侧已经在树中
root->count记录左子树数目,即小于节点值的节点数目。这样当前值小于节点,root->count++;当前值大于节点,就要加上节点的root->count+1.如此一直到应该插入时,就累加得到了count_smaller的值