有一个 类似 二分搜索的方法。 这个方法有两个入参: sequence
是一个整数数组, target
是一个整数。 这个方法可以判断 target
是否存在 sequence
中。
该方法的伪代码如下:
func(sequence, target) while sequence is not empty randomly choose an element from sequence as the pivot if pivot = target, return true else if pivot < target, remove pivot and all elements to its left from the sequence else, remove pivot and all elements to its right from the sequence end while return false
当 sequence
是排好序时, 这个方法对 所有 值都可正常判断。如果 sequence
不是排好序的, 该方法并不是对所有值都可正常判断, 但对一些 值仍可正常判断。
给定一个仅包含不同数字的数组 nums
表示 sequence
, nums是否排序未知,对于 所有可能的选择, 返回通过这个方法保证能找到的值的数量。
示例 1:
输入: nums = [7] 输出: 1 解释: 7 保证能被找到. 因为数组中只有一个数字, 7 一定会被选中. 因为选中的值等于target, 这个方法会返回 true.
示例 2:
输入: nums = [-1,5,2] 输出: 1 解释: 只有 -1 保证能被找到. 如果 -1 被选中, 这个方法就会返回 true. 如果 5 被选中, 5 和 2 会被移除。 在下一次循环时, 这个序列只有一个元素: -1 ,这个方法就会返回 true. 如果 2 被选中, 2 将会被移除。 在下次循环时, 这个序列里将会有 -1 和 5. 无论哪个数字被选中, 这个方法都会找到 -1 且返回 true. 5 不能保证被找到。 如果 2 被选中, -1, 5 和 2 将会被移除。 这个序列将会被清空且这个方法会返回 false。 2 不能保证被找到. 如果 5 被选中, 5 和 2 将会被移除。在下次循环时, 这个序列只会有一个元素: -1 且这个方法会返回 false。 因为只有-1 是保证能被找到的, 你应该返回 1.
提示:
1 <= nums.length <= 105
-105 <= nums[i] <= 105
nums
中所有值都 不同.
提升: 如果 nums
存在 重复的值, 你会如何修改你的算法吗?
我们注意到,对于数组中的每个元素,如果它是可被二分搜索的,那么需要满足两个条件:
- 这个元素大于它的左边所有元素,否则,如果左边存在比当前元素大的元素,那么就会被移除,导致无法找到当前元素;
- 这个元素小于它的右边所有元素,否则,如果右边存在比当前元素小的元素,那么就会被移除,导致无法找到当前元素。
我们创建一个数组
我们先从左到右遍历数组,维护前缀最大值
然后我们从右到左遍历数组,维护后缀最小值
最后我们统计
时间复杂度
class Solution:
def binarySearchableNumbers(self, nums: List[int]) -> int:
n = len(nums)
ok = [1] * n
mx, mi = -1000000, 1000000
for i, x in enumerate(nums):
if x < mx:
ok[i] = 0
else:
mx = x
for i in range(n - 1, -1, -1):
if nums[i] > mi:
ok[i] = 0
else:
mi = nums[i]
return sum(ok)
class Solution {
public int binarySearchableNumbers(int[] nums) {
int n = nums.length;
int[] ok = new int[n];
Arrays.fill(ok, 1);
int mx = -1000000, mi = 1000000;
for (int i = 0; i < n; ++i) {
if (nums[i] < mx) {
ok[i] = 0;
}
mx = Math.max(mx, nums[i]);
}
int ans = 0;
for (int i = n - 1; i >= 0; --i) {
if (nums[i] > mi) {
ok[i] = 0;
}
mi = Math.min(mi, nums[i]);
ans += ok[i];
}
return ans;
}
}
class Solution {
public:
int binarySearchableNumbers(vector<int>& nums) {
int n = nums.size();
vector<int> ok(n, 1);
int mx = -1000000, mi = 1000000;
for (int i = 0; i < n; ++i) {
if (nums[i] < mx) {
ok[i] = 0;
}
mx = max(mx, nums[i]);
}
int ans = 0;
for (int i = n - 1; i >= 0; --i) {
if (nums[i] > mi) {
ok[i] = 0;
}
mi = min(mi, nums[i]);
ans += ok[i];
}
return ans;
}
};
func binarySearchableNumbers(nums []int) (ans int) {
n := len(nums)
ok := make([]int, n)
for i := range ok {
ok[i] = 1
}
mx, mi := -1000000, 1000000
for i, x := range nums {
if x < mx {
ok[i] = 0
} else {
mx = x
}
}
for i := n - 1; i >= 0; i-- {
if nums[i] > mi {
ok[i] = 0
} else {
mi = nums[i]
}
ans += ok[i]
}
return
}