代码随想录01 | 704二分查找和27移除元素
目录
一 、二分查找
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/
题中也是给了排序数组和目标值,可以使用二分查找:本题的关键是如何处理当目标值不存在数组中,返回将按顺序插入的位置
本题可以细分为四种情况:
- 目标值将会插在数组最前面 [0,-1]
- 目标值将会插在数组之后 [left,right]
- 目标值将会插在数组之中 [left,right]
- 目标值在数组之中 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/ 本题一看就知道用二分法,但实际操作起来反而没那么好想:
查找开始位置和结束位置,可以转换成两个二分法分别查找左右边界
三种情况:
- 目标值不在数组中,应该插入至第一个或最后一个
- 目标值不在数组中,应该插至数组中
- 目标值在数组中,返回首尾索引
计算出来的左右边界,实质上是(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移除元素相关推荐
- 代码随想录算法训练营第一天 704 二分查找、27 移除元素
代码随想录算法Day1 | 704. 二分查找.27. 移除元素 Last edited time: April 5, 2023 11:27 AM 数据理论基础 数组是存放在连续内存空间上的相同类型数 ...
- 【Day1】数组、704二分查找、27移除元素
[Day1]数组.704二分查找.27移除元素 数组 704 二分查找 版本一 左闭右闭 即[left, right] 版本二 左闭右开 即[left, right) 27 移除元素 暴力解法 双指针 ...
- 第一天| 704. 二分查找、27. 移除元素。
第一天| 704. 二分查找.27. 移除元素. 704.二分查找 1. 题目描述 题目链接:力扣704题 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函 ...
- 打卡第一天 704. 二分查找、27. 移除元素
打卡第一天| 704. 二分查找.27. 移除元素 704.二分查找 看到题目就想到曾经做过类似的,先取得左右边界,然后求中间值,如果要求的数在nums[middle]左边,就把右边界取middle- ...
- Suzy找到实习了吗 Day 1 | 704. 二分查找、27. 移除元素
Suzy找到实习了吗 | 704. 二分查找.27. 移除元素 Leetcode 704:二分搜索 收获 Divide and conquer Recursive relation Python 3 ...
- 代码随想录算法训练营第一天 | 数组理论基础,704. 二分查找,27. 移除元素
今日学习的文章链接如下: 代码随想录 (programmercarl.com) 代码随想录 (programmercarl.com) 704. 二分查找 自己看到题目的第一想法 拿到题目首先想办法,一 ...
- 代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。
704. 二分查找 题目链接:704. 二分查找 - 力扣(LeetCode) 第一天代码跑题了,做出来了但是没有使用二分法,看了讲解,对于左闭右闭和左闭右开还需要多思考,并没有完全理解.那就先总结一 ...
- 【代码随想录算法练习】| DAY01 | JavaScript | 数组理论基础,704. 二分查找,27. 移除元素
详细解析:请看Carl老师的讲解 数组基础理论 下标从 0 开始 内存空间地址是连续的 增删元素时,会涉及其他元素地址的变动 704. 二分查找 | 点击查看力扣对应题目 二分法,也叫折半查找法,这里 ...
- 代码随想录算法训练营第一天 | 704.二分查找、27.移除元素题目
704.二分查找 题目链接:二分查找 思路: 1.从头开始遍历,首先如果不用二分查找法,最容易想到的就是直接暴力查找,时间复杂度为O(n)直接从头开始遍历一便就行.这样如果数据量庞大会运行时间较长. ...
最新文章
- nginx同域名代理tomcat不同目录下的文件
- 求多个四元数的平均数
- java报错误设置属性值_java – 设置属性值时出错;嵌套异常是org.springframework.beans.NotWritablePropertyException:...
- Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结
- 关于 Angular 项目类型为 library 的工程使用 tsconfig.json 的问题
- Android之手机摇一摇震动刷新(支持ListView、GridView、WebView)并生成我的二维码
- Apache2 部署flask项目
- Android 基础 —— 活动的生存周期
- 前端学习(1849)vue之电商管理系统电商系统前端项目初始化
- Diango博客--22.Django Haystack 全文检索与关键词高亮
- 论文浅尝 | 用可微的逻辑规则学习完成知识库推理
- hadoop基础----hadoop理论----Hadoop简介
- kettle-多文件合并
- SQL Server 百度网盘免费下载
- J-Link RTT Viewer 的各种不爽以及解决方案
- 2019 icpc南昌邀请赛 G Winner
- 使用vue+elementUI页面实现前端做分页
- 暗影精灵双系统(win10和Ubuntu16.04)安装+Cuda和tensorflow安装-深度学习环境配置
- 数据库基础知识及概念
- 随时随地访问家里搭建的私有存储(tfcenter)