双指针 EASY 21.11.13


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

我的解法

class Solution {
    public int removeDuplicates(int[] nums) {
        int len = nums.length, n = 0;
        if (len == 0 || len == 1){
            return len;
        }
        
        //创建一个新数组记录不重复的数字
        int[] sorted = new int[len];
        
        //遍历原数组,如果不相同就记录进新数组,相同就记录数组的长度减一
        //n是新数组的指针,当有非重复数字记录进新数组时,n++
        sorted[0] = nums[0];
        for (int i = 1; i < nums.length; i++){
            if (sorted[n] != nums[i]){
                sorted[n + 1] = nums[i];
                n++;
            }else {
                len--;
            }
        }
        //len是记录没有重复数字的数组长度,将新数组赋值给nums的前len位
        for (int j = 0; j < len; j++){
            nums[j] = sorted[j];
        }
        return len;
    }
}

执行用时:1 ms, 在所有 Java 提交中击败了96.24%的用户
内存消耗:39.7 MB, 在所有 Java 提交中击败了75.83%的用户


官方解法

不借助新的数组媒介,因为直接覆盖的要么是原元素,要么是重复的元素。

class Solution {
    public int removeDuplicates(int[] nums) {
        int n = nums.length;
        if (n == 0){
            return 0;
        }
        int flat = 1, slow = 1;
        while (flat < n){
            if (nums[flat] != nums[slow - 1]){
                nums[slow] = nums[flat];
                slow++;
            }
            flat++;
        }
        return slow;
    }
}

执行用时:1 ms, 在所有 Java 提交中击败了96.24%的用户
内存消耗:39.4 MB, 在所有 Java 提交中击败了95.73%的用户


88.合并两个有序数组

我的解法

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int index = 0;
        for (int i = 0; i < n; i++){
            while (index < m + i){
                if (nums2[i] <= nums1[index]){
                    insert(nums1, i, index, m);
                    nums1[index] = nums2[i];
                    break;
                }
                index++;
            }
            nums1[index] = nums2[i];
        }
    }
    public void insert(int[] nums1, int i, int index, int m){
        for (int j = m + i; j > index; j--)
            nums1[j] = nums1[j - 1];
    }
}

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.1 MB, 在所有 Java 提交中击败了96.39%的用户


官方解法


2.1 合并后排序

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

执行用时:1 ms, 在所有 Java 提交中击败了17.63%的用户
内存消耗:38.4 MB, 在所有 Java 提交中击败了75.55%的用户


2.2 双指针

该方法借助了新的数组

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int[] sorted = new int[m + n];
        int p1 = 0, p2 = 0;
        while (p1 < m || p2 < n){
            if (p1 == m){
                sorted[p1 + p2] = nums2[p2];
                p2++;
            }else if (p2 == n){
                sorted[p1 + p2] = nums1[p1];
                p1++;
            }else if (nums1[p1] > nums2[p2]){
                sorted[p1 + p2] = nums2[p2];
                p2++;
            }else {
                sorted[p1 + p2] = nums1[p1];
                p1++;
            }
        }
        for (int i = 0; i < m + n; i++){
            nums1[i] = sorted[i];
        }
    }
}

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.3 MB, 在所有 Java 提交中击败了88.29%的用户


2.3 逆向双指针

该方向可以避免覆盖。

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int p1 = m - 1, p2 = n - 1;
        while (p1 > -1 || p2 > -1){
            if (p1 == -1){
                nums1[p1 + p2 + 1] = nums2[p2];
                p2--;
            }else if (p2 == -1){
                nums1[p1 + p2 + 1] = nums1[p1];
                p1--;
            }else if (nums1[p1] > nums2[p2]){
                nums1[p1 + p2 + 1] = nums1[p1];
                p1--;
            }else {
                nums1[p1 + p2 + 1] = nums2[p2];
                p2--;
            }
        }
    }
}

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.2 MB, 在所有 Java 提交中击败了92.05%的用户


27.移除元素

我的解法

借助了新数组媒介

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

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:37 MB, 在所有 Java 提交中击败了50.39%的用户


官方解法

1、双指针

直接在原数组上改动

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

2、双指针优化

用左右双指针,避免重复赋值操作

01223042val=2
01403
class Solution {
    public int removeElement(int[] nums, int val) {
        int left = 0, right = nums.length;
        while (left < right){
            if (nums[left] == val){
                nums[left] = nums[right - 1];
                right = right - 1;
            }else {
                left++;
            }
        }
        return left;
    }
}

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36.6 MB, 在所有 Java 提交中击败了97.94%的用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值