目录

一 、二分查找

1 二分查找

2 搜索插入位置

3  在排序数组中查找元素的第一个和最后一个位置

二、移除元素


一 、二分查找

1 二分查找

704 二分查找https://leetcode.cn/problems/binary-search/

二分查找实际上就是:有序数组,查找目标元素

  • 找到中间值mid;
  •  目标值大于mid,就往右找,更新左边界;
  • 目标值小于mid,往左找,更新右边界。

左右边界的更新具体要根据左闭右闭还是左闭右开来判断。

左闭右开如下:

class Solution {public:int search(vector<int>& nums, int target) {//左闭右开int left = 0;int right = nums.size();//右边界为开区间,这里不包含nums[right]while(left < right){ // [ left , right)int mid = left + (right - left)/2;//防止溢出if(target > nums[mid]) left = mid+1;//目标值大于中间值,往右缩:[mid+1,right)else if(target < nums[mid]) right = mid;//目标值小于中间值,往左缩:[left,mid)else return mid;}return -1;}
};

 左闭右闭如下:

class Solution {
public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size() - 1; //[left, right]while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=int middle = left + ((right - left) / 2);// 防止溢出if (nums[mid] > target) {right = mid - 1; // 目标值小于中间值,即目标值在左边,[left, mid - 1]} else if (nums[mid] < target) {left = mid + 1; // 目标值大于中间值,即目标值在右边,[mid + 1, right]} else { return mid; // 找到目标值,直接返回下标}}// 未找到目标值return -1;}
};

2 搜索插入位置

35 搜索插入位置https://leetcode.cn/problems/search-insert-position/description/

题中也是给了排序数组和目标值,可以使用二分查找:本题的关键是如何处理当目标值不存在数组中,返回将按顺序插入的位置

本题可以细分为四种情况:

  1.  目标值将会插在数组最前面  [0,-1]
  2. 目标值将会插在数组之后 [left,right]
  3. 目标值将会插在数组之中 [left,right]
  4. 目标值在数组之中 return mid

