69. x 的平方根
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入: x = 4
输出: 2
示例 2:
输入: x = 8
输出: 2
解释: 8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
解题思路:这题的解题思路是固定循环一百遍,因为二分算法每次都是将范围减少一半,所以一百遍会使head和tail足够接近,代码如下:
var mySqrt = function(x) {
//边界条件处理,小于1就返回0
if(x < 1) return 0;
//二分其实位置head和末尾位置tail
let head = 0,tail = x,m;
//使查找的范围大于当前查找的值
tail += 1;
for(let i = 0; i < 100; i ++){
//每次范围缩小一半,使head和tail接近
m = (head + tail) / 2.0;
if(m * m <= x) head = m;
else tail = m;
}
return parseInt(head);
};
35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 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
解题思路:这题的要求是找到大于等于目标值的第一个参数,就是类似于0000011111模型找到第一个1,小于目标值的都是0 大于等于目标值的都是1,二分算法代码如下:
var searchInsert = function(nums, target) {
let head = 0,tail = nums.length - 1,m;
//最后三个数使用for循环更好,因为边界条件不好判断
while(tail - head > 3){
//计算中间值
m = (head + tail) >> 1;
//数组范围缩小一半.当中间值小于目标值说明目标值在后部分,当中间值大于目标值,说明在前半分
if(nums[m] < target) head = m - 1;
else tail = m;
}
for(let i = head; i <= tail; i ++){
//从前往后对比,当大于等于目标值的时候,你就是目标值的位置
if(nums[i] >= target) return i;
}
//至此说明没有找到目标值,所以目标值是最后一个
return nums.length;
};
1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入: nums = [3,2,4], target = 6
输出: [1,2]
示例 3:
输入: nums = [3,3], target = 6
输出: [0,1]
解题思路:这题的解题思路就是重组数组,然后从小到大排序,然后开始遍历重组的数组,在剩下的数字里找到目标值减当前值,找到的话就返回两个索引,代码如下:
var twoSum = function(nums, target) {
//重组数组
let data = [];
for(let i = 0; i < nums.length; i ++){
data.push({idx:i,val:nums[i]})
}
//从小到大排序
data.sort((a,b) => {
return a.val - b.val;
})
//开始遍历数组查找符合的数组
for(let i = 0; i < data.length; i ++){
// 查找剩下的数组里是否存在target - data[i].val
let j = two_sun(i + 1,data,target - data[i].val);
//j == -1 说明不存在,进行下一轮比较
if(j == -1) continue;
至此说明找到对应值
//return [data[i].idx,j]
}
return;
};
let two_sun = function(idx,data,target){
let henad = idx, tail = data.length - 1,m;
while(tail - henad > 3){
m = (henad + tail) >> 1;
if(data[m].val >= target) tail = m;
else henad = m + 1;
}
for(let i = henad; i <= tail; i ++){
//因为要返回的是索引,所以这里返回的是索引
if(data[i].val == target) return data[i].idx;
}
return -1;
}
34. 在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
示例 3:
输入: nums = [], target = 0
输出: [-1,-1]
解题思路:这题的解题思路也是模型00001111,其实位置值就是第一个1的位置,结尾位置就是目标值加一的1的位置,然后判断结尾的前一位是否等于目标值,如果是就是结尾位置,如果不是就是-1,代码如下:
var searchRange = function(nums, target) {
//边界处理
if(nums.length < 1 || (nums.length == 1 && nums[0] != target)) return [-1,-1];
if(nums.length == 1) return [i,0]
//查起始位置
let i = search_range(0,nums,target);
//判断第一个1是不是等于目标值,如果不是就说明不存在
if(nums[i] != target ) return [-1,-1];
let j = search_range(i,nums,target + 1);
return [i,j - 1]
};
//以下是二分算法代码
let search_range = function(idx,data,target){
let head = idx,tail = data.length,m;
while(tail - head > 3){
m = (head + tail) >> 1;
if(data[m] < target) head = m + 1;
else tail = m;
}
for(let i = head; i <= tail; i ++){
if(data[i] >= target) return i;
}
return data.length;
}