滑动窗口和双指针1

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

在刷了一百多道leecode题目后,发现了再好记性不如一次好的总结,所以对之前写过的leecode归类的做了一次总结,话不多说,我要开始了。


一、删除有序数组中的重复项

删除数组中的重复项
给你一个有序数组 nums ,请你** 原地** 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。

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

示例:

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

分析思路:这道题的难度属于简单题,相信很多人都可以写的出来,这道题的解法很多,每一种解法的左右指针含义不同,所以不重复元素所在的区间也会对应不一样

  • 初始化 左右指针,将left指针初始化为0,right初始化为1
  • left指针用于指向第一个不重复元素,right指针向后遍历
  • 当nums[rigth] != nums[left]时,让left++然后赋值nums[left] = nums[rigth];
  • 如此往复最终right = length - 1,退出循环,left等于最后一个不重复的元素,所以不重复元素的区间[0,left], left + 1为不重复元素的长度
  public int removeDuplicates(int[] nums) {
        int left = 0;
        for(int rigth=1;rigth<nums.length;rigth++){
            if(nums[rigth] != nums[left]){
                left ++;
                nums[left] = nums[rigth];
            }
        }
        return left +1;
    }

二、最长连续递增序列

674. 最长连续递增序列
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
示例

连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], …, nums[r - 1], nums[r]] 就是连续递增子序列。

输入:nums = [1,3,5,4,7]
输出:3
解释:最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。

思路分析:因为我们要找的子序列是连续的,并且是严格的递增的

  • 如果当后一个元素严格大于左边的元素时,连续递增的长度 + 1
  • 否者将会重新开始计算
class Solution {
    public int findLengthOfLCIS(int[] nums) {
        int len = nums.length;
        int res = 0;
        int i = 0;
        int j = 0;
        while (j < len) {
            if (j > 0 && nums[j - 1] >= nums[j]) {
                i = j;
            }
            j++;
            res = Math.max(res, j - i);
        }
        return res;
    }
}

三、移动元素

给你一个数组 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],也会被视作正确答案。

思路分析:因为不考虑超出新长度后边的元素,并且要在原地修改,所以这道题和删除有序数组中的重复项非常类似,说是一模一样也不过分

  • 让 l 遇到要删除的值的时候停留,让r往下找,当r不等于要删除的值的时候交换,l后移(因为交换后当前值改变)
  • 有几个目标值l就少移动几次,当循环退出的时返回 l
class Solution {
    public int removeElement(int[] nums, int val) {
        int l = 0;
        for(int r=0;r<nums.length;r++){
            if(nums[r] != val){
                int temp = nums[l];
                nums[l] = nums[r];
                nums[r] = temp;
                l++;
            }
        }
        return l;
    }
}

四、 删除排序数组中的重复项 II

删除排序数组中的重复项 II
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。

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

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

思路分析:

  • l、r初始化从 2 开始,因为数组是有序的如果与前面的一样,说明出现了2次以上
  • l 始终停留在某一个数出现两次以上的位置,让r往后移动直到二者位置上的值不相等的时候开始赋值,l后移
  • 一直往后走,最后返回l
class Solution {
    public int removeDuplicates(int[] nums) {
        int l = 2;
        for(int r = 2;r < nums.length;r++){
            if(nums[l - 2] != nums[r]){
                nums[l] = nums[r];
                l++;
            }
        }
        return l;
    }
}

五、移动零

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

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

示例

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

思路分析:和前面的题目类型简直一模一样

  • l r 两个指针刚开始指向同一位置,当出现0时,l指针负责指向零,r往后移动,r不为零的时候,发生交换,
class Solution {
    public void moveZeroes(int[] nums) {
        int l = 0;
        for(int r = 0;r<nums.length;r++){
            if(nums[r] != 0){
                int temp = nums[l];
                nums[l] = nums[r];
                nums[r] = temp;
                l++;
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值