小白的算法之路1

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

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

示例一:

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

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

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

示例二:

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

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

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

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

标准参考一:

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

标准参考二:

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

小白答案:

	public int removeDuplicates(int[] nums) {
		if(nums.length==0)return 0;
		int j=1;
		for(int i=0;i<nums.length;i++) {
			j=i+1;
			if(j>=nums.length)break;
			int temp=j;
			while(nums[i]==nums[j]) {
				j++;
				if(j>=nums.length)return i+1;
			}
			for(int m=temp;m<j;m++) {
			nums[m]=nums[j];
			}
			for(int k=j;k<nums.length;k++) {
				if(j>=nums.length-1)break;
				nums[k]=nums[j++];
			}
			
		}
		return nums.length;
	}

小白是一个大学三年级的学生,因为平时在学校做开发相对较多,也没有专门的去深究过算法,抱着想要学好的心态开始了自己的算法之路,如果在自己的文章中有不当之处,或者有能给予小白指导,欢迎留言。

 下面就讲一下自己对整个题目的理解及解题思路,并红着脸大致的讲解下好算法的妙处。

这是一道初级算法题。根据该题目的说明,就是去掉数组中重复的元素,并且不借助其他容器,实现“原地“”删除。刚拿到这道题目的时候原地爆炸,心里面在想:我这歌Set集合,貌似我只要把数组中的元素添加进去,他就会自动去重。当正准备写的时候,看了一下返回值,我的天,返回的是int类型,也就是说返回的是长度,传进来的nums[]数组我对他没有任何改动通过set集合去重,有什么用呢??所以马上有回过头看了两边题目,仔细的分析了下,我通过for循环,从第一个数组元素a[i]开始和后面的元素比较,如果相同,就该元素接着和后面的元素比较,这时里面就嵌套了个while循环,知道比较到不同值的元素a[j],此时我从a[i]到a[j]的所有元素全部更新为a[j],此处全部更新为的是防止出现1,2,1,2..这样的情况,由此就能将所有不同的元素全部赋值到数组的前端,并返回相应的长度。

相对参考一和参考二的答案,自己一下子就懵了。不是说看不懂,是因为发现自己在还没有发现说明中的元素规律就开始写了,比较的时候应该是a[i],a[i-1],同时i往增大的方向上去就可以了,没有必要说我的左边一端固定死了,通过右端的下标左右移动,这个是最重要的一点。其次就是发现了个大问题,就是自己在写for循环的时候喜欢写成:

for(int i=0;i<nums.length;i++){
    if(a[i]==a[i++]){
        ....
    }
}

而参考中的写法是:

for(int i=1;i<nums.length;i++){
     if(a[i-1]==a[i]){
        ....
    }
}

 显然,参考的写法能够避免大量的数组越界判断,是一个小技巧。

扫描二维码关注公众号,回复: 2729554 查看本文章

猜你喜欢

转载自blog.csdn.net/m0_37265215/article/details/81368012
今日推荐