Day01.二分查找、移除元素

0704.二分查找

题目链接:0704.二分查找

思路:二分查找,仅对有序数组有效。每次需要数组的中间值,与目标值比较大小,如果中间值比目标值大,说明目标值位置在left与mid中间,区间缩小一半;
同理,如果中间值比目标值小,说明目标值在mid与right中间,区间缩小一半。

二分查找最容易出错的地方是区间的确定,分为左闭右闭和左闭右开两种。不管哪一种,模板如下:

class Solution {public:int search(vector<int>& nums, int target){int left = 0;int right = /* 取值是 nums.size 或者 nums.size-1 */while (left /* < 或者 <= */ right) {int mid = left + (right - left) / 2;int cur = nums[mid];if (cur == target) {return mid;} else if (cur > target) {right = /* mid 或者 mid - 1 */} else {left = mid + 1;}}return -1;}
};

right的取值决定了区间类型,right = nums.size() - 1为左闭右闭区间,即[left,right]right = nums.size()为左闭右开区间,即[left,right)

左闭右闭时,循环条件中就是<=,因为是闭区间,right指向的值也应该被取到,如果为<,那么会少一个值。
判断语句中right = mid - 1,mid不是目标位置,不应该被取到,如果不减1,那么因为是闭区间,mid还是有可能被取到。因此左闭右闭区间的代码为:

class Solution {public:int search(vector<int>& nums, int target){int left = 0;// 左闭右闭区间int right = nums.size() - 1;// 当左闭右闭区间时,左右是可以相等的while (left <= right) {int mid = left + (right - left) / 2;int cur = nums[mid];if (cur == target) {return mid;} else if (cur > target) {// 当右边为闭合时,right需要mid-1right = mid - 1;} else {left = mid + 1;}}return -1;}
};

左闭右开时,循环中的条件就是<,因为是开区间,right可能并不在数组合法区间内,会有越界的风险,因此不能等于,只能小于。
判断语句中right = mid,mid不是目标位置,不应该被取到,又因为这里是开区间,本来就取不到,所以直接赋值即可。
如果这里mid减1,那么就会因为开区间,取不到mid前面的那个值。左闭右开区间代码:

class Solution {public:int search(vector<int>& nums, int target){int left = 0;// 左闭右开区间int right = nums.size();// 当左闭右开时,左右不能相等while (left < right) {int mid = left + (right - left) / 2;int cur = nums[mid];if (cur == target) {return mid;} else if (cur > target) {// 当左闭右开时,right值就是mid,不需要mid-1right = mid;} else {left = mid + 1;}}return -1;}
};

0027.移除元素

题目链接:0027.移除元素

思路1:借助erase接口,循环遍历数组,遇到目标值时,调用接口移除元素。由于元素删除后,后续元素会前移,就相当于索引后移,因此删除时索引不变。
直到数组被删到只剩索引大小或者索引位置不等于目标值时,索引才会后移。

class Solution {public:int removeElement(vector<int>& nums, int val){size_t ind = 0;while (ind < nums.size()) {while (ind < nums.size() && nums[ind] == val) {nums.erase(nums.begin() + ind);}++ind;}return nums.size();}
};

思路2:暴力解法,记录初始长度,使用索引遍历数组,寻找与目标相同的位置,然后从当前索引的后一个位置开始,将后面的值前移,同时长度减1,这就相当与删除了一个元素。
同样,因为是后面的值覆盖前面的值,就相当于索引后移,因此删除时,索引不变。只有当索引不是目标值时才向后移动。

由于这题不考虑顺序问题,所以在前移元素时,可以只把最后位置的和当前覆盖即可。可以减少复杂度。

class Solution {public:int removeElement2(vector<int>& nums, int val){if (nums.empty()) {return 0;}size_t length = nums.size();size_t ind = 0;// length随着元素移除会不断变小,当为0时退出while (length > 0 && ind < length) {if (nums[ind] == val) {// 当前值与目标值相等时,将后面的元素前移,覆盖当前值,这种方法可以保证元素顺序// 如果不考虑元素顺序,可以直接将最后一个元素放置在此处for (size_t i = ind + 1; i < length; ++i) {nums[i - 1] = nums[i];}--length;} else {++ind;}}return length;}
};

思路3:双指针法。删除的基本思想是旧元素覆盖新元素。快指针指向新元素,需要保留的元素;慢指针指向旧元素,需要被覆盖的元素。快指针从0开始,一直向后移动;慢指针从0开始,只有在被覆盖后才向后移动。
如果数组的前面没遇到目标值,那么快慢指针就会一直相等,快指针一直后移,因为没遇到目标值,会走覆盖的逻辑,慢指针也会一直后移。

参考连接:代码随想录-移除元素

学习视频:代码随想录-移除元素

class Solution {public:// 双指针// 删除元素的基本思想是:将目标元素后面的元素前移,将快指针指向新数组中的元素// 慢指针指向旧数组中应该被替换的位置int removeElement2(vector<int>& nums, int val){size_t slow = 0; // 指向需要被替换的位置size_t fast = 0; // 指向需要保留的位置for (fast; fast < nums.size(); ++fast) {// 只有当fast位置不等于目标值时,才会替换前面的位置// 当fast位置等于目标值时,跳过,slow位置没有被替换,因此不后移if (nums[fast] != val) {// 只有当fast不等于目标值时才会发生替换,++slow// 这里如果slow和fast可能相等nums[slow] = nums[fast];++slow;}// 不管是不是等于目标值,fast会一直后移}return slow;}
};

Day01.二分查找、移除元素相关推荐

