保研机试前的最后七道数组题

快慢指针

原地修改数组元素

26. 删除有序数组中的重复项 - 力扣(LeetCode)这里我们选择用两种解法,第一种是用map去重,然后将值依次赋给nums;第二种是用快慢指针的思想

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        /*第一种:map*/
        map<int,int> m;
        int len=nums.size();
        for(int i=0;i<len;i++){
            m[nums[i]]=1;
        }
        int cnt=0;
        for(auto i:m){
            nums[cnt++]=i.first;
        }
        return cnt;
    }
};
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        /*第二种:快慢指针*/
        int len=nums.size();
        int left=0;
        int right=1;
        while(right<len){
            if(nums[left]==nums[right]){right++;}
            else{
                left++;
                nums[left]=nums[right];
                right++;
            }
        }
        return left+1;
    }
};

27. 移除元素 - 力扣(LeetCode) 思想与第一题一致,因为限制空间,所以没法用map去重(并且数组无序),请一定要注意双指针思想,因为当数组长度很大时,这个方法就显得尤为重要!

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len=nums.size();
        int left=0;
        int right=0;
        while(right<len){
            if(nums[right]==val){right++;}
            else{
                nums[left]=nums[right];
                left++;
                right++;
            }
        }
        return left;
    }
};

283. 移动零 - 力扣(LeetCode)真的不要太简单~,原地修改数组,请用双指针,当这种思想用到了别的题目时,记得会用哦

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        /*是不是就是原地修改数组类型,双指针!*/
        int len=nums.size();
        int left=0;
        int right=0;
        while(right<len){
            if(nums[right]==0){right++;}
            else{
                nums[left]=nums[right];
                left++;
                right++;
            }
        }
        for(int i=left;i<len;i++){
            nums[i]=0;
        }
    }
};

滑动窗口(过几日回来补)

明天继续更左右指针~

左右指针

二分(过几日回来补)

两数之和

思路真的很巧妙,左指针指向最左面,右指针指向最右面,两数之和大于关键值,说明右面的数大了;两数之和小于关键值,说明左面的数小了

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int> res;
        int left=0;
        int len=numbers.size();
        int right=len-1;
        while(numbers[left]+numbers[right]!=target){
            if(numbers[left]+numbers[right]>target){
                right--;
            }
            else{
                left++;
            }
        }
        res.push_back(left+1);
        res.push_back(right+1);
        return res;
    }
};

只要数组有序,就应该想到双指针技巧 

反转数组(reverse就好)

参考:C++中vector的reverse函数及其用法(详解)_vector reverse-CSDN博客

vector<int> vi ={1,2,3,4,5,6};
reverse(vi.begin(),vi.end());  //vi反转后为6,5,4,3,2,1

回文子串

5. 最长回文子串 - 力扣(LeetCode)第一想法是动态规划,明天用动规做一下(突然想起来是区间dp:AcWing---游戏---区间dp-CSDN博客

class Solution {
public:
    string Palindrome(string s,int i,int j){
        int len=s.size();
        int l,r;
        if(i==j){//以i为中心的奇串
            l=i;
            r=i;
            while(l>=0 && r<len && s[l]==s[r]){
                l--;
                r++;
            }
            l++;
            r--;
        }
        else{//以i,i+1为中心的偶串
            l=i;
            r=i+1;
            if(r==len || s[l]!=s[r]){return "";}
            while(l>=0 && r<len && s[l]==s[r]){
                l--;
                r++;
            }
            l++;
            r--;
        }
        return s.substr(l,r-l+1);
    }
    string longestPalindrome(string s) {
        /*遍历以i为中心*/
        string res="";
        int len_res=0;
        int len=s.size();
        for(int i=0;i<len;i++){
            string temp1=Palindrome(s,i,i);
            int len_temp1=temp1.size();
            if(len_temp1>len_res){res=temp1,len_res=len_temp1;}
            string temp2=Palindrome(s,i,i+1);
            int len_temp2=temp2.size();
            if(len_temp2>len_res){res=temp2,len_res=len_temp2;}
        }
        return res;
    }
};

看到回文串:左右指针从中心向两端扩展

动态规划做法:

class Solution {
public:
    string longestPalindrome(string s) {
        int len=s.size();
        vector<vector<int>> g(1010,vector<int>(1010,0));
        int l=0;
        int len_res=1;    
        string res;                        
        for(int i=1;i<=len;i++){//字符串的长度
            for(int j=0;j+i-1<len;j++){//字符串的起始位置
                if(i==1){
                    g[i][j]=1;
                    continue;
                }
                else if(i==2){
                    if(s[j]==s[j+1]){
                        g[i][j]=1;
                        if(len_res<i){
                            l=j;
                            len_res=i;
                        }
                    }
                    else{
                        g[i][j]=0;
                    }
                }
                else{
                    if(g[i-2][j+1]==1 && s[j]==s[j+i-1]){
                        g[i][j]=1;
                        if(len_res<i){
                            l=j;
                            len_res=i;
                        }
                    }
                    else{
                        g[i][j]=0;
                    }
                }
            }
        }
        //cout<<l<<endl;
        //cout<<len_res<<endl;
        res=s.substr(l,len_res);
        return res;
    }
};

明天将继续更新动态规划解决最长回文子串,以及四道数组双指针问题!

接下来更新4道数组双指针思想题目,找找感觉~ 

看这里:五道数组习题,只过思路-CSDN博客

参考:

双指针技巧秒杀七道数组题目 | labuladong 的算法笔记

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值