leetcode第34题

简介: 第二种思路,参考这里。我们开始更新 start 的时候,是 mid + 1,如果剩两个元素,例如 2 4,target = 6 的话,此时 mid = 0,start = mid + 1 = 1,我们返回 start + 1 = 2。如果 mid 是右端点,那么 mid = 1,start = mid + 1 = 2,这样就可以直接返回 start 了,不需要在返回的时候加 1 了。

image.png

给定一个有序数组,依旧是二分查找,不同之处是如果没有找到指定数字,需要返回这个数字应该插入的位置。

这道题比较简单,在二分查找的基础上,只要想清楚返回啥就够了。想的话,就考虑最简单的情况如果数组只剩下 2 5,target 是 1, 3, 6 的时候,此时我们应该返回什么就行。

publicintsearchInsert(int[] nums, inttarget) {
intstart=0;
intend=nums.length-1;
if (nums.length==0) {
return0;
    }
while (start<end) {
intmid= (start+end) /2;
if (target==nums[mid]) {
returnmid;
        } elseif (target<nums[mid]) {
end=mid;
        } else {
start=mid+1;
        }
    }
//目标值在不在当前停的位置的前边还是后边if(target>nums[start]){
returnstart+1;
    }
//如果小于的话,就返回当前位置,跑步超过第二名还是第二名,所以不用减 1。else{
returnstart;
    }
}

时间复杂度:O(log(n))。

空间复杂度:O(1)。

这道题不难,但是对于二分查找又有了一些新认识。

首先,一定要注意,数组剩下偶数个元素的时候,中点取的是左端点。例如 1 2 3 4,中点取的是 2。正因为如此,我们更新 start 的时候不是直接取 mid ,而是 mid + 1。因为剩下两个元素的时候,mid 和 start 是相同的,如果不进行加 1 会陷入死循环。

然后上边的算法,返回最终值的时候,我们进行了一个 if 的判断,那么能不能避免呢。

  • 第一种思路,参考这里
    首先为了让 start 在循环的时候多加 1,我们将循环的 start < end 改为 start <= end。
    这样就会出现一个问题,当 start == end,此时 mid 不仅等于了 start 还会等于 end,所以之前更新 end 是直接赋 mid,现在需要改成 end = mid - 1,防止死循环。这样就达到了目标。
publicintsearchInsert(int[] nums, inttarget) {
intstart=0;
intend=nums.length-1;
if (nums.length==0) {
return0;
    }
while (start<=end) {
intmid= (start+end) /2;
if (target==nums[mid]) {
returnmid;
        } elseif (target<nums[mid]) {
end=mid-1;
        } else {
start=mid+1;
        }
    }
returnstart;
}

第二种思路,参考这里

我们开始更新 start 的时候,是 mid + 1,如果剩两个元素,例如 2 4,target = 6 的话,此时 mid = 0,start = mid + 1 = 1,我们返回 start + 1 = 2。如果 mid 是右端点,那么 mid = 1,start = mid + 1 = 2,这样就可以直接返回 start 了,不需要在返回的时候加 1 了。

怎么做到呢?最最开始的时候我们取 end 的时候是 end = nums.length - 1。如果我们改成 end = nums.length,这样每次取元素的时候,如果和之前对比,取到的就是右端点了。这样的话,最后返回的时候就不需要多加 1 了。

publicintsearchInsert(int[] nums, inttarget) {
intstart=0;
intend=nums.length;
if (nums.length==0) {
return0;
    }
while (start<end) {
intmid= (start+end) /2;
if (target==nums[mid]) {
returnmid;
        } elseif (target<nums[mid]) {
end=mid;
        } else {
start=mid+1;
        }
    }
returnstart;
}

虽然题很简单,但对二分查找有了更多的理解。



相关文章
|
8月前
|
C++ Python
leetcode-283:移动零
leetcode-283:移动零
30 0
|
8月前
leetcode-827:最大人工岛
leetcode-827:最大人工岛
70 0
|
8月前
|
消息中间件 Kubernetes NoSQL
LeetCode 1359、1360
LeetCode 1359、1360
LeetCode 389. 找不同
给定两个字符串 s 和 t,它们只包含小写字母。
81 0
LeetCode 354. Russian Doll Envelopes
给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。 请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
85 0
LeetCode 354. Russian Doll Envelopes
|
存储
leetcode第56题
常规的思想,将大问题化解成小问题去解决。 假设给了一个大小为 n 的列表,然后我们假设 n - 1 个元素的列表已经完成了全部合并,我们现在要解决的就是剩下的 1 个,怎么加到已经合并完的 n -1 个元素中。 这样的话分下边几种情况, 我们把每个范围叫做一个节点,节点包括左端点和右端点。 1. 如下图,新加入的节点左端点和右端点,分别在两个节点之间。这样,我们只要删除
111 0
leetcode第56题
|
算法
leetcode第45题
时间复杂度:O(n)。 空间复杂度:O(1)。 这里要注意一个细节,就是 for 循环中,i < nums.length - 1,少了末尾。因为开始的时候边界是第 0 个位置,steps 已经加 1 了。如下图,如果最后一步刚好跳到了末尾,此时 steps 其实不用加 1 了。如果是 i < nums.length,i 遍历到最后的时候,会进入 if 语句中,steps 会多加 1 。
116 0
leetcode第45题
leetcode第39题
对回溯法又有了更深的了解,一般的架构就是一个大的 for 循环,然后先 add,接着利用递归进行向前遍历,然后再 remove ,继续循环。而解法二的动态规划就是一定要找到递进的规则,开始的时候就想偏了,导致迟迟想不出来。
100 0
leetcode第39题
|
算法
leetcode第40题
会发现出现了很多重复的结果,就是因为没有跳过重复的 1。在求 opt [ 1 ] 的时候就变成了 [ [ 1 ],[ 1 ] ] 这样子,由于后边求的时候都是直接在原来每一个列表里加数字,所有后边都是加了两次了。
leetcode第40题
leetcode第37题
从上到下,从左到右遍历每个空位置。在第一个位置,随便填一个可以填的数字,再在第二个位置填一个可以填的数字,一直执行下去直到最后一个位置。期间如果出现没有数字可以填的话,就回退到上一个位置,换一下数字,再向后进行下去。
leetcode第37题