leetcode
leetcode 2101 ~ 2150
找到所有好下标

找到所有好下标

难度:

标签:

题目描述

代码结果

运行时间: 87 ms, 内存: 27.7 MB


/*
 * 思路:
 * 1. 使用两个数组 left 和 right 分别记录每个位置之前和之后的非递增和非递减长度。
 * 2. 遍历数组,根据条件找到所有的好下标。
 */

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

public class GoodIndicesStream {
    public List<Integer> goodIndices(int[] nums, int k) {
        int n = nums.length;
        int[] left = new int[n];
        int[] right = new int[n];
        List<Integer> result = new ArrayList<>();
        
        // 初始化left数组
        IntStream.range(0, n).forEach(i -> {
            if (i == 0 || nums[i] <= nums[i - 1]) {
                left[i] = (i == 0) ? 1 : left[i - 1] + 1;
            } else {
                left[i] = 1;
            }
        });
        
        // 初始化right数组
        IntStream.iterate(n - 1, i -> i >= 0, i -> i - 1).forEach(i -> {
            if (i == n - 1 || nums[i] <= nums[i + 1]) {
                right[i] = (i == n - 1) ? 1 : right[i + 1] + 1;
            } else {
                right[i] = 1;
            }
        });
        
        // 查找好下标
        IntStream.range(k, n - k).filter(i -> left[i - 1] >= k && right[i + 1] >= k).forEach(result::add);
        
        return result;
    }
    
    public static void main(String[] args) {
        GoodIndicesStream solution = new GoodIndicesStream();
        int[] nums = {2, 1, 1, 1, 3, 4, 1};
        int k = 2;
        System.out.println(solution.goodIndices(nums, k)); // 输出: [2, 3]
    }
}

解释

方法:

解题思路主要是通过一次遍历来检查每一个可能的好下标。首先,初始化三个指针:left、right 和 cur。left 和 right 分别代表检查非递增和非递减子数组的起始位置。cur 用于计数连续满足条件的元素个数。遍历过程中,如果当前的元素满足非递增和非递减的条件,cur 递增并移动 left 和 right。当 cur 达到 k 时,说明找到了一个好下标并将其加入结果列表。如果条件被打破,cur 重置为 1。这种方法避免了多次重复检查子数组的情况。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
在题解中提到的`滑动窗口检查每个可能的好下标`策略如何确保不会错过任何一个好下标?
滑动窗口的策略基于两个主要的指针:left和right,其中right指针负责探索数组的向右边界,而left指针随着right的推进同时推进。由于right指针会从k+1起始,确保其遍历数组直到倒数第二个元素之前,这样就能够覆盖所有可能的好下标位置。每次循环中,left和right指针都会同步向右移动,确保数组中的每个元素都被考虑到,因此不会错过任何一个可能的好下标。
🦆
题解中提到,如果连续满足条件的元素个数达到k,记录为好下标。那么,如果在达到k之后的下一次迭代中条件不再满足,是如何处理的?
一旦连续满足条件的元素个数达到k,相应的下标会被记录为好下标。如果在此之后的下一次迭代中条件不再满足,即nums[left+1] > nums[left]或nums[right+1] < nums[right],则cur(当前连续满足条件的长度)会被重置为1,同时left和right指针会同步向右移动一位。这意味着,每次条件不满足时,都会从新的位置开始重新计数,以寻找新的可能的好下标。
🦆
题解中没有详细解释如何处理`cur`在不满足条件时的重置逻辑,能否详细说明这一部分的处理逻辑?
在题解的逻辑中,如果在遍历过程中遇到不满足非递增或非递减条件的情况,`cur`(当前连续满足条件的元素个数)会被立即重置为1。同时,left和right指针也会同步向右移动一位,从而开始新的检查周期。这种重置逻辑确保只有连续满足条件的元素序列才会被考虑为好下标的候选,一旦发现不符合条件的元素,之前的计数将不被考虑,且从新的起点开始重新计数。
🦆
题解说明中提到,当`right`指针到达数组末尾前,循环就会停止。这是否意味着数组的最后几个元素不会被完全检查?
确实,按照题解中的逻辑,当right指针达到数组的倒数第二个元素时,循环将停止。这意味着数组的最后几个元素不会作为好下标的起始点来考虑。在实际实现中,由于需要检查以每个元素为起始点的k个元素是否满足非递增或非递减条件,所以在接近数组末尾时可能无法形成完整的k长度的子数组,因此这些元素不会被算作好下标起始点。

相关问题