【LeetCode刷题笔记】(二)双指针专题

84 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第31天,点击查看活动详情 这也是第36篇文章

删除有序数组中的重复项

题目

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

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

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

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

思路

快慢指针。当没有遇到重复元素时,两个指针是同步的,但是遇到重复元素时,慢指针不前移,导致下次快指针指向的值赋给当前慢指针指向的位置,从而将重复的元素覆盖。 最后慢指针指向的位置就是有效数组长度了(因为慢指针从1开始遍历)

代码实现

class Solution {
    public int removeDuplicates(int[] nums) {
        int n=nums.length;
        int j=1;
        for(int i=1;i<n;i++){
            if(nums[i]!=nums[i-1]){
                nums[j]=nums[i];
                j++;
            }
        }
        return j;
    }
}

类题——移除元素

题目

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

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

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

思路

和前面那题一样,快慢指针,只是if条件里面的变量换成了val;快慢指针初始指向的位置也不同(这次是从下标0开始)。

代码实现

class Solution {
    public int removeElement(int[] nums, int val) {
        int n=nums.length;
        int j=0;
        for(int i=0;i<n;i++){
            if(nums[i]!=val){
                nums[j]=nums[i];
                j++;
            }
        }
        return j;
    }
}

合并两个有序数组

题目

给你两个按 非递减顺序 排列的整数数组 nums1 **和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 **到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意: 最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

思路

写题解时我还特意去翻了一下自己曾经的提交记录,发现那时候竟然是直接将2的元素先填到1,然后再排序,并没有用双指针。于是用双指针又写了一遍,下面代码会附上两个版本的实现。 双指针的解法思想和前面两道题大同小异。

代码实现

暴力法,直接塞进去再排序

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        for(int i=m,j=0;j<n;i++,j++){
            nums1[i]=nums2[j];
        }
        Arrays.sort(nums1);
    }
}

双指针法。ij分别指向两个数组,从后往前修改,把相对更大的放入1中。

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i=m-1,j=n-1;
        int r=m+n-1;
        int cur;
        while(i>=0||j>=0){
            if(i==-1) cur=nums2[j--];
            else if(j==-1) cur=nums1[i--];
            else if(nums1[i]>nums2[j]){
                cur=nums1[i--];
            }else cur=nums2[j--];
            nums1[r--]=cur;
        }
    }
}

写在最后的碎碎念

今天依然是一天都在回顾6.s081的实验,但是关于实验依然没什么新鲜的东西写,于是继续更新刷题笔记了。上一篇((一))有点跳跃,估计我自己之后看起来也都一脸懵,所以这次特意挑了一个鲜明的主题——双指针!