今日学习链接:代码随想录 (programmercarl.com)
一、第一个
题目内容:力扣链接704. 二分查找 - 力扣(LeetCode)
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
1.第一想法:
简单的有序查询,可直接遍历,找到target为止,否则直接返回。因此,优化可以直接利用二分查找逼近,从而减少查询次数。
2.代码随想录的启发:
对符号的理解很棒,唔!果然,要善于总结,不能只停留在通过。而二分法的关键就在于,子查找是在哪个区域,包括哪部分内容。
3.代码:
int search(int* nums, int numsSize, int target){
int left=0,right=numsSize-1;
int mid = 0;
while(left<=right){
mid=(left+right)/2;
if(target==nums[mid]){return mid;}
else if(target<nums[mid]){right=mid-1;}
else{
left=mid+1;
}
}
return -1;//没找到就返回-1
}
4.结果:
慢了慢了,有点拉,没事,继续继续
小插曲:笑死,符号搞错了位置,导致结果是反的,就离谱
二、第二个咯
题目内容:
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
1.第一想法:
最简单的就是,啥也不用想双循环直接跑,找到一个就从后往前把元素挪过来,这样的复杂度是o(n^2);
仔细想想,可以看到输出中剩余元素的顺序是无关紧要的,因此可以先排序后删除。
2.随想录后记:
哦,哈哈哈,看了以后发现也没必要排序,快慢指针法会更快。快指针用于遍历数组元素寻找非val元素,当出现该元素时,慢指针不动,快指针往后;没有就同步往后。
3.代码:
第一种:傻瓜式暴力法
int removeElement(int* nums, int numsSize, int val){
for(int i=0;i<numsSize;i++)
if(nums[i]==val){
Size--;//新数组长度减1
for(int j=i;j<=numsSize-1;j++){
nums[j]=nums[j+1];//把后边的往前挪
}
i--;
}
return numsSize;
}
第二种: 双指针法
int removeElement(int* nums, int numsSize, int val){
int low=0,high=0;
for(;high<numsSize;high++){//high就是遍历用的指针
if(nums[high]!=val){
nums[low]=nums[high];
low++;
}
}
return low;
}
4.结果
第一种:
第二种:
5.反思:
5.1
其实傻瓜式也有bug出现,因为每次外循环直接加一,遇到相等就把后面的补了上来,所以中间出了点小问题,所以每次补齐以后将i重新刷新一下,有点中断处理的感觉,这样避免了,连续两个需要删除却没完成的情况。样例:
[3,2,2,3,5,6,7,7,8,9]
7预计输出:[3,2,2,3,5,6,9,8]
如果不加 i--这一步,会出现输出:[3,2,2,3,5,6,7,8,9]
5.2
这个快慢指针法很灵性,慢的记录长度,快的用于扫描,很好!但是这个执行时间和内存消耗,很奇怪,我最开始的方法竟然耗时0ms,比第二章还少,不懂,后面回来再详细看看为啥?