领釦网算法学习笔记 - 80

领釦网算法学习笔记

本系列的算法题目来自领釦网

数组类算法第一天

题目:

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

示例:

给定 nums = [1,1,1,2,2,3],
函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。
给定 nums = [0,0,1,1,1,1,2,3,3],
函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。

说明:

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

解题过程:

思路:

根据之前的题目,看到这个题目的第一感觉是:我只要判断是的第几个重复值就OK了。

定义一个变量用来记录当前是第几个重复值,如果当前两个判断的值是一样的,且为这个变量的值为0,则保存这两个值,把这个变量的值改为1,后续判断时,因为这个变量值为一,所以重复值会忽略,当遇到两个不同的值时,则保存数据,且把这个变量的值变回0.

代码如下:

class Solution {
    public int removeDuplicates(int[] nums) {
        // 思路:定义一个变量用来记录当前是第几个重复值,如果当前两个判断的值是一样的,且为前两个则改变这个变量的值
        // 如果当前变量的值改变了,则接下来的相同的数据就忽略掉
        
        if(nums.length==0 || nums.length==1){
            return nums.length;
        }
        
        int repeatNum = 0;  // 如果repeatnum为0,则表示为前两个值,此时改变repeatNum值,当判断的值变化时在变回去
        int numDate = 0;    // 保存新数组的位置
        
        for(int i=1;i<nums.length;i++){
            if(nums[numDate]==nums[i] && repeatNum == 0){
                numDate++;
                nums[numDate] = nums[i];
                repeatNum = 1;
            }
            if(nums[numDate]!=nums[i]){
                numDate++;
                nums[numDate] = nums[i];
                repeatNum = 0;
            }
        }
        return (numDate+1);
    }
}
// 用时15ms

后续思考:

该方法我觉得已经很简便了,只需要循环一次数组且不会多次修改比较值,但是还不是最优的,最优的方法在不看优质解答的情况下真没思路了,证明思维还是有所欠缺的。

领釦上面该题其他高质量范例:

class Solution {
    public int removeDuplicates(int[] nums) {    
        int i = 0;
		for (int num : nums) {
			if (i < 2 || num > nums[i - 2]) {
				nums[i++] = num;
			}
		}
		return i;
    }
}
// 用时 <1ms

自我整理:

  1. 这个代码,不能说惊艳到我了,毕竟只有短短的这一段,但是这个思路很值得我借鉴。
思路:

​ 因为要重复值最多保留两个,所以只要现在的值和第三个的值不一样就可以了。不管第二个值相不相同。

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

自我整理:

  1. 用时1ms的代码只是比小于1ms的代码多了个数据长度判断,思路是一样的。所以没写,

  2. 2ms这个思路其实也是一个方向吧,但是感觉没有像上一个那样新奇,思路还是比较大众的。

思路:

​ 它依然是定义一个变量来记录当前重复值的数量,根据变量的值来判定是否保留。

自我总结:

​ 其实很多时候,看着题目,我们需要发散一下思维,想一下都有哪些情况能达到题目的要求,不要侷限于一般的逻辑思维,可能目前的思维比较差,但是我觉得遇到问题时,在你很快能想到一个普遍的想法时,或许可以再多抽点时间想想有没有更好的方法。就算没有,发散一下思维,也能锻炼一下自己,使得下一次思维的扩展性变得更好。

点赞