704.二分查找
手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找
状态:明白理论,但是代码实现出现了一堆问题
思路
leetcode从的704题是一道原汁原味的二分查找法的题目,比较容易,注意二分查找的前提条件是有序顺序数组,且对于边界条件的处理,即究竟使用的是左闭右闭的区间还是使用的左闭右开的区间,都有不同的处理策略。
左闭右闭区间
第一种写法是定义target是在一个左闭右闭的区间,即[left,right]
代码实现:
int left=0;
int right=nums.size()-1;//因为是左闭右闭区间,因此right所指的元素是合法值
while(left<=right){//因为right 所指元素是合法值,因此要使用<=
int mid=left+((right-left)/2);//防止溢出
if(nums[mid]>target)
right=mid-1;//在if条件判断中已经判断过mid所指元素不符合条件,因此right应该为mid-1
else if(nums[mid]<target)
left=mid+1;
else
return mid;
}
return -1;
}
左闭右开区间
代码实现:
int left=0;
int right=nums.size();//与左闭右闭区间的差别在于左闭右开区间right所指的元素并不是一个有效值,因此他应该指向有效值的后一个位置表示开区间
while(left<right){//因为right并不是一个有效值,所以left不可能与right相等
int mid=left+((right-left)/2);//防止溢出
if(nums[mid]>target)
right=mid;//划分区间到左区间同样遵循right表示开区间,指向的为有效值的后一个位置来表示开区间
else if(nums[mid]<target)
left=mid+1;
else
return mid;
}
return -1;
}
最后,用于实现二分查找的时间复杂度为o(logn)空间复杂度为o(1)
27.移除元素
数组中移除元素并不容易! | LeetCode:27. 移除元素
状态:只会用暴力解,并且对于数组元素整体移动很模糊
思路
思路一(暴力解法)
使用两层for循环,外层循环遍历数组,搜索与val值相同的元素,内层循环更新数组,保证数组元素在内存地址上连续的特性
代码实现:
//暴力解法
int size=nums.size();//一味考虑修改nums.size(),忘记可以把其值用一个变量记录
for(int i=0;i<size;i++){
if(nums[i]==val){
//int j=i+1;int k=i;
//for(;j<size;j++,k++){//数组在内存地址中是连续存放的,所有元素依次向前移动,保证数组的这种特性
// nums[k]=nums[j];
//忘记怎么删除顺序表数组元素了
for(int j=i+1;j<size;j++)
nums[j-1]=nums[j];
size--;
i--;//因为下标i以后的元素都向前移动了一位,所以i也向前移动一位;
}
}
return size;
显然时间复杂度为o(n^2)空间复杂度为o(1)
思路二(双指针)
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作
首先要明白快慢指针都代表什么含义:1.快指针:用于寻找新数组元素的指针,新数组就是值不含有目标元素的数组
2.慢指针:用于更新新数组下标的指针(代表的是真实的数组下标)
总体可以理解为一句话:前方探路,后方整顿。整体就是一个覆盖原来数组的过程,如果快指针探索到的元素值与目标元素不一样,就覆盖到慢指针所指的位置,如果快指针探索到的位置与目标元素一样,那么就不管该元素,快指针继续向后探索,这样等快指针探索到旧数组的最后一个位置,新慢指针所更新的新数组一定不包含目标元素。
代码实现:
int slowindex=0,fastindex=0; for(;fastindex<nums.size();fastindex++){ if(nums[fastindex]!=val){ nums[slowindex++]=nums[fastindex]; } } return slowindex;
时间复杂度为o(n) 空间复杂度为o(1)
总结
在把思路转换为代码的过程中碰到较大的障碍,一方面是太久未写代码导致语法遗忘比较严重,一方面是一些细枝末节的地方掌握的不扎实导致编译的过程中一直出错,通过代码随想录的学习,对于c++的操作基本都回忆起来了,并且对于实现过程中的一些细节也都掌握了,今天收获很多,首先开拓了我对二分查找的思路,以前写二分查找就是直接上手,一通乱写,现在对于各种区间的定义以及相应的操作都理解的很透彻,第二复习了如何删除数组元素,原来只是停留在理论,现在可是动手实践出来了,是很大的进步,第三双指针算是入门了,掌握了双指针的简单应用,很有收获。