2026-08-01:最小稳定下标Ⅰ。用go语言,给定一个长度为 n 的整数数组 nums 和一个整数 k。对于数组中的每个位置 i,先找出从数组开头到位置 i

16 阅读5分钟

2026-08-01:最小稳定下标Ⅰ。用go语言,给定一个长度为 n 的整数数组 nums 和一个整数 k。对于数组中的每个位置 i,先找出从数组开头到位置 i 这段区间内的最大值,再找出从位置 i 到数组末尾这段区间内的最小值,用前者减去后者,得到该位置的一个差值。如果这个差值不超过 k,就认为这个位置是符合条件的。现在需要在这些符合条件的位置中,找到下标最小的那一个;如果没有任何一个位置符合条件,则返回 -1。

1 <= nums.length <= 100。

0 <= nums[i] <= 1000000000。

0 <= k <= 1000000000。

输入: nums = [5,0,1,4], k = 3。

输出: 3。

解释:

在下标 0 处:[5] 中的最大值是 5,[5, 0, 1, 4] 中的最小值是 0,因此不稳定值为 5 - 0 = 5。

在下标 1 处:[5, 0] 中的最大值是 5,[0, 1, 4] 中的最小值是 0,因此不稳定值为 5 - 0 = 5。

在下标 2 处:[5, 0, 1] 中的最大值是 5,[1, 4] 中的最小值是 1,因此不稳定值为 5 - 1 = 4。

在下标 3 处:[5, 0, 1, 4] 中的最大值是 5,[4] 中的最小值是 4,因此不稳定值为 5 - 4 = 1。

这是第一个不稳定值小于等于 k = 3 的下标,因此答案是 3。

题目来自力扣3903。

根据给定的代码和题目要求,下面分步骤详细说明整个求解过程,最后给出时间和空间复杂度。


算法处理步骤

  1. 输入数据
    给定一个整数数组 nums(长度记为 n,且 n >= 1)和一个整数 k

  2. 预处理:计算后缀最小值数组

    • 创建一个长度为 n 的数组 sufMin,用于存储从每个位置 i 到数组末尾这段区间内的最小值。
    • 首先将最后一个位置 n-1 的后缀最小值设为 nums[n-1](因为区间只包含自身)。
    • 然后从倒数第二个位置 n-2 开始,依次向前遍历:
      对于每个 i,比较 nums[i] 和已经计算出的 sufMin[i+1],取其中的较小值赋给 sufMin[i]
      这样,sufMin[i] 就表示 nums[i]nums[n-1] 这段范围内的最小值。
  3. 从左到右遍历并计算不稳定值

    • 初始化一个变量 preMax 为 0(因为题目保证 nums[i] >= 0,所以初始值 0 不会影响后续最大值更新;若 nums[0] 也为 0,则取最大值后仍为 0,若大于 0 则会被更新)。
    • 按顺序遍历数组下标 i 从 0 到 n-1
      • 更新 preMax:将当前元素 nums[i] 与当前的 preMax 比较,取较大者作为新的 preMax。此时 preMax 就代表了从数组开头到当前位置 i 这段区间内的最大值。
      • 取出已经准备好的 sufMin[i],它代表从当前位置 i 到数组末尾这段区间内的最小值。
      • 计算不稳定值:差值 = preMax - sufMin[i]
      • 判断该差值是否小于等于 k
        若是,则当前下标 i 就是第一个(也是最小的)符合条件的稳定下标,立即返回 i
  4. 结束遍历
    如果遍历完整个数组都没有找到任何一个差值 <= k 的下标,则说明不存在稳定下标,返回 -1


示例推演(以 nums = [5,0,1,4]k=3 为例)

  • 计算后缀最小值:

    • sufMin[3] = 4
    • sufMin[2] = min(1, 4) = 1
    • sufMin[1] = min(0, 1) = 0
    • sufMin[0] = min(5, 0) = 0
  • 遍历过程:

    • i=0preMax = max(0,5)=5,差值 = 5 - sufMin[0](0) = 5,>3,不满足。
    • i=1preMax = max(5,0)=5,差值 = 5 - sufMin[1](0) = 5,>3,不满足。
    • i=2preMax = max(5,1)=5,差值 = 5 - sufMin[2](1) = 4,>3,不满足。
    • i=3preMax = max(5,4)=5,差值 = 5 - sufMin[3](4) = 1,≤3,满足,返回 3

复杂度分析

  • 时间复杂度
    预处理后缀最小值需要一次从右向左的遍历,时间复杂度为 O(n);
    从左向右的遍历也需要一次,时间复杂度为 O(n)。
    总时间复杂度为 O(n)

  • 额外空间复杂度
    主要开销是存储后缀最小值数组 sufMin,长度为 n,占用 O(n) 空间;
    其他变量(如 preMax)均占用常数空间。
    总额外空间复杂度为 O(n)


最终答案:当 nums = [5,0,1,4]k=3 时,返回 3;复杂度为 O(n) 时间,O(n) 空间。

Go完整代码如下:

package main

import "fmt"

func firstStableIndex(nums []int, k int) int {
	n := len(nums)
	sufMin := make([]int, n) // 后缀最小值
	sufMin[n-1] = nums[n-1]
	for i := n - 2; i >= 0; i-- {
		sufMin[i] = min(sufMin[i+1], nums[i])
	}

	preMax := 0 // 前缀最大值
	for i, x := range nums {
		preMax = max(preMax, x)
		if preMax-sufMin[i] <= k {
			return i
		}
	}
	return -1
}

func main() {
	nums := []int{5, 0, 1, 4}
	k := 3
	result := firstStableIndex(nums, k)
	fmt.Println(result)
}

在这里插入图片描述

Python完整代码如下:

# -*-coding:utf-8-*-

def first_stable_index(nums, k):
    n = len(nums)
    # 计算后缀最小值
    suf_min = [0] * n
    suf_min[-1] = nums[-1]
    for i in range(n - 2, -1, -1):
        suf_min[i] = min(suf_min[i + 1], nums[i])

    pre_max = 0  # 注意:与原 Go 代码保持一致,初始化为 0
    for i, x in enumerate(nums):
        pre_max = max(pre_max, x)
        if pre_max - suf_min[i] <= k:
            return i
    return -1

if __name__ == "__main__":
    nums = [5, 0, 1, 4]
    k = 3
    result = first_stable_index(nums, k)
    print(result) 

在这里插入图片描述

C++完整代码如下:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int firstStableIndex(vector<int>& nums, int k) {
    int n = nums.size();
    if (n == 0) return -1;

    // 后缀最小值数组
    vector<int> sufMin(n);
    sufMin[n - 1] = nums[n - 1];
    for (int i = n - 2; i >= 0; --i) {
        sufMin[i] = min(sufMin[i + 1], nums[i]);
    }

    int preMax = 0;
    for (int i = 0; i < n; ++i) {
        preMax = max(preMax, nums[i]);
        if (preMax - sufMin[i] <= k) {
            return i;
        }
    }
    return -1;
}

int main() {
    vector<int> nums = {5, 0, 1, 4};
    int k = 3;
    int result = firstStableIndex(nums, k);
    cout << result << endl;
    return 0;
}

在这里插入图片描述