【优选算法】(第十篇)

目录

搜索插⼊位置(easy)

题目解析

讲解算法原理

编写代码

x的平⽅根(easy)

题目解析

讲解算法原理

编写代码


搜索插⼊位置(easy)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给定⼀个排序数组和⼀个⽬标值,在数组中找到⽬标值,并返回其索引。如果⽬标值不存在于数组中,返回它将会被按顺序插⼊的位置。
请必须使⽤时间复杂度为 O(log n) 的算法。⽰例1:
输⼊: nums = [1,3,5,6], target = 5 输出: 2
⽰例2:
输⼊: nums = [1,3,5,6], target = 2 输出: 1
⽰例3:
输⼊: nums = [1,3,5,6], target = 7 输出: 4

讲解算法原理

解法(⼆分查找算法):
算法思路:

a. 分析插⼊位置左右两侧区间上元素的特点:
设插⼊位置的坐标为 index ,根据插⼊位置的特点可以知道:
• [left, index - 1] 内的所有元素均是⼩于 target 的;
• [index, right] 内的所有元素均是⼤于等于 target 的。
b. 设 left 为本轮查询的左边界, right 为本轮查询的右边界。根据 mid 位置元素的信
息,分析下⼀轮查询的区间:
▪ 当 nums[mid] >= target 时,说明 mid 落在了 [index, right] 区间上,
mid 左边包括 mid 本⾝,可能是最终结果,所以我们接下来查找的区间在 [left, 
mid] 上。因此,更新 right 到 mid 位置,继续查找。
▪ 当 nums[mid] < target 时,说明 mid 落在了 [left, index - 1] 区间上,
mid 右边但不包括 mid 本⾝,可能是最终结果,所以我们接下来查找的区间在 [mid 
+ 1, right] 上。因此,更新 left 到 mid + 1 的位置,继续查找。
c. 直到我们的查找区间的⻓度变为 1 ,也就是 left == right 的时候, left 或者
right 所在的位置就是我们要找的结果。

编写代码

c++算法代码:

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 right + 1;
 return right;
 }
};

Java算法代码:

class Solution
{
 public int searchInsert(int[] nums, int target) 
 {
 int left = 0, right = nums.length - 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;
 return right;
 }
}

 

x的平⽅根(easy)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给你⼀个⾮负整数 x ,计算并返回 x 的算术平⽅根。
由于返回类型是整数,结果只保留整数部分,⼩数部分将被舍去。
注意:不允许使⽤任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。⽰例1:
输⼊: x = 4
输出: 2
⽰例2:
输⼊: x = 8
输出: 2
解释:
8 的算术平⽅根是 2.82842... ,由于返回类型是整数,⼩数部分将被舍去。

讲解算法原理

解法⼀(暴⼒查找):
算法思路:
依次枚举 [0, x] 之间的所有数 i :
(这⾥没有必要研究是否枚举到 x / 2 还是 x / 2 + 1 。因为我们找到结果之后直接就返回了,往后的情况就不会再判断。反⽽研究枚举区间,既耽误时间,⼜可能出错)
▪ 如果 i * i == x ,直接返回 x ;
▪ 如果 i * i > x ,说明之前的⼀个数是结果,返回 i - 1 。由于 i * i 可能超过 int 的最⼤值,因此使⽤ long long 类型。

算法代码:
 

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;
 }
};

解法⼆(⼆分查找算法):
算法思路:
设 x 的平⽅根的最终结果为 index :
a. 分析 index 左右两次数据的特点:
▪ [0, index] 之间的元素,平⽅之后都是⼩于等于 x 的;
▪ [index + 1, x] 之间的元素,平⽅之后都是⼤于 x 的。
因此可以使⽤⼆分查找算法。 

编写代码

c++算法代码:

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; // 防溢出 if(mid * mid <= x) left = mid;
 else right = mid - 1;
 }
 return left;
 }
};

java算法代码:

class Solution
{
 public int mySqrt(int x) 
 {
 // 细节
 if(x < 1) return 0;
 long left = 1, right = x;
 while(left < right)
 {
 long mid = left + (right - left + 1) / 2;
 if(mid * mid <= x) left = mid;
 else right = mid - 1;
 }
 return (int)left;
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值