LeetCode26 27 删除排序数组中的重复项、移除元素

双指针常见用法

一、双指针法将时间复杂度O(n^2)的解法优化为 O(n)的解法,可以将时间复杂度一个数量级。

  • 27 移除元素
  • 15 三数之和
  • 18 四数之和

二、 双指针来记录前后指针实现链表反转

  • 206 反转链表

三、 使用双指针来确定有环

  • 142 环形链表2

LeetCode26 删除排序数组中的重复项

题目

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

双指针思路:

定义两个指针,快指针和慢指针

快指针用于发现重复元素,慢指针用于更新数组

  1. 当发现重复元素时,快指针跳过,慢指针不动

  2. 当确认快指针指向的元素与下一个元素不相同时,更新快慢指针,同时更新数组

代码

/**
 * @version V1.0
 * @ClassName:Leet26
 * @Description: 删除排序数组中的重复项
 * @author:Daniel
 * @date:2021/1/24 上午10:53
 */
public class Leet26 {
    
    

    public static void main(String[] args) {
    
    
        int[] nums = {
    
    0,0,1,1,1,2,2,3,3,4};
        int i = removeDuplicates(nums);
        System.out.println(i);
    }

    // 法一:快慢指针
    public static int removeDuplicates(int[] nums) {
    
    
        int i = 0; // 慢指针
        for (int j = 0; j < nums.length - 1; j ++) {
    
     // 快指针
            if (nums[j+1] == nums[j]) {
    
    
                continue;
            }
            nums[++i] = nums[j+1]; // 利用第一个元素一定不是重复的,进行错位
        }
        return i+1;
    }
}

LeetCode27 移除元素

题目

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

两种暴力解法的不同思路,并对第一种暴力解法做了优化。

使用快慢指针。

代码

/**
 * @version V1.0
 * @ClassName:Leet26
 * @Description: 移除元素
 * @author:Daniel
 * @date:2021/1/23 下午5:00
 */
public class Leet27 {
    
    
    public static void main(String[] args) {
    
    
        int[] nums = {
    
    3,2,2,3};
        int val = 2;
        int i = removeElement4(nums, 2);
        System.out.println(i);
    }

    // nums = [0,1,2,2,3,0,4,2], val = 2
    // 返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

    // 法一:暴力解法
    public static int removeElement(int[] nums, int val) {
    
    
        // 记录新数组长度
        int size = nums.length;
        for (int i = 0; i < size; ) {
    
    
            if (nums[i] == val) {
    
    
                size--;
                // 覆盖
                for (int j = i; j < nums.length - 1; j++) {
    
    
                    nums[j] = nums[j + 1];
                }
            }
            // 覆盖后,需要继续判断下标i处的元素是否等于val,若等则继续在i处覆盖,不等则i++
            i = (nums[i] == val) ? i : i + 1;
        }
        return size;
    }

    // 对法一的优化
    public static int removeElement4(int[] nums, int val) {
    
    
        int size = nums.length;
        for (int i = 0; i < size; i++) {
    
    
            if (nums[i] == val) {
    
    
                size --;
                for (int j = i; j < nums.length - 1; j ++) {
    
    
                    nums[j] = nums[j+1];
                }
                i--; // 优化,i也前移一位,重新判断nums[i]是否等于val
            }
        }
        return size;
    }

    // 法二:暴力解法 (别人提供的思路,比较优美)
    public static int removeElement2(int[] nums, int val) {
    
    
        // 新数组长度
        int size = nums.length;
        for (int i = 0; i < size; i++) {
    
    
            if (nums[i] == val) {
    
    
                for (int j = i+1; j < size; j++) {
    
    
                    nums[j-1] = nums[j];
                }
                i --; // 因为下标i以后的数值都向前移动一位了,所以i也向前移动一位
                size --; // 此时数组的大小-1
            }
        }
        return size;
    }

    // 解法三:快慢指针
    // 思路:
    // 1. 两个指针,前面一个后面一个,前面的用于搜索需要删除的值。
    // 2. 当遇到需要删除的值时,前指针直接跳过,后面的指针不动。
    // 3. 当遇到正常值时,两个指针都进行移动,并修改慢指针的值。
    public static int removeElement3(int[] nums, int val) {
    
    
        int i = 0; // 慢指针
        for (int j = 0 ; j < nums.length; j++) {
    
     // 快指针
            if (nums[j] == val) {
    
    
                // 如果等于目标值,则跳过(删除)
                continue;
            } else {
    
    
                // 如果不等于目标值,则赋值给 num[i], 并更新慢指针
                nums[i++] = nums[j];
            }
        }
        return i;
    }
}

猜你喜欢

转载自blog.csdn.net/DDDDeng_/article/details/113104674