leetcode双指针合集

if(nums[fastIndex] != val) {

nums[slowIndex] = nums[fastIndex];

slowIndex++;

}

}

return slowIndex;

}

};

344. 反转字符串


class Solution {

public:

void reverseString(vector& s) {

for(int i = 0,j = s.size()-1; i < s.size()/2; i++,j–) {

swap(s[i],s[j]);

}

}

};

剑指 Offer 05. 替换空格


class Solution {

public:

string replaceSpace(string s) {

/**

思路:

1.双指针(一个指针指向旧的字符串末尾ptr1,一个指针指向扩容后的字符串末尾ptr2)

2.对原字符串的扩容,因为%20是占3个空格的,所以要在原来一个空格基础上进行扩容

3.当遇到不是空格的时候,两个指针指向的字符就正常赋值,如果当ptr1指向空格的时候

ptr2就前面的3个空格 填上%20

*/

int count = 0;//记录空格数

int oldSize = s.size();

for(int i = 0; i < s.size(); i++) {

if(s[i] == ’ '){

count++;

}

}

s.resize(oldSize+2*count);

int newSize = s.size();

//i和j模拟指针

for(int i = oldSize-1,j = newSize-1; i>=0; i–,j–) {

if(s[i] == ’ '){

s[j] = ‘0’;

s[j-1] = ‘2’;

s[j-2] = ‘%’;

j = j-2;

}else{

s[j] = s[i];

}

}

return s;

}

};

151. 翻转字符串里的单词


class Solution {

public:

/**

思路:

1.去除空格(字符串前面的空格 字符串中间冗余的空格 字符串后面的空格)

2.反转字符串

3.将每个单词进行反转

**/

void removespacing(string &s) {

int slowIndex = 0,fastIndex = 0;//定义快慢指针(最终慢指针为去完冗余空格的字符串)

//去除字符串前面的空格

while(s[fastIndex] == ’ '){

fastIndex++;

}

for( ; fastIndex < s.size(); fastIndex++) {

//去除冗余的空格

if(fastIndex-1 > 0 &&

s[fastIndex-1] == s[fastIndex]

&& s[fastIndex] == ’ '){

continue;

}else {

s[slowIndex] = s[fastIndex];

slowIndex++;

}

}

//去除末尾的空格(如果字符串的末尾有多个空格的话 上方只能处理到末尾只有一个空格)

if(slowIndex-1 > 0 && s[slowIndex - 1] == ’ '){

s.resize(slowIndex-1);

}else{

s.resize(slowIndex);

}

}

void reverseStr(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) {

removespacing(s);

reverseStr(s,0,s.size() - 1);

for(int i = 0; i < s.size(); i++) {

int j = i;

//找到空格

while(j < s.size() && s[j] != ’ ') {

j++;

}

reverseStr(s,i,j-1);//这里j-1是因为s[j]已经表示的是空格了

i = j;

}

return s;

}

};

206. 反转链表


class Solution {

public:

ListNode* reverseList(ListNode* head) {

ListNode* temp;//存放临时结点

ListNode* cur = head;

ListNode* pre = NULL;

while(cur) {

temp = cur->next;

cur->next = pre;//调转指针

pre = cur;//往后移动一个结点

cur = temp;

}

return pre;//当cur指向5的时候 下一个就指向空 那么pre = cur 则就表示前指针表示指向的是5

}

};

19. 删除链表的倒数第 N 个结点


class Solution {

public:

ListNode* removeNthFromEnd(ListNode* head, int n) {

/**

思路:

1.双指针(慢指针p1,快指针p2)

2.要删除倒数第n个结点,也就是要正向删除 第(总的节点数 - n)个结点

3.为了处理倒数问题,先让p2往后移动n个结点,(这时候p2还剩下(总的节点数-n = sum)),那么此时

p1和p2一块移动,等到p2指向末尾的时候,p1也就指向要删除的结点

*/

ListNode* fakeNode = new ListNode(0);

fakeNode->next = head;

ListNode* slowNode = fakeNode;//慢指针

ListNode* fastNode = fakeNode;//快指针

while(n-- && fastNode != NULL) {

fastNode = fastNode->next;

}

fastNode = fastNode->next;//让其再快一格是为了当快指针到末尾的时候,慢指针指向要删除结点的

//的前一个结点

while(fastNode != NULL){

fastNode = fastNode->next;

slowNode = slowNode->next;

}

slowNode->next = slowNode->next->next;

return fakeNode->next;

}

};

