领扣网算法学习笔记
本系列的算法题目来自领扣网
数组类算法第三天
题目:删除排序数组中的重复项
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 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。
解题过程:
思路:
看到这道题时,感觉很简单,直接动手写,写完测试时发现怎么做都不对,然后发现题目审错了,开始我以为只是一个数组,没有排序,需要在不使用额外空间的情况下以O(1)完成,所以我的思路是记录最后一个不相同的元素的位置,初值为最后一个元素的位置,将相同的元素与最后一个元素交换,然后记录的位置往前移一位,这样就无需遍历了。但是后面测试代码出现问题,后面审题才发现是有序的。于是思路简化,直接定义一个变量用来记录不同值的位置,然后将不同值依次从第一位赋值过去即可。
代码如下:
class Solution {
public int removeDuplicates(int[] nums) {
// 因为数组有序,所以重复值只能在一起,所以定义一个变量,循环遍历数组,当出现一个不同值时,数值加一
int numdate = 1;
for(int i=0;i<nums.length-1;i++){
if(nums[i]!=nums[i+1]){
nums[numdate] = nums[i+1];
numdate++;
}
}
return (numdate);
}
}
// 用时14ms
后续思考:
审题这事不容忽视,工作中,弄清业务需求也一样,不然开发再完美,但是不符合需求,而且还浪费了时间。
领扣上面该题其他高质量范例:
class Solution {
public int removeDuplicates(int[] nums) {
int index = Integer.MAX_VALUE ;
int counter = 0 ;
for(int i=0; i<nums.length; i++){
if(nums[i] == index) nums[i] = Integer.MAX_VALUE ;
else {
counter++ ;
index = nums[i] ;
}
}
Arrays.sort(nums);
return counter ;
}
}
// 用时10ms
自我整理:
领扣上还有时间更短的示例,但是思路和我的类似,有的差不多只是变量名不同,但是执行时间就是比我的快,百思不得其解。
这个例子算是与我的区别比较大的一种。
我的是比较相邻的两个值是否相同,这里是当值没有变化时,位置不变,继续往后读取比较,变化后再重新赋值比较;
但是这个没有对数组进行排序,后面再使用Arrays.sort进行排序的。
代码优化:
class Solution {
public int removeDuplicates(int[] nums) {
int numdate = 0;
for(int i=1;i<nums.length;i++){
if(nums[numdate]!=nums[i]){
numdate++;
nums[numdate] = nums[i];
}
}
return (numdate+1);
}
}
// 用时8ms
自我整理:
优化内容就不总结了,主要明白了一点,原来去数组中取指定位置的值也是需要时间的,所以这也是一个优化点。