 其中,前三种是需要处理的关键,第四种就可以直接利用二分法找到mid

二分法:

//左闭右闭
class Solution {
public:int searchInsert(vector<int>& nums, int target) {int left = 0;int right = nums.size()-1;int mid;while(left <= right){mid = left + (right - left)/2;if(target > nums[mid]) left = mid+1;else if(target < nums[mid]) right = mid-1;else  return mid;}//目标值将会插在数组最前面  [0,-1]//目标值将会插在数组之后 [left,right]//目标值将会插在数组之中 [left,right]//目标值在数组之中 return midreturn right+1;}
};

情况1:

情况2、3和情况1类似,比较好看出来

左闭右开:

//左闭右开
class Solution {
public:int searchInsert(vector<int>& nums, int target) {int left = 0;int right = nums.size();int mid;while(left < right){mid = left + (right - left)/2;if(target > nums[mid]) left = mid+1;//[left,right)else if(target < nums[mid]) right = mid;else  return mid;}//1. 目标值将会插在数组最前面  [0,0)//2. 目标值在数组之中 return mid//3. 目标值将会插在数组之中 [left,right)//4. 目标值将会插在数组之后 [left,right)return right;}
};

 暴力解法:

class Solution {
public:int searchInsert(vector<int>& nums, int target) {int size = nums.size();//for循环寻找目标值for(int i = 0;i < size;i++){//1.找到目标值//2.无目标值:应该插在数组最前面,即目标值最小//3.无目标值:插在数组中间if(nums[i] >= target){return i;}}//4.无目标值:应该插在数组最后,即目标值最大return size;}
};

3  在排序数组中查找元素的第一个和最后一个位置

在排序数组中查找元素的第一个和最后一个位置https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/description/ 本题一看就知道用二分法,但实际操作起来反而没那么好想:

查找开始位置和结束位置,可以转换成两个二分法分别查找左右边界

三种情况:

  1. 目标值不在数组中,应该插入至第一个或最后一个
  2. 目标值不在数组中,应该插至数组中
  3. 目标值在数组中,返回首尾索引

计算出来的左右边界,实质上是(left-1,right+1) 

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {int leftBorder = findLeftBorder(nums,target);int rightBorder = findRightBorder(nums,target);//这里注意不要用-1对左右边界进行初始化,因为当数组元素只有1个时,//左边界此时正好等于-1,就返回了{-1,-1}//而不是{0,0}if(leftBorder == -2 || rightBorder == -2) return {-1,-1};if(rightBorder-leftBorder > 1) return {leftBorder+1,rightBorder-1};return {-1,-1}; }//开始位置和结束位置:即左右边界,各自用二分法找到private:int findRightBorder(vector<int>& nums, int target){int left = 0;int right = nums.size()-1;int rightBorder = -1;while(left <= right ){int mid = left + (right - left)/2;if(nums[mid] > target){right = mid - 1;}else{ //找右边界,当目标值大于等于midleft = mid + 1;rightBorder = left;}}return rightBorder;}    int findLeftBorder(vector<int>& nums, int target){int leftBorder = -1;int left = 0;int right = nums.size()-1;while(left <= right){int mid = left + (right - left)/2;if(nums[mid] >= target){ //找左边界,当目标值小于等于midright = mid-1;leftBorder = right;}else{left =mid+1;}}return leftBorder;}
};

4 位运算

在上面的二分查找题目中计算mid时,需要注意溢出问题

可以用下面这种方法代替简单的(left+right)/2


int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2

或者利用位运算符

mid = left + ((right - left) >> 1)

右移运算符是将一个二进制数按指定移动的位数向右移动。

移动过程中,正数最高位补0,负数最高位补1,无符号数最高位补0。

二、移除元素

27 移除元素

由于数组元素在内存地址中是连续的,不能删除数组中的元素。要想实现移除功能,就要用其他元素覆盖原来的元素。

暴力解法:

两层for循环,第一层寻找目标值val,第二层在找到目标值之后,将后面的元素依次向前覆盖一位。

class Solution {
public:int removeElement(vector<int>& nums, int val) {int size = nums.size();for(int i = 0; i < size; i++){if(nums[i] == val ){//找到目标for(int j = i+1; j < size; j++){nums[j-1] = nums[j];//将后面的元素依次向前覆盖}i--;//向前覆盖之后,即i以后的元素都向前移动了一位,那么i也要向前移动一位size--;}} return size;}
};

 双指针法:

这里利用快慢指针:

  • fast在前面探路,寻找新数组的元素
  • slow在后面构造新数组
class Solution {
public:int removeElement(vector<int>& nums, int val) {int size = nums.size();int slow = 0;for(int fast = 0; fast < size; fast++){if(nums[fast] != val ) nums[slow] = nums[fast],slow++;}return slow;//最后slow构造新数组完成,slow就是新数组的长度}
};

代码随想录01 | 704二分查找和27移除元素相关推荐

  1. 代码随想录算法训练营第一天 704 二分查找、27 移除元素

    代码随想录算法Day1 | 704. 二分查找.27. 移除元素 Last edited time: April 5, 2023 11:27 AM 数据理论基础 数组是存放在连续内存空间上的相同类型数 ...

  2. 【Day1】数组、704二分查找、27移除元素

    [Day1]数组.704二分查找.27移除元素 数组 704 二分查找 版本一 左闭右闭 即[left, right] 版本二 左闭右开 即[left, right) 27 移除元素 暴力解法 双指针 ...

  3. 第一天| 704. 二分查找、27. 移除元素。

    第一天| 704. 二分查找.27. 移除元素. 704.二分查找 1. 题目描述 题目链接:力扣704题 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函 ...

  4. 打卡第一天 704. 二分查找、27. 移除元素

    打卡第一天| 704. 二分查找.27. 移除元素 704.二分查找 看到题目就想到曾经做过类似的,先取得左右边界,然后求中间值,如果要求的数在nums[middle]左边,就把右边界取middle- ...

  5. Suzy找到实习了吗 Day 1 | 704. 二分查找、27. 移除元素

    Suzy找到实习了吗 | 704. 二分查找.27. 移除元素 Leetcode 704:二分搜索 收获 Divide and conquer Recursive relation Python 3 ...

  6. 代码随想录算法训练营第一天 | 数组理论基础,704. 二分查找,27. 移除元素

    今日学习的文章链接如下: 代码随想录 (programmercarl.com) 代码随想录 (programmercarl.com) 704. 二分查找 自己看到题目的第一想法 拿到题目首先想办法,一 ...

  7. 代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。

    704. 二分查找 题目链接:704. 二分查找 - 力扣(LeetCode) 第一天代码跑题了,做出来了但是没有使用二分法,看了讲解,对于左闭右闭和左闭右开还需要多思考,并没有完全理解.那就先总结一 ...

  8. 【代码随想录算法练习】| DAY01 | JavaScript | 数组理论基础,704. 二分查找,27. 移除元素

    详细解析:请看Carl老师的讲解 数组基础理论 下标从 0 开始 内存空间地址是连续的 增删元素时,会涉及其他元素地址的变动 704. 二分查找 | 点击查看力扣对应题目 二分法,也叫折半查找法,这里 ...

  9. 代码随想录算法训练营第一天 | 704.二分查找、27.移除元素题目

    704.二分查找 题目链接:二分查找 思路: 1.从头开始遍历,首先如果不用二分查找法,最容易想到的就是直接暴力查找,时间复杂度为O(n)直接从头开始遍历一便就行.这样如果数据量庞大会运行时间较长. ...

最新文章

  1. nginx同域名代理tomcat不同目录下的文件
  2. 求多个四元数的平均数
  3. java报错误设置属性值_java – 设置属性值时出错;嵌套异常是org.springframework.beans.NotWritablePropertyException:...
  4. Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结
  5. 关于 Angular 项目类型为 library 的工程使用 tsconfig.json 的问题
  6. Android之手机摇一摇震动刷新(支持ListView、GridView、WebView)并生成我的二维码
  7. Apache2 部署flask项目
  8. Android 基础 —— 活动的生存周期
  9. 前端学习(1849)vue之电商管理系统电商系统前端项目初始化
  10. Diango博客--22.Django Haystack 全文检索与关键词高亮
  11. 论文浅尝 | 用可微的逻辑规则学习完成知识库推理
  12. hadoop基础----hadoop理论----Hadoop简介
  13. kettle-多文件合并
  14. SQL Server 百度网盘免费下载
  15. J-Link RTT Viewer 的各种不爽以及解决方案
  16. 2019 icpc南昌邀请赛 G Winner
  17. 使用vue+elementUI页面实现前端做分页
  18. 暗影精灵双系统(win10和Ubuntu16.04)安装+Cuda和tensorflow安装-深度学习环境配置
  19. 数据库基础知识及概念
  20. 随时随地访问家里搭建的私有存储(tfcenter)

热门文章

  1. git fetch总结
  2. Java在Web端微信公众号授权登录
  3. matlab对非平稳一维信号的小波变换
  4. js循环绑定事件问题及解决方法
  5. Windows Server 2012 R2 离线安装 .Net Framework3.5
  6. VMware虚拟机的使用
  7. 【Leetcode-每日一题】找出游戏的获胜者
  8. 计算机系统论文摘要,计算机系统结构论文摘要怎么写 计算机系统结构论文摘要范文参考...
  9. 对Scanner.hasNext的总结
  10. vue给元素添加指令_Vue指令动态模糊元素