leetcode
leetcode 1751 ~ 1800
未排序数组中的可被二分搜索的数

未排序数组中的可被二分搜索的数

难度:

标签:

题目描述

代码结果

运行时间: 66 ms, 内存: 26.5 MB


/*
 * LeetCode 1966: Find Elements in Unsorted Array that Can be Binary Searched
 * 
 * 思路:
 * 1. 使用Java Stream来解决这个问题。
 * 2. 我们依然使用两个数组:leftMax和rightMin。
 * 3. leftMax[i]表示从左到i的子数组中的最大值。
 * 4. rightMin[i]表示从i到右的子数组中的最小值。
 * 5. 对于每个元素,如果leftMax[i-1] <= nums[i] <= rightMin[i+1],那么它可以通过二分搜索找到。
 */

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Solution {
    public List<Integer> binarySearchableNumbers(int[] nums) {
        int n = nums.length;
        int[] leftMax = new int[n];
        int[] rightMin = new int[n];

        leftMax[0] = nums[0];
        for (int i = 1; i < n; i++) {
            leftMax[i] = Math.max(leftMax[i-1], nums[i]);
        }

        rightMin[n-1] = nums[n-1];
        for (int i = n-2; i >= 0; i--) {
            rightMin[i] = Math.min(rightMin[i+1], nums[i]);
        }

        return IntStream.range(0, n)
                .filter(i -> (i == 0 || nums[i] >= leftMax[i-1]) && (i == n-1 || nums[i] <= rightMin[i+1]))
                .mapToObj(i -> nums[i])
                .collect(Collectors.toList());
    }
}

解释

方法:

该题解的核心思路是检查每个数组元素是否可以通过二分搜索确定其位置。一个元素x是可被二分搜索的,如果它的位置不受其左侧元素的最大值和右侧元素的最小值的影响。算法首先从左向右遍历数组,记录到目前为止的最大值,如果当前元素小于这个最大值,则其不可能是可被二分搜索的元素。接着,算法从右向左遍历数组,记录到目前为止的最小值,如果当前元素大于这个最小值,则其同样不可能是可被二分搜索的元素。最终,所有同时不被左侧最大值和右侧最小值影响的元素计数即为答案。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在算法中需要从两个方向遍历数组来判断一个元素是否可被二分搜索?
在算法中从两个方向遍历数组是为了确保每个元素在其位置上是否独立于其左侧和右侧的元素。对于一个元素来说,只有当它大于其左侧所有元素的最大值并且小于其右侧所有元素的最小值时,才能通过二分搜索准确地被定位。因此,从左向右遍历来更新最大值,确保元素大于其左侧的所有元素;从右向左遍历来更新最小值,确保元素小于其右侧的所有元素。这两个条件同时满足时,该元素才是可被二分搜索的。
🦆
在从左向右遍历时,将最大值初始化为-1000000是否安全,或者这个值是否应该依赖于数组中的具体数据类型和范围?
将最大值初始化为-1000000可能不是安全的选择,因为这个值可能不适用于所有范围的数据。例如,如果数组中包含比-1000000还小的值,那么这个初始化就会导致错误的结果。更安全的做法是使用数组中的第一个元素作为初始化的最大值,这样可以确保处理的逻辑始终适用于任何数据类型和范围。
🦆
在遍历数组的过程中,如果数组中存在重复元素,这种情况下算法的处理方式是怎样的,特别是对于那些重复元素?
如果数组中存在重复元素,该算法会标记所有重复元素中第一个出现的为可搜索(如果它大于之前所有元素的最大值),而之后出现的重复元素都会被标记为不可搜索(因为它们不小于前面的元素,即不满足小于右侧所有元素的最小值的条件)。这意味着除非重复元素是连续的一段中的第一个,并且没有其他左侧元素大于它,否则这些重复元素不会被认为是可二分搜索的。
🦆
算法返回的结果是可被二分搜索的元素数量,如果要修改算法使其直接返回这些元素的索引,应如何调整?
要修改算法以返回可被二分搜索的元素的索引,可以在遍历过程中保存满足条件的元素的索引而非计数。具体来说,可以初始化一个空列表用来存储索引,然后在最后的遍历中,如果元素满足可被二分搜索的条件(即ok数组中对应位置为1),则将该索引添加到列表中。最后返回这个列表即可。

相关问题