代码随想录 -- 双指针法

移除元素

题目链接

描述

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。

示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

你不需要考虑数组中超出新长度后面的元素。

题解:双指针法

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len = nums.size();
        int slow{0};
        for(int fast=0;fast<len;++fast){
        	if(nums[fast]!=val)
        		nums[slow++]=nums[fast];
        }
        return slow;
    }
};

题解:暴力

双层循环即可

反转字符串

题目链接

描述

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:
输入:[“h”,“e”,“l”,“l”,“o”]
输出:[“o”,“l”,“l”,“e”,“h”]

示例 2:
输入:[“H”,“a”,“n”,“n”,“a”,“h”]
输出:[“h”,“a”,“n”,“n”,“a”,“H”]

题解

class Solution {
public:
	void swap(char&c1,char&c2){
    	char tmp = c1;
    	c1=c2;
    	c2=tmp;
	}
    void reverseString(vector<char>& s) {
    	size_t left = 0,right = s.size()-1;

    	while(left <right){
    		swap(s[left],s[right]);
    		++left;--right;
    	}
    }
};

替换数字

描述

给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。

例如,对于输入字符串 “a1b2c3”,函数应该将其转换为 “anumberbnumbercnumber”。

对于输入字符串 “a5b”,函数应该将其转换为 “anumberb”

输入:一个字符串 s,s 仅包含小写字母和数字字符。

输出:打印一个新的字符串,其中每个数字字符都被替换为了number

样例输入:a1b2c3

样例输出:anumberbnumbercnumber

数据范围:1 <= s.length < 10000。

题解

#include <iostream>
#include <string>
using namespace std;

void change_string(string&s){
	size_t old_len = s.size();
	int count{0};
	for(int i=0;i<old_len;++i){
		if(s[i]<='9'&&s[i]>='0')
			++count;
	}
	s.resize(old_len+5*count);
	size_t new_len = s.size();
	for(int front = old_len-1,back=new_len-1;front>=0;--back,--front){
		if(s[front]>='0'&&s[front]<='9'){
			s[back]='r';
			s[back-1]='e';
			s[back-2]='b';
			s[back-3]='m';
			s[back-4]='u';
			s[back-5]='n';
			back-=5;
		}else
			s[back]=s[front];
	}
}
int main(){
	string s;
	cin>>s;
	change_string(s);
	cout<<s<<"\n";
	return 0;
}

翻转字符串里的单词

题目链接

描述

示例 1:
输入: “the sky is blue”
输出: “blue is sky the”

示例 2:
输入: " hello world! "
输出: “world! hello”
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:
输入: “a good example”
输出: “example good a”
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

题解

class Solution {
public:
	void deleteExtSpace(string&s){
		int slow{0},fast{0};
		size_t len{s.size()};
		while(fast<len&&s[fast]==' ')
			++fast;
		while(fast<len){
			if(fast>0&&s[fast]==' '&&s[fast-1]==' '){
				++fast;continue;
			}else{
				s[slow++]=s[fast++];
			}
		}
		if(slow-1>0&&s[slow-1]==' '){
			s.resize(slow-1);
		}else
			s.resize(slow);
	}
	void reverseStr(string&s,int beg,int end){
		if(end<beg)return;
		while(beg<end){
			char tmp = s[beg];
			s[beg]=s[end];
			s[end]=tmp;
			++beg;
			--end;
		}
	}
    string reverseWords(string&s){
    	deleteExtSpace(s);
    	reverseStr(s,0,s.size()-1);
    	int i,j;
    	for(i=0,j=0;i<s.size();++i){
    		if(s[i]==' '){
    			reverseStr(s,j,i-1);
    			j=i+1;
    		}
    	}
    	reverseStr(s,j,i-1);
    	return s;
    }
};

反转链表

题目链接

class Solution {
public:
    ListNode *reverseList(ListNode *head) {
    	if(!(head&&head->next))return head;
    	ListNode*pre = nullptr,*cur=head;
    	while(cur){
    		ListNode*tmp = cur->next;
    		cur->next = pre;
    		pre = cur;
    		cur = tmp;
    	}
    	return pre;
    }
};