  1. 第一天 :二分查找+移除元素

    数组基础 数组在内存空间的地址是连续的 数组下标都是从0开始 数组元素不能删,只能覆盖 二分查找 题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数 ...

  2. Python算法二分查找之重复元素列表

    描述: 请实现有重复数字的升序数组的二分查找 给定一个 元素有序的(升序)长度为n的整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的第一个出现的target,如果目标 ...

  3. 二分查找离左边元素最近的(可以等于)

    int compare(const void *a,const void *b) {return *(int *)a-*(int *)b; } //二分查找离元素(可以等于) int bi_searc ...

  4. 开花(在b数组中二分查找a数组元素)

    注意: 代码一:二层循环暴力查找超时 代码二(最棒):借用STL set中的count()方法快速搞定,且没有超时so,集合查询应该很快注意:count()时间复杂度是线性变换的最坏的情况为O(n)s ...

  5. 常考数据结构与算法-NC105 二分查找-II

    描述 请实现有重复数字的升序数组的二分查找 给定一个 元素有序的(升序)长度为n的整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的第一个出现的target,如果目标值存 ...

  6. 二分查找--AVL查找树

    Data Mining 开启阅读模式 二分查找--AVL查找树 二分查找可以找到元素在数组中的下标位置,而查找树由于采用的是树结构,所以只能判断出元素是不是在树中以及给出最大/小值,而不能确定指定元素 ...

  7. pat-1057 Stack 树状数组+二分查找

    题意 给我们一个n表示操作数量 然后三种操作 push和pop 还有求中位数的操作 让我们根据操作输出正确的解 分析 用sort排序做 或者 map标记法都会超时 考虑更快的方法 如何快速找到给定一串 ...

  8. 二分查找算法实现(图解)与实例

    现在我们来玩一个猜数的游戏,假设有一个人要我们猜0-99之间的一个数.那么最好的方法就是从0-99的中间数49开始猜.如果要猜的数小于49,就猜24(0-48的中间数):如果要猜的数大于49,就猜74 ...

  9. 二分查找的平均查找长度_二分查找

    1.什么是二分查找 数据的查找在计算机的操作中非常常见,那么我们应该怎样在计算机中实现查找操作呢? 最简单的一种方法:"傻找",也就是一个一个的找,我们把数组中的每个元素都和我们想 ...

最新文章

  1. SQL Server Management Studio 2012 设置脚本默认保存路径
  2. android之json解析优化,Android开发之json解析
  3. 15 sql base line 工作机制
  4. MAP(Mean Average Precision):
  5. 如何打造一份优雅的简历?
  6. Object c 基础知识
  7. 支付宝的一些小问题,注意事项等等,等用得时候在来写写
  8. 20200910:力扣204周周赛题解上(Java/Python/Cpp)
  9. golang key map 所有_Golang语言小技巧(踩坑)
  10. 如何下载Xcode DMG或XIP文件?
  11. python函数算面积_面积函数python
  12. 公开说说别人看不到_空间设置了权限说说所有人可见
  13. 拒绝精神内耗,5个适合中年人的自学网站,让你脱胎换骨
  14. 什么是数据科学?如何把数据变成产品?
  15. STM32 GPIO的配置寄存器(CRL、CRH)快速学习
  16. Spring AOP源码分析二
  17. 摄影教室:数码摄影区域曝光法实用教程
  18. Dart- move html element
  19. 以太坊Geth 共识算法源码解析
  20. 文件下载(下载文件名乱码解决方法)

热门文章

  1. c#通用后台管理系统
  2. Typora收费了,再找找免费的Markdown编辑器吗?
  3. node.js + express + mysql 简单运用
  4. 微信小程序的登录界面实现
  5. 用Qemu搭建x86学习环境
  6. java ext.dirs_关于-Djava.ext.dirs使用问题
  7. C/C++面试题-1
  8. MXL90614红外线测温传感器
  9. 以太网之父Bob Metcalfe荣获图灵奖,其同名定律成为互联网经济基石
  10. Win Server 系统远程桌面连接失败解决办法