二分
int Binary_Search(vector<int> A,int key){
int n=A.size();
int low=0,high=n-1,mid;
while(low<=high){
mid=(low+high)/2;
if(A[mid]==key)
return mid;
else if(A[mid]>key)
high=mid-1;
else
low=mid+1;
}
return -1;
}
折半插入排序
——找到第一个 ≥ \ge ≥tem的元素
void InsertSort(vector<int> A){
int n=A.size();
int low,high,mid;
for(int i=1;i<=n;i++){
int tem=A[i];
low=1;high=i-1;
while(low<=high){
mid=(low+high)/2;
if(A[mid]>tem) //只要A[high]>tem,就不断往后移
high=mid-1;
else //先往右移,后续往做移
low=mid+1;
}
for(int j=i-1;j>=high+1;j--)
A[j+1]=A[j];
A[high+1]=tem;
}
在非递减数组中找到比x小的最后一个元素和比x大的第一个元素
- 每次有要处理的就if-else
- 为了避免无限循环>>[begin,mid-1] U mid U [mid+1,end]
- 为了产生mid+1对nums[mid+1]进行讨论
class Solution {
public:
int search_left(vector<int> nums,int begin,int end,int target){
if(begin>end) return -1;
if(nums[end]<target)
return end;
if(nums[begin]>=target)
return begin-1;
else {
int mid=(begin+end)/2;
if(nums[mid]>=target)
return search_left(nums,begin,mid-1,target);
else {
if(mid==nums.size()-1)
return -1;
else if(nums[mid+1]>=target)
return mid;
else
return search_left(nums,mid+1,end,target);
}
}
}
int search_right(vector<int> nums,int begin,int end,int target){
if(begin>end) return nums.size();
if(nums[begin]>target){
return begin;
}
if(nums[end]<=target){
return end+1;
}
else {
int mid=(begin+end)/2;
if(nums[mid]<=target)
return search_right(nums,mid+1,end,target);
else{
if(mid==0) return nums.size();
if(nums[mid-1]<=target) return mid;
else return search_right(nums,begin,mid-1,target);
}
}
}
vector<int> searchRange(vector<int>& nums, int target) {
int N=nums.size();
int left=search_left(nums,0,N-1,target);
int right=search_right(nums,0,N-1,target);
vector<int> ans(2);
if(left>=right-1){
ans[0]=-1;
ans[1]=-1;
}
else {
ans[0]=left+1;···
ans[1]=right-1;
}
return ans;
}
};
三数之和
- 三数之和首先把nums[0]~nums[n-1]排序
- 在a固定的情形下,条件: 每次c及其右侧所有可能都被确定,
利用贪心性质:if b+c+a<0, b左侧的在c往左移的过程中更不可能,因此b++
else if b+c+a>0,c及其右侧在b右移的过程中更不可能,因此c–,
b+c+a=0,当前的b及其左侧已不可能,不妨b++,
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
// 枚举 a
for (int first = 0; first < n; ++first) {
// 需要和上一次枚举的数不相同
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
// c 对应的指针初始指向数组的最右端
int third = n - 1;
int target = -nums[first];
// 枚举 b
for (int second = first + 1; second < n; ++second) {
// 需要和上一次枚举的数不相同
if (second > first + 1 && nums[second] == nums[second - 1]) {
continue;
}
// 需要保证 b 的指针在 c 的指针的左侧
while (second < third && nums[second] + nums[third] > target) {
--third;
}
// 如果指针重合,随着 b 后续的增加
// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if (second == third) {
break;
}
if (nums[second] + nums[third] == target) {
ans.push_back({nums[first], nums[second], nums[third]});
}
}
}
return ans;
}
};`
四数相加
- 要返回解,只能2层循环+双指针,2个数组的双指针,不能输出全部解
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int>hash;
int res = 0;
int n =nums1.size();
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
hash[nums1[i]+nums2[j]]++;
}
} for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
auto it = hash.find(-(nums3[i]+nums4[j]));
if(it!=hash.end()){
res += it->second;
}
}
}
return res;
}
};