LeetCode 704 二分查找
题目链接: https://leetcode.cn/problems/binary-search/submissions/
文章链接: https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
第一眼思路: 首先比较数组中间值与目标值的大小,根据大小调整搜索区间
遇到问题:
-
忘记一些处理数组的常用函数了,例如取数组中元素个数的nums.size(),这个博客里列举了一些常用函数:
https://blog.csdn.net/u012011912/article/details/131682992?ops_request_misc=&request_id=&biz_id=102&utm_term=c++%E5%A4%84%E7%90%86%E6%95%B0%E7%BB%84%E7%9A%84%E5%87%BD%E6%95%B0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-3-131682992.142v99pc_search_result_base4&spm=1018.2226.3001.4187 -
关于如何取中间值,因为太久没写代码,都有点记不清了,最开始将右下标减去左下标后除以二,忘记加左下标了。。
int middle = (right - left) / 2 + left;
- 第三个问题,写的时候没想到把left和right的比较拿来做while循环的跳出条件,用的数组middle值与target的比较,怎么写感觉怎么不对呢。。结果运行也超时了
看文章收获:
- 左闭右闭
- while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
- if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
- 左闭右开
- while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
- if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
最终代码!
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
int middle = (right - left) / 2 + left;
int i;
while(left <= right)
{
i = nums[middle];
if(i < target)
{
left = middle + 1;
}
if(i > target)
{
right = middle - 1;
}
else if(i == target)
{
return middle;
}
middle = (right - left) / 2 + left;
}
return -1;
}
};
提交后无意点开提交记录,这……真是零的突破啊,希望自己这次能真正地坚持下来!
LeetCode 27.移除元素
题目链接: https://leetcode.cn/problems/remove-element/description/
文章链接: https://www.programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html#%E6%80%9D%E8%B7%AF
第一眼思路: 先用一个for循环检测数组中和目标数值相同的元素,然后再用一个for循环移动元素,这是暴力解法,时间复杂度为O(n^2)
暴力解法如下:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int length = nums.size();
for(int i = 0;i < length;i++){
if(nums[i] == val){
for(int j = i + 1;j < length;j++){
nums[j - 1] = nums[j];
}
length--;
i--;
}
}
return length;
}
};
遇到的问题:
- 使用暴力解法时没注意到for循环中要i–,因为i后面的元素整体前移了一位,循环到for的控制语句时要i++,这样就不能检测到移动的哪一位,故要i–;
看文章思路: 学到了双指针法,通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新,新数组下标的位置
最终代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for(int fastIndex = 0; fastIndex < nums.size();fastIndex ++){
if(val != nums[fastIndex]){
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
};