1.双指针
(1)题目示例1
- 因为数据有唯一解且两个数组都为升序,指针 i 指向A数组开头,指针 j 指向 B 数组结尾
- A[ i ] + B[ j ] > x : --j , A[ i ] + B[ j ] < x : ++i , A[ i ] + B[ j ] == x ,返回 i , j
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n,m,x;
cin >> n >> m >> x;
vector<int> A(n,0);
vector<int> B(m,0);
for(int i = 0 ; i < n;++i) cin >> A[i];
for(int i = 0 ; i < m;++i) cin >> B[i];
int i = 0;
int j = m-1;
while(true)
{
int temp = A[i] + B[j];
if(temp > x)
{
--j;
}
else if(temp < x)
{
++i;
}
else
{
cout << i << " " << j;
break;
}
}
return 0;
}
(2)无重复字符的最长子串
class Solution {
public:
int lengthOfLongestSubstring(string s)
{
int res = 0;
int chars[128] = {0}; //记录某个字符的个数
int j = 0;
for(int i = 0 ; i < s.size() ;++i)
{
chars[s[i]]++;
while(chars[s[i]] > 1) //如果该字符在 j ~ i 之间重复了,就要把最左边的该字符除去
{
chars[s[j]]--; //j不断右移除去 该字符
++j;
}
res = max(res,i-j+1);
}
return res;
}
};
(3)长度最小的子数组
//1.最简版 -(self)
int minSubArrayLen(int target, vector<int>& nums)
{
int res = INT_MAX;
int sum = 0;
for(int i = 0 ,j = 0 ; i < nums.size() ;++i )
{
sum += nums[i];
while(sum >= target)
{
res = min(res,i-j+1);
sum -= nums[j];
++j;
}
}
return res == INT_MAX ? 0 : res;
}
//2.清晰版
int minSubArrayLen(int target, vector<int>& nums)
{
int left = 0, right = 0, res = INT_MAX, len = 0;
int windows_sum = 0;
for(int i= 0 ; i < nums.size() ;++i)
{
if(nums[i] >= target)
return 1;
}
while(right < nums.size())//窗口区间为[left, right)
{
while(right < nums.size() && windows_sum < target) //增大窗口 ->右边先走
{
windows_sum += nums[right];//更新窗口状态
right++;
}
while(windows_sum >= target)//收缩窗口
{
len = right - left;
res = min(res, len); //更新窗口大小
windows_sum -= nums[left];//更新窗口状态
left++;
}
}
return res == INT_MAX? 0:res;
}
(4)三数之和
- 先确定一个数,再利用双指针去找另外两个数
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums)
{
//本题最重要的就是对a,b,c进行去重操作
vector<vector<int>> res;
int n = nums.size();
sort(nums.begin(),nums.end()); //排序
//小优化,最小的都 > 0
if(nums[0] > 0)
{
return res;
}
//枚举a
for(int i = 0 ; i < n ;++i)
{
//对a去重
if(i && nums[i] == nums[i-1] ) continue;
int left = i+1;
int right = n-1;
while(left < right)
{
if(nums[i] + nums[left] + nums[right] > 0)
{
--right;
}
else if(nums[i] + nums[left] + nums[right] < 0)
{
++left;
}
else //找到一组结果
{
//要对b,c去重
//去重逻辑应该放在找到一个三元组之后,对b 和 c去重
while(left < right && nums[left] == nums[left+1]) ++left;
while(left < right && nums[right] == nums[right-1]) --right;
res.push_back({nums[i], nums[left] ,nums[right]});
//找到答案时,双指针同时收缩
left++;
right--;
}
}
}
return res;
}
};
2.位运算
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> a(n,0);
for(int i = 0 ; i < n ;++i) cin >> a[i];
for(int i = 0 ; i < n ;++i)
{
int temp = a[i];
int count = 0;
while(temp)
{
if(temp & 1)
{
count++;
}
temp = temp >> 1;
}
cout << count << " ";
}
return 0;
}