【优选算法必刷100题】第019~20题(二分查找算法):x 的平方根、搜索插入位置

【优选算法必刷100题】第019~20题(二分查找算法):x 的平方根、搜索插入位置

🔥艾莉丝努力练剑:个人主页

专栏传送门:《C语言》《数据结构与算法》C/C++干货分享&学习过程记录Linux操作系统编程详解笔试/面试常见算法:从基础到进阶

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬艾莉丝的简介:


🎬艾莉丝的算法专栏简介:


目录

019  x 的平方根

1.1  思路一:暴力解法

1.1.1  算法思路

1.1.2  算法实现

1.2  思路二:二分查找

1.2.1  算法思路

1.2.2  算法实现

1.3  博主手记

020  搜索插入位置

2.1  算法思路——二分查找

2.2  算法实现

2.3  博主手记

结尾



019  x 的平方根

力扣链接:69. x 的平方根

力扣题解链接:二分查找算法模版解决【x 的平方根 】问题

题目描述:

1.1  思路一:暴力解法

1.1.1  算法思路

依次枚举 [0,x] 之间的所有数 (这里没有必要研究是否枚举到x / 2还是x / 2 + 1。因为我们找到结果之后直接就返回了,往后的情况就不会判断。反而研究枚举区间,既耽误时间,又可能出错):

(1)如果i * i == x,直接返回;
(2)如果i * i > x,说明之前的一个数是结果,返回i - 1。

由于i * i可能超过int的最大值,因此使用 long long类型。

1.1.2  算法实现

代码演示如下——

