Index LeetCode
双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。也可以延伸到多个数组的多个指针
若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域即为当前的窗口),经常用于区间搜索;
若两个指针指向同一数组,但是遍历方向相反,则可以用来进行搜索,待搜索的数组往往是排好序的。
BM87. 合并两个有序数组(188.合并两个有序数组)[easy]
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n){
int l1=m-1, l2=n-1, k=m+n-1;
while(l1>=0 && l2>=0){
if(nums1[l1] > nums2[l2]){
nums1[k--]=nums1[l1--];
}else{
nums1[k--]=nums2[l2--];
}
}
while(l2>=0){
nums1[k--]=nums2[l2--];
}
}
BM88. 判断是否为回文字符串(125.验证回文串)[easy]
输入:"race a car"
输出:false
bool isPalindrome(string s){
string tmp;
for(char c:s){
if(islower(c) || isdigit(c)) tmp+=c;
else if(isupper(c)) tmp+=tolower(c);
}
int left=0, right=tmp.size()-1;
while(left < right){
if(tmp[left++] != tmp[right--])
return false;
}
return true;
}
BM89. 合并区间(56.合并区间)[medium]
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]
//leetcode
vector<vector<int>> merge(vector<vector<int>>& intervals){
int n=intervals.size();
if(n==1) return intervals;
vector<vector<int>> res;
sort(intervals.begin(), intervals.end());
for(int i=0; i<n; i++){
int start=intervals[i][0], end=intervals[i][1];
while(i<n-1 && end>=intervals[i+1][0]){
end=max(end, intervals[i+1][1]);
i++;
}
res.push_back({start, end});
}
return res;
}
//牛客
static bool cmp(Interval& a, Interval& b){
return a.start < b.start;
}
vector<Interval> merge(vector<Interval> &intervals) {
if(intervals.size()==0) return intervals;
vector<Interval> res;
sort(intervals.begin(), intervals.end(), cmp);
res.push_back(intervals[0]);
for(int i=1; i<intervals.size(); i++){
if(res.back().end >= intervals[i].start){
res.back().end=max(res.back().end, intervals[i].end);
}else{
res.push_back(intervals[i]);
}
}
return res;
}
BM90. 最小覆盖子串(76.最小覆盖子串)[hard]
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
说明:给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""。
滑动窗口,哈希匹配
string minWindow(string S, string T){
unordered_map<int, int> hash;
for(char c:T) hash[c]++;
int left=0, cnt=0, minlen=s.size()+1, start=left;
for(int i=0; i<S.size(); i++){
if(--hash[S[i]] >= 0) cnt++; //覆盖计数
while(cnt == T.size()){
if(minlen > i-left+1){ //计算最小覆盖
minlen=i-left+1;
start=left;
}
if(++hash[S[left]] > 0) cnt--; //S[left]是否包含T中字符
left++;
}
}
return minlen==S.size()+1 ? "":S.substr(start, minlen);
}
BM91. 反转字符串(344.反转字符串)[easy]
输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]
void reverseString(vector<char>& s){
int left=0, right=s.size()-1;
while(left<right){
swap(s[left], s[right]);
left++;
right--;
}
}
BM92. 最长无重复子数组(3.无重复字符的最长子串)[medium]
输入:s = "abcabcbb"
输出:3
滑动窗口,哈希匹配
int lengthOfLongSubstring(string s){
if(s.size()==0) return 0;
unordered_map<char, int> hash;
int maxlen=0, left=0;
for(int i=0; i<s.size(); i++){
hash[s[i]]++; //窗口右移进入哈希表统计出现次数
while(hash[s[i]] > 1){ //出现次数大于1,有重复数据
hash[s[left++]]--; //窗口左移,同时减去该数字出现的次数
}
maxlen=max(maxlen, i-left+1); //维护最长无重复数组
}
return maxlen;
}
BM93. 盛水最多的容器(11.盛水最多的容器)[medium]
输入:[1,8,6,2,5,4,8,3,7]
输出:49
双指针
int maxArea(vector<int>& height){
int left=0, right=height.size()-1,res=0;
while(left<right){
res=max(res, min(height[left], height[right])*(right-left));
if(height[left] < height[right]) left++;
else right--;
}
return res;
}
BM94. 接雨水问题(42.接雨水)[hard]
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)
双指针
int trap(vectro<int>& height){
int left=0, right=height.size()-1, maxL=0, maxR=0, res=0;
while(left < right){
maxL=max(maxL, height[left]); //每次维护往中间的最大边界
maxR=max(maxR, height[right]);
if(maxR > maxL) //较短的边界确定该格子的水量
res+=maxL - height[left++];
else
res+=maxR - height[right--];
}
return res;
}
BM22.比较版本号(165.比较版本号)[medium]
输入:version1="1.01",version2="1.001"
输出:0
双指针,分段比较
int compareVersion(string version1, string version2){
int i=0,j=0;
while(i<version1.size() || j<version2.size()){
int a=0,b=0;
while(i<version1.size() && version1[i]!='.') a=a*10+(version1[i++]-'0');
while(j<version2.size() && version2[j]!='.') b=b*10+(version2[j++]-'0');
if(a>b) return 1;
if(b>a) return -1;
i++,j++; //跳过点
}
return 0;
}
BM54.三数之和(15.三数之和)[medium]
输入:nums=[-1,0,1,2,-1,-4] 找出三个数a,b,c;使得a+b+c=0
输出:[[-1,-1,2],[-1,0,1]]
*排序+双指针+去重
vector<vector<int>> threeSum(vector<int>& nums){
vector<vector<int>> res;
if(nums.size() < 3) return res;
sort(nums.begin(), nums.end());
for(int i=0; i<nums.size()-2; i++){
if(nums[i]+nums[i+1]+nums[i+2] > 0) return res;
if(i>0 && nums[i]==nums[i-1]) continue; //去重
int left=i+1,right=nums.size()-1;
while(left < right){
if(num[left]+nums[right] == -nums[i]){
res.push_back({nums[i], nums[left], nums[right]});
while(left<right && nums[left]==nums[left+1]) left++;
while(left<right && nums[right]==nums[right-1]) right--;
left++;
right--;
}else if(nums[left]+nums[right] > -nums[i]){
right--;
}else{
left++;
}
}
}
return res;
}