提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目
互联网大厂们在公司养了一大批ACM竞赛的大佬们,吃完饭就是设计考题,然后去考应聘人员,你要做的就是学基础树结构与算法,然后打通任督二脉,以应对波云诡谲的大厂笔试面试题!
你要是不扎实学习数据结构与算法,好好动手手撕代码,锻炼解题能力,你可能会在笔试面试过程中,连题目都看不懂!比如华为,字节啥的,足够让你读不懂题
基础知识:
【1】LeetCode高频题15:三数之和
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = […]; // 输入数组
int[] expectedNums = […]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例:示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按 升序 排列
这种题目的思想,咱们已经见过多次了
啥思想呢?
就是i与i-1不相等的时候,咱们可以收集答案
你看看这个题:
【1】LeetCode高频题15:三数之和
当时的答案怎么收集?
以a开头,那么后续的答案,就不能再以a开头了,当然i=0时,直接要了答案【因为i=0是第一个,就不会重复的】
本题也是一样的,要求不能用外部数组转移,就空间复杂度o(1)
那么显然就是要把不重复的统统移动到左边来
那只要你i和i-1处数字不相同,咱就往前挪,用index来控制结果数组的位置变化
比如index=0,最开始的话
i=0,1,直接搬移放1,index++=1
i=1,1,查i-1也是1,不搬
i=2,2,查i-1=1,不同,搬i到index=1处,然后index++=2
i=3,2,查i-1也是2,不搬
i=4,2,查i-1也是2,不搬
i=5,3,查i-1=2,不同,搬i到index=2处,然后index++=3
i=6,4,查i-1=3,不同,搬i到index=3处,然后index++=4
i=7,4,查i-1也是4,不搬
完事
手撕代码:
//复习:
//那只要你i和i-1处数字不相同,咱就往前挪,用index来控制结果数组的位置变化
public int removeDuplicatesReview(int[] nums) {
if (nums == null || nums.length == 0) return 0;
int index = 0;//控制新结果,后续的不管
int N = nums.length;
for (int i = 0; i < N; i++) {
if (i == 0 || nums[i] != nums[i - 1]) nums[index++] = nums[i];
}
//最后index就是结果,咋着都会加1的
return index;
}
测试:
public static void test(){
int[] arr = {1,1,2,2,3,4,4};
int[] arr2 = {1,1,2,2,3,4,4};
Solution solution = new Solution();
int len = solution.removeDuplicates(arr);
for (int i = 0; i < len; i++) {
System.out.print(arr[i] +" ");
}
System.out.println();
len = solution.removeDuplicatesReview(arr2);
for (int i = 0; i < len; i++) {
System.out.print(arr2[i] +" ");
}
}
public static void main(String[] args) {
test();
}
结果OK
1 2 3 4
1 2 3 4
你也可以这样写
随意,反正实现了就行
public int removeDuplicates(int[] nums) {
if (nums == null || nums.length == 0) return 0;
//从0位置开始搜,找不同于当前i的数,填过来,同时每次记录我数组长++
int index = 0;//数组索引
int i = 0;
nums[index++] = nums[i];
while (i < nums.length - 1){
int j = i + 1;
while (j < nums.length && nums[i] == nums[j]) j++;
//当j那个数恰好不等于i
if (j < nums.length){//j不可越界
nums[index++] = nums[j];
}
i = j;//更新位置
}
return index;//这就是长度了
}
提示:重要经验:
1)这种i和i-1位置数字不一样的,才有必要收集答案的思想,咱们见过多次了,熟悉了就知道在这用,不用别人说你也能手撕代码
2)反正算法题就是优先考虑时间复杂度,再考虑空间复杂度
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。