LeetCode_03:Remove Element

1、总结:

上一题开心完今天就跪了,算法虽然也解决问题,但是不知道为什么空间复杂度居高不下。

2、题目:

Given an array nums and a value val, remove all instances of that value in-place and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
The order of elements can be changed. It doesn’t matter what you leave beyond the new length.

Example 1:

Given nums = [3,2,2,3], val = 3,
Your function should return length = 2, with the first two elements of nums being 2.
It doesn't matter what you leave beyond the returned length.

Example 2:

Given nums = [0,1,2,2,3,0,4,2], val = 2,
Your function should return length = 5, with the first five elements of nums containing 0, 1, 3, 0, and 4.
Note that the order of those five elements can be arbitrary.
It doesn't matter what values are set beyond the returned length.
3、我的解决方法:

解题思路依旧延续上一题:

// 方法一:
var removeElement = function(nums, val) {
    let len = 0;
    for(let i = 0; i < nums.length; i++) {
        if(nums[i] != val) {
            if(i > len) {
                nums[len] = nums[i]
            }            
            len++;
        }
    }
    return len;
};

在这里插入图片描述
经观察发现,如果不判断 i > len 这个方法依旧有效,只是少了判断,多了元素的左向移动,提交后发现速度的确小小的提升,不确定是因为元素copy的花销大于判断的花销,还是由于随机因素(网络环境等);

// 方法二:
var removeElement = function(nums, val) {
    let len = 0;
    for(let i = 0; i < nums.length; i++) {
        if(nums[i] != val) {
            if(i > len) {
                nums[len] = nums[i]
            }            
            len++;
        }
    }
    return len;
};

在这里插入图片描述

4、solution:

看过solution之后,又get了一种解法,就是当需要丢弃的元素很少时,上面的代码需要copy大量有效元素,例如[4, 3, 2, 1, 5, 6]
val 是 4 时,需要将[3, 2, 1, 5, 6]全部左移,这属于不必要的开销。于是,又产生了另一种解法:将需要丢弃的元素与数组的最后一位交换,同时数组长度减1,再从第i位重新检索。

// 方法三:
// when elements to remove are rare
var removeElement = function(nums, val) {
    let i = 0;
    let n = nums.length;
    while(i < n) {
        if(nums[i] == val) {
            nums[i] = nums[n-1];
            n--;
        } else {
            i++;
        }
    }    
    return n;
};

本以为这种方法会节约时间,但奇怪的是执行时间反而提升了:
在这里插入图片描述
因此 执行时间增长的原因待详查,这里依然记录这种解法以拓展解题思路。

5、其他人的解法:

大概看了一下,用到splice居多,差别就是正向遍历与反向遍历。
正向遍历时需要注意,splice移除元素之后,下次遍历需要再次遍历当前位置的元素,而不是向前一步。

// 方法五:
// 正向移除
var removeElement = function(nums, val) {
    for(let i=0; i < nums.length; i++) {
        if(nums[i] === val) {
            nums.splice(i, 1); 
            i = i-1;
        }
    }
   return nums.length;
};


// 方法四:
// 反向移除
var removeElement = function(nums, val) {
    for (let i = nums.length - 1; i >= 0; i--){
        if (nums[i] == val){
            nums.splice(i, 1);
        }
    }
    return nums.length;
};

效率如下,感觉相差不大:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值