1、数组
反转字符串(双指针从两边往中间收缩)
替换空格(一个指针标识索引,一个指针遍历操作;反向遍历;先扩容再遍历)
翻转字符串里的单词(一个指针标识索引,一个指针遍历操作)
class Solution {
public:
void reverse(string&s, int start, int end){
for(int i=start,j=end;i<j;i++,j--)
swap(s[i],s[j]);
}
string reverseWords(string s) {
int slow;//新字符串下标
//去除多余空格
for(int i=0;i<s.size();i++){
if(s[i]!=' '){//如果是空格,跳到下一个,非空格,手动添加一个空格
if(slow!=0)s[slow++]=' ';//不是第一个元素
while(s[i]!=' '&&i<s.size())//写入之前安全性检查
s[slow++]=s[i++];//单词写入
}
}
s.resize(slow);
//反转整个字符串
reverse(s,0,s.size()-1);
//反转每个单词
int start=0;
for(int i=0;i<=s.size();i++)
if(s[i]==' '||i==s.size()){
reverse(s,start,i-1);
start=i+1;
}
return s;
}
};
2、链表
反转链表(借助双指针改变指向,并借助临时指针防止断链)
struct ListNode* reverseList(struct ListNode* head){
typedef struct ListNode ListNode;
ListNode*pre=NULL,*cur=head;
ListNode*tmp;//记录当前节点下一个
while(cur){
tmp=cur->next;
cur->next=pre;
pre=cur;
cur=tmp;
}
return pre;
}
环形链表(快慢指针,快指针匀速靠近慢指针,一定在某处相遇)
3、N数之和
三数之和(一个指针遍历,两个指针从两边向中间收缩,注意去重)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>result;//结果数组
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++){
if(i>0)return result;//剪枝,第一个元素大于零,不可能存在
if(i>0&&nums[i]==nums[i-1])continue;//去重
//双指针
int left=i+1,right=nums.size()-1;
while(right>left){//收缩逻辑
if(nums[left]+nums[right]+nums[i]>0)right--;
else if(nums[left]+nums[right]+nums[i]<0)left++;
else{//先入栈再去重
result.push_back(vector<int>{nums[i],nums[left],nums[right]});
while((nums[left]==nums[left+1])&&(right>left))left++;
while((nums[right]==nums[right-1])&&(right>left))right--;
//没有重复,移动指针即可
right--;
left++;
}
}
}
return result;
}
};