18. 四数之和


class Solution {

public:

vector<vector> fourSum(vector& nums, int target) {

vector<vector >ans;

vector v;

sort(nums.begin(),nums.end());

for(int i = 0; i < nums.size(); i++) {

if(i > 0 && nums[i-1] == nums[i]) {

continue;

}

for(int j = i+1; j < nums.size(); j++) {

if(j-1 > i &&nums[j-1] == nums[j]){//这里的j-1大于i主要考虑的是我们去重复的是从

continue; //j开始指向的元素

}

int left = j+1;

int right = nums.size() - 1;

while(left < right) {

if(nums[i]+nums[j] > target - (nums[left]+nums[right])) right–;

else if(nums[i]+nums[j] < target - (nums[left]+nums[right])) left++;

else {

v.push_back(nums[i]);

v.push_back(nums[j]);

v.push_back(nums[left]);

v.push_back(nums[right]);

ans.push_back(v);

//去重处理

while(left < right && nums[right-1] == nums[right]) right–;

while(left > right && nums[left+1] == nums[left]) left++;

//换下一组

right–;

left++;

v.clear();

}

}

}

}

return ans;

}

};

15. 三数之和


class Solution {

public:

vector<vector> threeSum(vector& nums) {

/**

思路:

1.我们将所有元素进行升序处理(这样处理的话,我们可以知道当前面的元素大于0的时候,那么便一定

不会出现 a+b+c=0

2.这里我们设置三个指针(模拟的) 第一个指针(i)指向数组的第一个元素,第二个指针(left)指向数组的

第二个元素,第三个指针(right)指向数组的最后的元素

3.nums[i] + nums[left] + nums[right] > 0; right-- ,i和left不动

nums[i] + nums[left] + nums[right] < 0; left++,i和right不动

nums[i] + nums[left] + nums[right] = 0;left++,right–,i也移动一个单位

当我们找到一组答案的时候,就要同时移动三个指针;因为当我们找到一组答案的时候,如果不移动

i,只移动left和right,因为是升序的,那么的话nums[left] + nums[right] 只会更小

与nums[i]相加也不会等于0;如果我们想要最终的和为0,那么的话nums[i] < 0,nums[left] < 0,

nums[right] > 0,那么往后移动i,如果和为0的话 nums[left] + nums[right]的结果只会更小

因此我们每确定一组答案的时候,需要同时移动left,right,i

4.这里的去重,我们是当遇到相同的元素跳过它

*/

vector<vector >ans;

vectorv;

sort(nums.begin(),nums.end());

for(int i = 0; i < nums.size(); i++) {

if(nums[i] > 0){//如果首元素大于0的话那么就不会有和为0了

return ans;

}

if(i > 0 && nums[i] == nums[i-1]){

continue;

}

int left = i+1;

int right = nums.size() - 1;

while(left < right) {

int sum = nums[i] + nums[left] + nums[right];

if(sum > 0) right–;

else if(sum < 0) left++;

else {

v.push_back(nums[i]);

v.push_back(nums[left]);

v.push_back(nums[right]);

ans.push_back(v);

//去重处理(相邻的元素出现了重复)

while(left < right && nums[right-1] == nums[right]) right–;

while(left < right && nums[left+1] == nums[left]) left++;

//换下一组答案(上方的去重处理只是指针移动到最后一个重复的元素)

right–;

left++;

v.clear();

}

}

}

return ans;

}

};

142. 环形链表 II


class Solution {

public:

ListNode *detectCycle(ListNode *head) {

/**

思路:

1.定义快慢指针(快指针一次移动一个节点,慢指针一次移动两个结点)

2.如果有环的话那么的话快慢指针一定会相遇(因为如果没环的话快慢指针永远不相遇)

3.那么我们接下来就要确认出口在哪里,(根据以证明的结论,定义一个新的结点头指针指向它,然后快指针

和其一块移动,当其相遇的时候,就是出口.

**/

ListNode* slowNode = head;

ListNode* fastNode = head;

//当fastNode->next != NULL的时候 是允许fastNode->next->next 为空的

//如果没有此条件的话,那么当指针指向最后一个结点的时候,fast->next 已经为空了,它便不能再指向空了

//即fast->next->next (不能空指向空)

while(fastNode != NULL && fastNode->next != NULL) {

fastNode = fastNode->next->next;

slowNode = slowNode->next;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值