【数组】删除有序数组中的重复项

1.问题描述

删除有序数组中的重复项

2.问题分析

2.1 数组元素移动法

因为题目所给数组是有序的,并且在删除元素期间是不可以使用在数组之外的空间。所以第一思路想到的就是遍历数组,如果发现有重复的元素,那么就让后面的元素来前移代替这个重复的元素。然后将数组长度-1。直到遍历完成。

2.1.1 实现代码

/**
    前提:数组有序、没有额外空间、在原数组上修改
    思路:示例:0 0 1 1 2 3
    1)从index=0开始遍历,判断nums[index]和nums[index+1]是否相同,若是相同,则2),若是不同,则3)
    2)从下标为index+1包含index+1的位置开始,后面的元素向前挪动一位,然后数组长度-1
    3)index累加,执行【判断逻辑 1)】==>直到index的位置等于当前数组长度-1。

    例子:
    0 0 1 1 2 3 
    1)0 1 1 2 3 3 因为发现重复元素,所以数据从第1位开始向前挪动,并且此时数组长度-1.更新为5.原本是6的
    2)index继续累加。发现1重复了。所以新的数组是 0 1 2 3 3 3,此时数组长度继续-1.更新为4,原本是5
    3)index继续累加到长度-1的位置。发现没有重复元素。遍历完成。最后的结果是前4个元素。
    0 1 2 3 
 */

class Solution {
    
    

    public int removeDuplicates(int[] nums) {
    
    
        
        int len = nums.length;
        for(int i=0;i<len-1;i++){
    
    
            if(nums[i]==nums[i+1]){
    
    
                changeArr(i+1,len-2,nums);
                len--;
            }
        }
        return len;
    }

    /**
        @param1 int start:开始向前挪动元素的开始位置
        @param2 int end:结束向前挪动元素的位置
        @param3 int[]nums :操作的数组
        // @retrun int[] nums :返回操作后的数组
     */
     public void changeArr(int start,int end,int[] nums){
    
    
        for(int i=start;i<=end;i++){
    
    
            nums[i] = nums[i+1];
        }
     }
}

public class MainClass {
    
    
    public static int[] stringToIntegerArray(String input) {
    
    
        input = input.trim();
        input = input.substring(1, input.length() - 1);
        if (input.length() == 0) {
    
    
          return new int[0];
        }
    
        String[] parts = input.split(",");
        int[] output = new int[parts.length];
        for(int index = 0; index < parts.length; index++) {
    
    
            String part = parts[index].trim();
            output[index] = Integer.parseInt(part);
        }
        return output;
    }
    
    public static String integerArrayToString(int[] nums, int length) {
    
    
        if (length == 0) {
    
    
            return "[]";
        }
    
        String result = "";
        for(int index = 0; index < length; index++) {
    
    
            int number = nums[index];
            result += Integer.toString(number) + ", ";
        }
        return "[" + result.substring(0, result.length() - 2) + "]";
    }
    
    public static String integerArrayToString(int[] nums) {
    
    
        return integerArrayToString(nums, nums.length);
    }
    
    public static void main(String[] args) throws IOException {
    
    
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while ((line = in.readLine()) != null) {
    
    
            int[] nums = stringToIntegerArray(line);
            
            int ret = new Solution().removeDuplicates(nums);
            String out = integerArrayToString(nums, ret);
            
            System.out.print(out);
        }
    }
}

2.1.3 算法分析

时间复杂度:因为每次发现重复元素都要遍历移动数据。所以时间复杂度O(n^2)
空间复杂度:没有占用额外空间

2.2 双指针取数法

大家都看过西游记,我这里类比唐僧没经过一个国家要通关文牒的例子。因为数据是有序的,所以我们把数据分类。每一个类别就是一个国家。那么这里的数据就是通关文牒。唐僧一直向前走,直到发现和上一个不同的国家才会去要通关文牒。那么这里也是同样的道理。
我们使用两个指针。指针1和指针2. 指针1指的是数组中不重复元素的位置,指针2的作用是遍历所有元素。
举例:
所给数组:0 1 1 2 2 2 4 6 6
指针1开始赋值=0
指针2同样也是0
1)指针2开始遍历,直到发现和自己值不一样的数据,也就是1.此时指针1++,并赋值为指针2发现的不同的数据
2)指针2继续遍历,发现了元素2. 指针1继续++,然后赋值为2
3)指针2继续遍历,发现4,然后指针1++,赋值为4
4)指针2继续遍历,发现6,然后指针1++,赋值为6
5)指针2越界,遍历结束
最后的结果是:
0 1 2 4 6

2.2.1 实现代码

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

2.2.2 算法分析

时间复杂度:因为只遍历一次,所以O(n)
空间复杂度:满足题目要求

Guess you like

Origin blog.csdn.net/weixin_41998764/article/details/118632619