Open azl397985856 opened 3 years ago
题目要求使用 O(log n) ,自然是二分搜索 \ 关键在于边界的定义
class Solution {
public int searchInsert(int[] nums, int target) {
//[left, right)
int left = 0;
int right = nums.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}
时间: O(log n) \ 空间: O(1)
排序数组 二分查找
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
let l = 0;
let r = nums.length - 1;
while (l <= r) {
// let mid = l + Math.floor((r - l) / 2);
let mid = l + ((r - l) >> 1);
if (nums[mid] === target) {
return mid;
} else if (nums[mid] < target) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return l;
};
直接扫描一遍原数组,遇到大于等于target的数字,那么返回当前下标
语言:JavaScript
var searchInsert = function(nums, target) {
for (let i = 0; i < nums.length; i++) {
if (nums[i] >= target) return i;
}
return nums.length;
};
class Solution {
public int searchInsert(int[] nums, int target) {
int lo = 0, hi = nums.length;
while (lo < hi){
int mid = lo + (hi - lo)/2;
if (nums[mid] < target){
lo = mid + 1;
}else {
hi = mid ;
}
}
return lo;
}
}
通过收缩的条件理解二分的判断条件,而且因为 < 和 hi = mid 右边界必然收缩,写到length而不是length - 1增加输出的范围,不影响二分的主体逻辑,不需要额外判断,也不会抛出异常
二分法
public int searchInsert(int[] nums, int target) {
int n = nums.length;
int left = 0, right = n - 1, ans = n;
while (left <= right) {
int mid = ((right - left) >> 1) + left;
if (target <= nums[mid]) {
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
}
35. 搜索插入位置
https://leetcode-cn.com/problems/search-insert-position/
二分查找法
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
middle = (left + right) // 2
if nums[middle] < target:
left = middle + 1
elif nums[middle] > target:
right = middle - 1
else:
return middle
return right + 1
public int searchInsert(int[] nums, int target) { int l = 0; int r = nums.length; while (l < r) { int m = l + (r - l) / 2; if (nums[m] == target) { return m; } else if (nums[m] > target) { r = m; } else { l = m + 1; } } return l; }
二分,查找不小于目标值的位置
class Solution {
public int searchInsert(int[] nums, int target) {
int i = 0, j = nums.length - 1;
while(i <= j){
if(nums[(i + j)/2] > target){
j = (i + j)/2 -1;
}ifelse(nums[(i + j)/2] < target){
i = (i + j)/2 + 1;
}ifelse {
return (i + j)/2;
}
}
return i;
}
}
时:O(logN)
空:O(1)
https://leetcode-cn.com/problems/search-insert-position/
二分答案,二分区间
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
# 二分答案
# time logn
# space 1
left, right = 0, len(nums) - 1
while (left <= right):
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
return left
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
# time logn
# space 1
# 二分区间
if len(nums) == 0:
return 0
left, right = 0, len(nums) - 1
while left + 1 < right:
mid = left + (right - left) // 2
if target == nums[mid]:
return mid
elif target > nums[mid]:
left = mid
elif target < nums[mid]:
right = mid
if nums[left] >= target:
return left
if nums[right] >= target:
return right
return right + 1
1.https://leetcode-cn.com/problems/first-bad-version/ 2.https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/ 3.https://leetcode-cn.com/problems/search-insert-position/ 4.https://leetcode-cn.com/problems/guess-number-higher-or-lower/ 5.待补充
二分
class Solution {
public int searchInsert(int[] nums, int target) {
int l=0,r=nums.length-1;
int mid;
while(l<=r){
mid=l+(r-l)/2;
if(nums[mid]==target)return mid;
else if(nums[mid]>target){
r=mid-1;
}else l=mid+1;
}
return r+1;
}
}
时间复杂度:O(logn) 空间复杂度:O(1)
https://leetcode-cn.com/problems/search-insert-position/
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 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
示例 4:
输入: nums = [1,3,5,6], target = 0
输出: 0
示例 5:
输入: nums = [1], target = 0
输出: 0
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 为无重复元素的升序排列数组
-104 <= target <= 104
要求logn解决,用二分查找
JavaScript Code:
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
// 二分查找
let left = 0 ;
let right = nums.length -1 ;
let middle = Math.floor((left+right)/2);
if ( target > nums[right]){
return right+1
}
if( target <= nums[ left ]){
return left
}
while ( left !== right && left!==middle && right !== middle){
if ( target > nums[right]){
return right+1
}
if( target < nums[ left ]){
return left
}
if( nums[middle] > target ){
right = middle
}else if ( nums[middle] < target){
left = middle
}else {
return middle
}
middle = Math.floor((left+right)/2);
}
return left + 1
};
复杂度分析
令 n 为数组长度。
Language: Java
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right-left)//2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid -1
else:
left = mid + 1
return left
思路
最左二分
代码
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){
right = mid - 1;
}else {
left = mid + 1;
}
}
return left;
}
}
复杂度
时间复杂度:O(logN)
空间复杂度:O(1)
class Solution {
public int searchInsert(int[] nums, int target) {
int l = 0;
int r = nums.length;
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
return l;
}
}
Time: O(logN)\ Space: O(n)
一次遍历。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
for (int i = 0; i < nums.size(); i++) if (nums[i] >= target) return i;
return nums.size();
}
};
二分查找。如果找到target
,则返回mid
。没找到,最后比较nums[mid]
和target
的大小,如果target
大,则返回mid + 1
,否则返回mid
。
class Solution {
public int searchInsert(int[] nums, int target) {
int lo = 0, hi = nums.length - 1;
int mid = 0;
while (lo <= hi) {
mid = lo + (hi - lo) / 2;
if (nums[mid] == target) return mid;
if (nums[mid] < target) {
lo = mid + 1;
}
else {
hi = mid - 1;
}
}
return nums[mid] < target ? mid + 1 : mid;
}
}
复杂度分析
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target){
right = mid;
} else {
left = mid + 1;
}
}
return right;
}
}
Go Code:
func searchInsert(nums []int, target int) int {
left, right := 0, len(nums) - 1
for left <= right {
mid := (right - left) / 2 + left
if nums[mid] < target {
left = mid + 1
} else if nums[mid] > target {
right = mid - 1
} else {
return mid
}
}
return left
}
复杂度分析
令 n 为数组长度。
class Solution
{
public:
int searchInsert(vector<int> &nums, int target)
{
int left{ 0 };
int right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (target == nums[mid]) {
return mid;
} else if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid - 1;
}
}
return left;
}
};
class Solution(object):
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
left = 0
right = len(nums) - 1
while left<=right:
mid = left + (right-left)//2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid - 1
else:
left = mid + 1
return left
时间复杂度:O(log(N)) 空间复杂度:O(1)
二分查找,查找左侧边界+
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(target<nums[mid])
right=mid-1;
else if(target>nums[mid])
left=mid+1;
else if(target==nums[mid])
right=mid-1;
}
return left;
}
};
复杂度分析
class Solution(object):
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
left, right = 0, len(nums)
while left < right:
mid = (left+right) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid
else:
left = mid + 1
return left
思路:二分查找
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right){
//中间值 mid = (left + right) // 2,循环条件 left <= right
int mid = left + (right - left) / 2;
//当 nums[mid] = target 时,找到目标,返回mid
if(nums[mid] == target){
return mid;
}
//当 nums[mid] > target 时,说明当前值偏大,右指针左移至 mid - 1
else if(nums[mid] < target){
left = mid + 1;
}
//当 nums[mid] < target 时,说明当前值偏小,左指针右移至 mid + 1
else{
right = mid - 1;
}
}
//跳出循环时,left 指向 target 插入位置,返回 left
//返回left正确性说明:
//当原数组不包含target时,考虑while循环最后一次执行的总是 left=right=mid,
//此时nums[mid] 左边的数全部小于target,nums[mid]右边的数全部大于target,
//则此时我们要返回的插入位置分为两种情况:
//①就是这个位置,即nums[mid]>target时,此时执行了right=mid-1,返回left正确
//②是该位置的右边一个,即nums[mid]<target时,此时执行了left=mid+1,返回left也正确
return left;
}
}
时间复杂度:O(logN) 空间复杂度:O(1)
python
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
n = len(nums)
left = 0
right = n - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid - 1
else:
left = mid + 1
return left
func searchInsert(nums []int, target int) int {
left, mid := 0, 0
right := len(nums) - 1
for left <= right {
mid = (left + right) >> 1
if nums[mid] == target {
return mid
} else if nums[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
return left
}
二分
class Solution(object):
def searchInsert(self, nums, target):
r = len(nums) - 1
l = 0
while l <= r:
m = l + (r - l) / 2
if target == nums[m]:
return m
if target > nums[m]:
l = m + 1
if target < nums[m]:
r = m - 1
return l
T: logn S: 1
搜索左侧插入位置(第一个大于等于 target
的位置)的二分模板,套模板即可
var searchInsert = function(nums, target) {
let l = 0;
let r = nums.length - 1;
let mid;
while(l <= r) {
// 防溢出补丁
mid = ~~((r - l) / 2 + l); // ~~ 快速下取整
if (nums[mid] >= target) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return l;
};
时间复杂度: O(logn)
额外空间复杂度: O(1)
二分
, 双指针
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
l =0
r = len(nums) -1
while l <= r:
mid = (l+r)//2
if nums[mid] == target:
return mid
elif nums[mid] < target:
l = mid+1
else:
r = mid-1
return l
时间O(logn) 空间O(1)
思路:典型的二分法
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right)//2 #Python可以不用考虑溢出!
if target <= nums[mid]: right = mid - 1 #在左边找
else: left = mid + 1 #在右边找
return left
时间复杂度:O(logn) 空间复杂度:O(1)
思路
用二分法搜索target 遇到第一个>=target的数返回index
代码
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
l , r = 0, len(nums)-1
while l <= r:
mid=(l+r)//2
if nums[mid] < target:
l = mid+1
else:
if nums[mid]== target and nums[mid-1]!=target:
return mid
else:
r = mid-1
return l
复杂度分析
时间复杂度: O(logN) (二分法每次只查找半个list)
空间复杂度: O(1) (只用了指针)
二分查找(三段式模版)
class Solution {
public int searchInsert(int[] nums, int t) {
int L = 0, R = nums.length - 1;
while (L <= R) {
int M = L + (R - L) / 2;
if (nums[M] > t) R = M - 1;
else if (nums[M] < t) L = M + 1;
else return M;
}
return L;
}
}
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0 , right = nums.size() - 1;
while(left + 1 < right) {
int mid = left + (right - left) / 2;
if(nums[mid] == target) {
return mid;
}
if(nums[mid] > target) {
right = mid;
} else {
left = mid;
}
}
if(nums[right] < target)
return right + 1;
if(nums[left] >= target)
return left;
return left + 1;
}
};
二分法,找到中间那个点
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
if not nums:
return 0
left, right = 0, len(nums) - 1
while left + 1 < right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid
else:
left = mid
if target > nums[right]:
return right + 1
if target == nums[right]:
return right
if target == nums[left]:
return left
if target > nums[left]:
return left + 1
if target < nums[left]:
if left == 0:
return 0
else:
return left - 1
return 0
/*
经典二分
*/
var searchInsert = function(nums, target) {
let left = 0;
let right = nums.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (nums[mid] === target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
};
二分。这里使用 start <= end 这个模板比较简单,不需要最后在做一次判断。
class Solution {
public int searchInsert(int[] nums, int target) {
int start = 0;
int end = nums.length - 1;
while (start <= end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
start = mid + 1;
} else {
end = mid - 1;
}
}
return start;
}
}
时间:O(logn)
空间:O(1)
二分查找
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums)
while left < right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
if nums[mid] < target:
left = mid + 1
if nums[mid] > target:
right = mid
return left
时间:O(logn) 空间:O(1)
二分法,注意边界
class Solution {
public int searchInsert(int[] nums, int target) {
int begin = 0;
int end = nums.length-1;
while(end - begin > 1){
int midIndex = (begin + end) / 2;
if(nums[midIndex] == target){
return midIndex;
}
if(nums[midIndex] < target){
begin = midIndex;
}else{
end = midIndex;
}
}
if(target == nums[begin]){
return begin;
}
if(target == nums[end]){
return end;
}
if(target < nums[begin]){
int index = --begin;
return index > 0 ? index : 0;
}
if(target > nums[end]){
return ++end;
}
return ++begin;
}
}
使用二分法
var searchInsert = function(nums, target) {
let left = 0, right = nums.length - 1
while (left <= right) {
const mid = left + ((right - left) >>> 1)
// 如果中间值小于target,缩小左侧区间,否则缩小右侧
nums[mid] < target && (left = mid + 1 ) || (right = mid - 1)
}
return right + 1
};
时间复杂度: O(logN)
空间复杂度: O(1)
思路: 西法的二分查找
func searchInsert(nums []int, target int) int {
left := 0
right := len(nums)-1
for left <= right{
mid := left + (right - left)/2
if nums[mid] == target{
return mid
}else if nums[mid] < target{
left = mid+1
}else{
right = mid-1
}
}
return left
}
时间复杂度O(logN) 空间复杂度O(1)
二分法, 寻找>= target 的第一个位子
class Solution {
public int searchInsert(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int left = 0, right = nums.length - 1;
while (left + 1 < right) {
int mid = left + (right - left) / 2;
if (nums[mid] >= target) {
right = mid;
} else {
left = mid;
}
}
if (nums[left] >= target) {
return left;
}
if (nums[right] >= target) {
return right;
}
return right + 1;
}
}
二分法
var searchInsert = function(nums, target) {
let left = 0
let right = nums.length - 1
while(left <= right) {
let mid = parseInt((left + right) / 2)
let midVal = nums[mid]
if (midVal === target) {
return mid
} else if (midVal < target) {
left = mid + 1
} else {
right = mid - 1
}
}
return left
};
时间复杂度 O(logn) 空间复杂度 O(1)
Binary Search
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
left = right = 0
while(right < len(nums)):
if nums[right] != nums[left]:
left+=1
nums[left] = nums[right]
right+=1
return left+1
Space: O(1) Time: O(logN)
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
l, r = 0, len(nums) - 1
while l <= r:
mid = (l+r) // 2
if nums[mid] > target:
r = mid - 1
elif nums[mid] < target:
l = mid + 1
else:
return mid
return l
Binary search.
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if target > nums[mid]:
left = mid + 1
elif target == nums[mid]:
return mid
else:
right = mid - 1
return left
Time complexity: O(logn) Space complexity: O(1)
二分
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
int ii = 0, jj = n - 1;
if(target < nums[ii]) return ii;
if(target > nums[jj]) return n;
int mid;
while(ii < jj){
mid = ii + jj >> 1;
if(nums[mid] < target){
ii = mid + 1;
}else{
jj = mid;
}
}
return ii;
}
};
n为数组长度。
【Day 27】35. 搜索插入位置
思路:二分查找
代码:
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums)
while left < right:
mid = (left+right)//2 #Floor除法,3//2=1
#mid= ((right - left) >> 1) + left #位运算 防止溢出 右移一位,等于//2
if nums[mid] == target:
return mid
if nums[mid] < target:
left = mid +1
if nums[mid] > target:
right = mid
return left
复杂度分析:
思路:使用二分法,值得注意的是,要注意它是左满足、还是右满足的情况。(左满足:找一个小于目标值得,右满足:找一个大于目标值。值得注意的是,1左右指针赋mid后是否加1或者减一,2计算mid的时候是否要也+1,
第一点是很好解决的,值要根据题意找mid是否需要被排除,例如本题中,当小于目标值得时候,l=mid +1;而大于目标值得时候,它还是有可能是第一个大于目标值的值,所有r=mid;
第二个点可能造成死循环的问题,
)
该题题意是找第一个小于目标值得下标所以为右满足。
class Solution { public int searchInsert(int[] nums, int target) { //暴力法的话就是从头开始遍历,但是时间复杂度为n //使用二分法,则可以满足时间复杂度为log n //注意二分法,它是左满足 还是右满足的情况!!! if(nums == null||nums.length==0)return 0; if(target>nums[nums.length-1])return nums.length; int l = 0,r =nums.length -1; int mid = 0; while(l<r){ mid = (r-l)/2 + l; if(nums[mid]==target){ return mid; }else if(nums[mid]>target){ r=mid; }else if(nums[mid]<target){ l=mid+1; } } return l; } }
采用二分查找,返回的下标如果小于目标值,则下标+1;
class Solution {
public int searchInsert(int[] nums, int target) {
int l = 0, r = nums.length-1;
while(l < r){
int mid = l+r>>1;
if(nums[mid] >= target) r = mid;
else l = l+1;
}
System.out.println(l);
if(nums[l] < target) return l+1;
return l;
}
}
时间复杂度:O(logn)
空间复杂度:O(1)
双指针
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
while left <= right:
middle = (left + right) // 2
if nums[middle] == target:
return middle
if target < nums[middle]:
right = middle - 1
else:
left = middle + 1
return left
T: O(logN) S: O(1)
35. 搜索插入位置
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/search-insert-position
前置知识
暂无
题目描述
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。