二分查找
参考连接
一, 最基础的模板
给一个有序无重复的数组,给定一个target,数组中是否存在,若存在,返回对应的下标,若不存在,返回-1
int search(vector<int> &nums, int target){
int left = 0;
int right = nums.size()-1;
while(left<= right){
int mid = left + (right - left)/2;
if(target>nums[mid]){
left = mid+1;
}else if(target<nums[mid]){
right = mid-1;
}else if(target == nums[mid]){
return mid;
}
}
return -1;
}
二、如果数组的元素存在重复的情况,使用二分法,找到左侧第一个元素
的位置,并返回位置,否者返回-1
int search(vector<int> &nums, int target){
int left = 0,right = nums.size()-1;
while(left <= right){
int mid = left + (right - left)/2;
if(target >nums[mid]){
left = mid+1;
}else if(target<nums[mid]){
right = mid -1;
}else if(target == nums[mid]){
right = mid;
}
}
return nums[left] == target?left:-1;
}
/*
* @Author: FeiPF2020 wpfn218925@163.com
* @Date: 2022-07-15 23:40:04
* @LastEditors: FeiPF2020 wpfn218925@163.com
* @LastEditTime: 2022-07-16 00:37:48
* @FilePath: \cpp_code\CPPinterver\chpter1\erfen.cpp
* @Description: 经典的二分模板
*/
#include<iostream>
#include<vector>
using namespace std;
//最基础的二分法
int search(vector<int> &nums, int target){
int left = 0;
int right = nums.size()-1;
while(left<= right){
int mid = left + (right - left)/2;
if(target>nums[mid]){
left = mid+1;
}else if(target<nums[mid]){
right = mid-1;
}else if(target == nums[mid]){
return mid;
}
}
return -1;
}
// 有序数组,最左边
int left_search(vector<int> &nums, int target){
int left = 0,right = nums.size()-1;
while(left < right){
int mid = left + (right - left)/2;
if(target >nums[mid]){
left = mid+1;
}else {
right = mid;
}
}
return nums[left] == target?left:-1;
}
//有序数组最右边
int right_search(vector<int> &nums, int target){
int left = 0,right = nums.size()-1;
while(left < right){
int mid = left + (right - left)/2+1;
if(target<nums[mid]){
right = mid -1;
}else {
left = mid;
}
}
return nums[right] == target?right:-1;
}
//有序数组,返回左右
vector<int> lr_search(vector<int> &nums, int target){
if(!nums.size() ) return vector<int>{-1,-1};
vector<int> result;
//先查找左边,
int left = 0,right = nums.size()-1;
while(left < right){
int mid = left + (right - left)/2;
if(target >nums[mid]){
left = mid+1;
}else {
right = mid;
}
}
int res = nums[right] == target?right:-1;
result.push_back(res);
if(res != -1){
int left = res,right = nums.size()-1;
while(left < right){
int mid = left + (right - left)/2+1;
if(target<nums[mid]){
right = mid -1;
}else {
left = mid;
}
}
int res1 = nums[right] == target?right:-1;
result.push_back(res1);
}else{
result.push_back(-1);
}
return result;
}
int main(){
vector<int> nums = {1,3,4,6,6,6,54,76,92},res_;
res_ = lr_search(nums,9);
for(auto &x :res_){
cout<<x<<" ";
}
system("pause");
return 0;
}
可以解决的问题有
69,374
等等
滑动窗口模板
寻找最长
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int left = 0,right = 0;
int maxlenth = 0;
unordered_set<char> str;
while(right<s.size()){
while(str.find(s[right]) != str.end()){
str.erase(s[left]);
left++;
}
str.insert(s[right]);
maxlenth = max(maxlenth,right-left+1);
right++;
}
return maxlenth;
}
};
寻找最短
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left= 0,right = 0;
int curSum= 0;
int minLenth = 0;
while(right<nums.size()){
curSum += nums[right];
while(curSum>= target){
if(right-left+1<minLenth||minLenth==0){
minLenth = right-left+1;
}
curSum = curSum-nums[left];
left++;
}
right++;
}
return minLenth;
}
};
滑动窗口算法的思路是这样:
1、我们在字符串 S 中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引闭区间 [left, right] 称为一个「窗口」。
2、我们先不断地增加 right 指针扩大窗口 [left, right],直到窗口中的字符串符合要求(包含了 T 中的所有字符)。
3、此时,我们停止增加 right,转而不断增加 left 指针缩小窗口 [left, right],直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。同时,每次增加 left,我们都要更新一轮结果。
4、重复第 2 和第 3 步,直到 right 到达字符串 S 的尽头。
第 2 步相当于在寻找一个「可行解」,然后第 3 步在优化这个「可行解」,最终找到最优解。左右指针轮流前进,窗口大小增增减减,窗口不断向右滑动。
寻找最长
int left = 0,right =0,length = 所给字符.size();
int result= 0,bestResult;
while(right<n){
扩大窗口,加入nums[right],并更新result
while(result不满足要求){
窗口缩小,left++;
}
更新最优的结果,right++;
}
return bestresult;
//int _sum =INT_MAX;
int_min = INT_MIN