两道二分题 LeetCode 33 & 34
Keywords: Binary Search
基本姿势 lower_bound && upper_bound
Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm’s runtime complexity must be in the order of O(log n).
If the target is not found in the array, return
[-1, -1]
.For example,
Given[5, 7, 7, 8, 8, 10]
and target value 8,
return[3, 4]
.
题意没啥可说的,先上代码:
upperBound()
返回 > target 的第一个位置。因为 == 的时候加入右边了。最后一次满足 == 之后加了1,故返回的是第一个 > 的位置。
同理lowerBound()
返回 >= target 的第一个位置。
两函数均为左闭右开,借鉴 C++ STL 的风格。
显然当 target 存在于 nums 中时, 答案是 [lowerBound(), upperBound() - 1]
。否则 lowerBound() = upperBound()
,故只要判断 ans[0] > ans[1]
就说明 target 不存在了。
刚写完就 T 了我的内心很崩溃……最后发现是 int m = l + (r - l) >> 1;
写蠢了,真的被自己蠢哭……括号应该打成 (r - l >> 1)
啊。既然是写 LC,而且用的还是 Java,以后还是少写这种风格的代码好了。
感谢韬韬的教学,虽然我A了之后他还WA着……
trick1:int m = l + (r - l) / 2
int m = l + r >> 1
有溢出风险
trick2:nums[m] <= target
,target 写在右边
为了 C++ 的范型?向 STL 看齐?but 我现在好像是在写 Java…以及以 target 为基准判断更自然嘛,所以我还是选择不这么写 [冷漠.jpg]
进阶理解
33. Search in Rotated Sorted Array 题目链接
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e.,
0 1 2 4 5 6 7
might become4 5 6 7 0 1 2
).You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
一开始想的是先二分一遍找出 privot,再对两边分别二分,写了整整 30 行 - -。其实一开始就隐隐约约感觉一次二分就可以了,就是不想写。但是三次二分写完才发现太挫了 - - ,所以还是强行重新写。
|
|
二分后,两边必有一部分是整体有序的,如果数据在有序的范围内,就可以做普通二分了,否则继续强行分再判断哪边有序。
注意这里我没有用常见的左闭右开 [l,r) 的写法,而是整个闭区间 [l, r]。因为一开始习惯性写左闭右开遇到了一些问题,写得不那么优雅,干脆换成闭区间了。
判断中也要注意 =
和 l = m + 1
的问题。
应该可以再进一步简化代码,把判断条件堆在一起,不过现在越来越觉得还是可读性比较重要了,为了一点点看上去的优雅牺牲可读性意义不大。
至于很挫的代码在这里的search1()。