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

问题描述:给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。


示例1:

给定数组 nums = [1,1,2], 

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 

你不需要考虑数组中超出新长度后面的元素。

示例2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。

import java.util.ArrayList;
/**
 * 这个算法有一个前提是:数组是先经过排序的
 * @author 汤小萌
 *
 */
public class Demo01 {
    // 方法一:使用ArrayList
    public static int removeTheagain(int[] array) {
        ArrayList list = new ArrayList<>();
        if(array == null || array.length == 0) {
            return 0;
        } else if(array.length == 1) {
            return 1;
        } else {
            int i = 0;
            int n = array.length - 1; // 数组的最后一个元素的索引
            while (i <= n) {
                if(i == n) { // 走到了最后一个元素了,肯定是没有重复的 > 先先下面的算法
                    list.add(array[i]);
                } else {
                    int j = i+1; // 需要用来跟前面的元素进行比较的索引
                    if(array[i] == array[j]) { // 跟i索引大1的的元素跟i相等(相邻的两个元素相等)
                        // 跟i相邻的后一个元素跟i相等,那么还需要继续判断这个元素之后的元素是否跟i有相等的
                        while(j <= n && array[i] == array[j]) { // 遍历完元素,或者一旦发现没有相等了的就跳出来,(数组之前就已经进行了排序)
                            j++; // 如果后面的跟当前i有相等的,那么j就不断往后走,看后面是否还有相等的
                        }
                    }
                    list.add(i); // 需要把i索引加入到这个list集合中
                    // i的索引需要变成i相同元素的最后一个索引加1的位置(因为这个位置是跟i是不同的之后的第一个位置)
                    i = j;  // 此时还可能在循环中,还需要继续进行判断
                }
            }
        }
        for(int k = 0; k < list.size(); k++) {
            array[k] = list.get(k);
        }
        return list.size();
    }
    // 方法二:
    // 数组下标(指针)与临时变量,是解决数组相关面试题的两大法宝
    public static int removeTheAgain02(int[] array) {
        if(array == null || array.length == 0) {
            return 0;
        } else if(array.length == 1) {
            return 1;
        } else {
            // 定义一个临时的变量开始就是数组的第一个元素  (这个临时变量可以看成是一个指针)
            // 一旦发现了出现了不一样的数组,这个临时变量就需要变成下一个不重复的数组的元素了
            int temp = array[0];
            int len = 1;
            for(int i = 1; i < array.length; i++) {
                if(temp == array[i]) { // 如果数组的元素一直跟这个临时变量的值是相等的,那么就一直continue
                    continue;
                } else {
                    // 如果发现了数组中的元素跟这个临时变量的值不一样的话,那么这个临时
                    // 变量就要往下走,变成这个不重复的元素
                    temp = array[i];

                    array[len] = array[i]; // 如果只是想等到长度的话,这段代码是可以不用写的
                    len ++; // 这个len就相当于是一个计数器(计算的是不重复元素的个数)
                }
            }
            return len;
        }
    }
    // 这个算法更加巧妙,跟上面的算法有类似的地方,但是这个算法更加简便
    /**
     * 数组完成排序后,我们可以放置两个指针 i 和 j,其中 i 是慢指针,而 j 是快指针。只要 
     * nums[i]=nums[j],我们就增加 j 以跳过重复项
     * 当我们遇到 nums[j]≠nums[i] 时,跳过重复项的运行已经结束,因此我们必须把它(nums[j])的值复
     * 制到 nums[i+1]。然后递增 i,接着我们将再次重复相同的过程,直到 j 到达数组的末尾为止。
     * @param nums
     * @return
     */
    public static int removeTheAgain03(int[] nums) {
        if(nums.length == 0) return 0;
        int i = 0;
        for(int j = 1; j < nums.length; j++) {
            if(nums[j] != nums[i]) { // 
                i++;
                nums[i] = nums[j];
            }
        }
        return i+1;
    }
    public static void main(String[] args) {
        int[] nums = {0,0,1,1,1,2,2,3,3,};
        System.out.println(removeTheagain(nums));
    }

}

特此声明:题目来自LeeCode(非常好的网站)
乐扣网站的原题

你可能感兴趣的:(删除排序数组中的重复项(给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度))