目录
搜索插⼊位置(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;
}
}