class Solution { public: int mySqrt(int x) { // 由于两个较⼤的数相乘可能会超过 int 最⼤范围 // 因此⽤ long long long long i = 0; for (i = 0; i <= x; i++) { // 如果两个数相乘正好等于 x,直接返回 i if (i * i == x) return i; // 如果第⼀次出现两个数相乘⼤于 x,说明结果是前⼀个数 if (i * i > x) return i - 1; } // 为了处理oj题需要控制所有路径都有返回值 return -1; } };
时间复杂度:O(n),空间复杂度:O(1)。

1.2  思路二:二分查找

1.2.1  算法思路

设x的平方根的最终结果为index——

1、分析index左右两次数据的特点:

(1)[ 0 , index ] 之间的元素,平方之后都是小于等于x的;
(2)[ index + 1 , x] 之间的元素,平方之后都是大于的。

因此可以使用二分查找算法

1.2.2  算法实现

代码演示如下——

class Solution { public: int mySqrt(int x) { if(x < 1) return 0; // 处理边界情况 int left = 1,right = x; while(left < right) { long long mid = left + (right - left + 1) / 2; // 数据量大,类型改成long long更加合适,防溢出 if(mid * mid <= x) left = mid; else right = mid - 1; } return left; } };
时间复杂度:O(logn),空间复杂度:O(1)。

1.3  博主手记

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下手记的推导过程!最好做题的过程中自己也推导一遍!!!自己能够推导很重要!


020  搜索插入位置

力扣链接:35. 搜索插入位置

力扣题解链接:二分查找模版解决【搜索插入位置】问题

题目描述:

2.1  算法思路——二分查找

1、分析插入位置左右两侧区间上元素的特点——
设插入位置的坐标为index,根据插入位置的特点可以知道:

(1)[left,index-1]内的所有元素均是小于target的;
(2)[index,right]内的所有元素均是大于等于target的。

2、设 left 为本轮查询的左边界,right为本轮查询的右边界。根据mid位置元素的信息,分析下一轮查询的区间:

(1)当nums[mid] >= target时,说明mid落在了[index , right]区间上,mid左边包括mid本身,可能是最终结果,所以我们接下来查找的区间在[left,mid]上。因此,更新right到mid位置,继续查找;

(2)当nums[mid] < target时,说明mid落在了([left , index - 1]区间上,mid右边但不包括mid本身,可能是最终结果,所以我们接下来查找的区间在[mid + 1 , right]上。因此,更新[left到mid+1的位置,继续查找。

3、到我们的查找区间的长度变为1,也就是left == right的时候,left 或者 right 所在的位置就是我们要找的结果。

2.2  算法实现

代码演示如下——

class Solution { public: int searchInsert(vector<int>& nums, int target) { int left = 0,right = nums.size() - 1; while(left < right) { int mid = left + (right - left) / 2; if(nums[mid] < target) left = mid + 1; else right = mid; } if(nums[left] < target) return left + 1; else return left; } };

left和right这里已经相遇了,返回left或者right都是可以的——

class Solution { public: int searchInsert(vector<int>& nums, int target) { int left = 0,right = nums.size() - 1; while(left < right) { int mid = left + (right - left) / 2; if(nums[mid] < target) left = mid + 1; else right = mid; } if(nums[right] < target) return right + 1; else return right; } };
时间复杂度:O(logn),空间复杂度:O(1)

2.3  博主手记

本题整个的思路、算法原理、解题过程博主在纸上推导了一遍,大家可以参考一下手记的推导过程!最好做题的过程中自己也推导一遍!!!自己能够推导很重要!


结尾

往期回顾:

【优选算法必刷100题】第018题(二分查找算法):在排序数组中查找元素的第一个和最后一个位置

结语:都看到这里啦!请大佬不要忘记给博主来个“一键四连”哦!

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡

૮₍ ˶ ˊ ᴥ ˋ˶₎ა


Read more

【数据结构与算法】单链表的综合运用:1.合并两个有序链表 2.分割链表 3.环形链表的约瑟夫问题

【数据结构与算法】单链表的综合运用:1.合并两个有序链表 2.分割链表 3.环形链表的约瑟夫问题

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人等方向学习者 ❄️个人专栏:《C语言》《【初阶】数据结构与算法》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、合并两个有序链表 * 1.1题目 * 1.2 算法原理 * 1.3代码 * 二、分割链表 * 2.1题目 * 2.2 算法原理 * 2.3代码 * 三、环形链表的约瑟夫问题 * 3.1题目 * 3.2 算法原理 * 3.3代码 * 总结与每日励志 前言 链表是C语言数据结构的核心内容,也是算法面试的高频考点,其灵活的指针操作与逻辑构建对编程思维要求颇高。本文聚焦链表经典实操题型,从合并有序链表、分割链表到环形链表约瑟夫问题,由浅入深拆解解题思路,

By Ne0inhk
算法王冠上的明珠——动态规划之路径问题(第一篇)

算法王冠上的明珠——动态规划之路径问题(第一篇)

目录 1. 什么叫路径类动态规划 一、核心定义(通俗理解) 二、核心特征(识别这类问题的关键) 2. 动态规划步骤 状态表示 状态转移方程 初始化 填表顺序 返回值 3. 例题讲解 3.1 LeetCode62. 不同路径 3.2 LeetCode63. 不同路径 II 3.3 LeetCodeLCR 166. 珠宝的最高价值 今天我们来聊一聊动态规划的路径类问题。 1. 什么叫路径类动态规划 路径类动态规划是 动态规划的一个重要分支,核心解决 “从起点到终点的路径相关问题”—— 比如 “路径总数”“最短路径长度”“路径上的最大 / 最小和” 等,其本质是通过 “状态递推” 避免重复计算,高效求解多阶段决策的路径问题。 一、

By Ne0inhk
【数据结构】常见时间复杂度以及空间复杂度

【数据结构】常见时间复杂度以及空间复杂度

时间复杂度与空间复杂度 * 一、复杂度的概念 * 二、时间复杂度 * 1、大O的渐进表示法 * 2、函数clock计算运算时间 * 3、常见复杂度对比 * 3.1常数项复杂度 * 3.2线性时间复杂度 * 案例1 * 案例2 * 3.3平方阶复杂度 * 3.4对数复杂度 * 3.5递归函数 * 单递归 * 双递归 * 三、空间复杂度 * 冒泡排序O(1) * 三个反置O(N) 一、复杂度的概念 * 一个算法的好坏,主要是对比两者的时间和空间两个维度,也就是时间和空间复杂度。 * 时间复杂度主要衡量一个算法运行的快慢,空间复杂度主要衡量一个算法运行需要的额外空间 二、时间复杂度 * 算法的时间复杂度是一个函数式T(N),算法中的基本操作的执行次数,为算法的时间复杂度。 * 注:编译器的不同,编译所需要的时间也不同。越新的编译器,编译的时间往往比旧的编译器快 * 当一个算法函数式为T(

By Ne0inhk
数据结构-单链表

数据结构-单链表

单链表 * 概念与结构 * 结点 * 链表的性质 * 链表的打印 * 实现单链表 * 头文件 * 源文件 * 单链表的打印 * 单链表申请新节点内存 * 尾插 * 头插 * 尾删 * 头删 * 查找 * 在指定位置之前插入数据 * 在指定位置之后插入数据 * 删除pos结点 * 删除pos之后的结点 * 销毁链表 * 链表的分类 * 代码地址 概念与结构 概念:链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 逻辑结构:线性 物理结构(存储结构):不一定是线性的 链表就类似一个火车,车头是哨兵位(可有可无),车厢是节点 * 将火车里的某节车厢去掉或加上,不会影响其他车厢,每节车厢都是独立存在的。 在链表⾥,每节“车厢”是什么样的呢? \color{red}{在链表⾥,每节“车厢”是什么样的呢?

By Ne0inhk