删除链表的倒数第N个节点

题目链接

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode*fhead = new ListNode(0,head);
    	ListNode*slow = fhead,*fast = fhead;
    	while(n--)
    		fast = fast->next;
    	while(fast->next){
    		slow=slow->next;
    		fast=fast->next;
    	}
    	slow->next = slow->next->next;
    	return fhead->next;
    }
};

链表相交

题目链接


class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        size_t lA{0},lB{0};
        ListNode*a = headA;
        while (a){
            lA++;
            a=a->next;
        }
        ListNode*b = headB;
        while (b){
            lB++;
            b=b->next;
        }
        //a 短  b长
        a=lA>lB?headB:headA;
        b=lA>lB?headA:headB;
        size_t len = lA>lB?lA-lB:lB-lA;
        while (len--)
            b=b->next;
        while (a&&b){
            if(a==b)
                return a;
            a=a->next;
            b=b->next;
        }
        return nullptr;
    }
};

环形链表II

题目链接

class Solution {
public:
    ListNode* detectCycle(ListNode *head) {
        ListNode*slow=head,*fast=head;
        while (fast && fast->next){
            slow=slow->next;
            fast=fast->next->next;
            if(slow==fast){
               //存在环
               slow = head;
                while (slow!=fast){
                    fast=fast->next;
                    slow=slow->next;
                }
                return slow;
            }
        }
        return nullptr;
    }
};

三数之和

题目链接

class Solution {
public:
    vector<vector<int>> threeSum(vector<int> &nums) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        size_t len = nums.size();
        for (int i = 0; i < len; ++i) {
            if (nums[i] > 0)break;
            //去重i
            if (i > 0 && nums[i] == nums[i - 1])continue;
            int slow = i + 1, fast = len - 1;
            while (slow < fast) {
                if (nums[i] + nums[slow] + nums[fast] > 0)
                    --fast;
                else if (nums[i] + nums[slow] + nums[fast] < 0)
                    ++slow;
                    //nums[i]+nums[slow]+nums[fast] == 0  还要考虑对slow fast去重
                else {
                    result.push_back(vector<int>{nums[i], nums[slow], nums[fast]});

                    //有重复 进行移位
                    // fast是和前一位比较 如果相同可以用前一位替换
                    // slow是和后一位比较 如果相同可以用后一位替换
                    while (slow < fast && nums[slow] == nums[slow + 1])
                        ++slow;
                    while (slow < fast && nums[fast] == nums[fast - 1])
                        --fast;

                    //fast slow没有重复也要位移
                    ++slow;
                    --fast;
                }
            }
        }
        return result;
    }
};

四数之和

题目链接

class Solution {
public:
    vector<vector<int>> fourSum(vector<int> &nums, int target) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        int len = nums.size();
        for (int i = 0; i < len; ++i) {
            if (nums[i] > target && nums[i] >= 0)break;
            //去重第一个
            if (i > 0 && nums[i] == nums[i - 1])continue;

            //下面和复现三数之和
            for (int j = i + 1; j < len; ++j) {
                int tmp = nums[i] + nums[j];
                if (tmp >= 0 && tmp > target)break;
                if (j > i + 1 && nums[j] == nums[j - 1])continue;

                int left = j + 1, right = len - 1;
                while (left < right) {
                    if ((long) tmp + nums[left] + nums[right] > target)
                        --right;
                    else if ((long) tmp + nums[left] + nums[right] < target)
                        ++left;
                    else {
                        //相等 但是对left和right去重
                        result.push_back(vector<int>{nums[i], nums[j], nums[left], nums[right]});
                        while (left < right && nums[left] == nums[left + 1])++left;
                        while (left < right && nums[right] == nums[right - 1])--right;

                        //正常的移动
                        ++left;
                        --right;
                    }
                }
            }
        }
        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值