leecode移除数组中元素相关问题(快慢指针法)C++

移除数组中元素相关问题

27. 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。

解答:
思想:使用快慢指针法,返回慢指针的最后的索引即可。

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

该方法时间复杂度:
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
也可以用暴力解法,两个for嵌套循环。
那样的时间复杂度就是:
时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( 1 ) O(1) O(1)

26. 删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 :

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

提示:
0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按 升序 排列

解答:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int slow=0;
        for(int fast=1;fast<nums.size();fast++){
            if(nums[fast]!=nums[slow]){
                nums[++slow]=nums[fast];   //注意此处要先++,先后移满指针
            }       
        }
        return slow+1;
    }
};

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

输入: nums = [0]
输出: [0]

提示:
1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1

解答:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int slow=0;
        for(int fast=0;fast<nums.size();fast++){
            if(nums[fast]!=0){
                nums[slow++]=nums[fast];
            }
            
        }
        for(int i=slow;i<nums.size();i++){
            nums[i]=0;
        }
    }
};

844. 比较含退格的字符串

给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。

注意:如果对空文本输入退格字符,文本继续为空。

输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。

输入:s = "ab##", t = "c#d#"
输出:true
解释:s 和 t 都会变成 ""。

输入:s = "a#c", t = "b"
输出:false
解释:s 会变成 "c",但 t 仍然是 "b"1 <= s.length, t.length <= 200
s 和 t 只含有小写字母以及字符 '#'

解答;

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        string s1,t1;
        s1=deal(s);
        t1=deal(t);
        
        return s1==t1; 
    }
    string deal(string s){
        if(s==""){return s;}
        int slow=0;
        for(int fast=0;fast<s.size();fast++){
            if(s[fast]!='#'){
                s[slow++]=s[fast];
            }
            else{
                slow--;
                if(slow<0){slow=0;}
            }        
        }
        return s.substr(0,slow);
    }
};

977. 有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 已按 非递减顺序 排序

解答:
思想:1、新建一个数组用来存储结果数组。2、双指针,一个从头开始,另一个从尾巴开始,取平方值大的存储起来。3、然后指针前移或后移。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> tmp(nums.size(),0);
        int front=0;
        int final=nums.size()-1;
        int k=nums.size()-1;
        while(front<=final){
            if((nums[final]+nums[front])<0){
                tmp[k]=nums[front]*nums[front];
                front++;
                k--;
            }
            else{
                tmp[k]=nums[final]*nums[final];
                final--;
                k--;
            }
        }
        return tmp;
    }
};

209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

输入:target = 4, nums = [1,4,4]
输出:1

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

解法一:暴力法
思想:两个for嵌套,一个一个筛查。
代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result=nums.size()+1;
        int sum=0;
        int sub=0;
        for(int i=0;i<nums.size();i++){
            sum=0;
            for(int j=i;j<nums.size();j++){
                sum+=nums[j];
                if(sum>=target){
                    sub=j-i+1;
                    if(sub<result)
                        result=sub;;
                        break;
                    }
            }
        }
        if(result<=nums.size()){return result;}
        else{return 0;}

    }
};

解法二:
思想:滑动窗口,前后两个指针,不断调整前后两个指针的位置,大于target的时候,就该移动前面的指针,然后比较子序列的长度,否则后面的指针后移。
代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result=nums.size()+1;
        int sum=0;
        int i=0;
        int sub=0;
        for(int j=0;j<nums.size();j++)
        {
            sum+=nums[j];
            while(sum>=target){
                sub=j-i+1;
                if(sub<=result){result=sub;}
                sum-=nums[i];
                i++;
            }
        }
        if(result<=nums.size()){return result;}
        else{return 0;}
    }
};

904. 水果成篮

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
示例:

输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。

输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。

输入:fruits = [1,2,3,2,2]
输出:4
解释:可以采摘 [2,3,2,2] 这四棵树。
如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。

输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。

提示:
1 <= fruits.length <= 105
0 <= fruits[i] < fruits.length

思想:
我的处理是在有三个及三个元素以上在进行排查。共四个指针,first就指向第一个篮子,second是第二个篮子,tmp是在第三个元素开始判断的指针,判断是否是前两个蓝色中的数,如果不是,first后移,second也后移。还有一个指针式p,用于检测是否是第一个篮子和第二个篮子的交替行为,因为比如3 3 3 1 2 1 1 2 3 3 4这类,如果不交替判断,会出现first指向index为3的位置,second指向index为4的位置,但实际second应该指向index为7的位置。c++
代码:

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int first=0;
        int second =1;
        int tmp=2;
        int result=0;
        int len=0;
        int p=second;
        if(fruits.size()==1){return 1;}
        if(fruits.size()==2){
            return 2;
        }

        for(;tmp<fruits.size();tmp++){
            if(fruits[tmp]!=fruits[second]&&fruits[tmp]!=fruits[first])
            {
                if(fruits[first]!=fruits[second]){
                    first=p;
                    second=tmp;
                }
                     second=tmp;        
            }
            if(fruits[p]!=fruits[tmp]){ //两个篮子的交替判断
                p=tmp;
            }
            len=tmp-first+1;
            if(len>=result){
                result=len;
            }
        }
        return result;
    }
};

你可能感兴趣的:(leecode,数组,leecode,c++)