1673. 找出最具竞争力的子序列

题目

给定一个整数数组 nums 和一个正整数 k,返回长度为 k 且最具竞争力的 nums 子序列。

数组的子序列是从数组中删除一些元素(可能不删除元素)得到的序列。

在子序列 a 和子序列 b 第一个不相同的位置上,如果 a 中的数字小于 b 中对应的数字,那么我们称子序列 a 比子序列 b(相同长度下)更具竞争力。例如,[1,3,4][1,3,5] 更具竞争力,在第一个不相同的位置,也就是最后一个位置上,4 小于 5

示例

示例 1:

输入:nums = [3,5,2,6], k = 2

输出:[2,6]

解释:在所有可能的子序列集合 [{3,5}, {3,2}, {3,6}, {5,2}, {5,6}, {2,6}] 中,[2,6] 最具竞争力。

示例 2:

输入:nums = [2,4,3,3,5,4,9,6], k = 4

输出:[2,3,3,4]

提示:

  • 1 <= nums.length <= 105
  • 0 <= nums[i] <= 109
  • 1 <= k <= nums.length

思路

为了找到最具竞争力的子序列,我们可以使用单调栈(Monotonic Stack)的策略。单调栈是一种保持元素顺序的栈结构,在这个问题中,我们需要维护一个递增栈,以确保子序列的最小化竞争力。

主要思路如下:

  1. 遍历数组 nums,并在每一步中确保栈中的元素保持递增顺序。
  2. 如果当前元素比栈顶元素小,并且栈中的元素数目加上剩余的元素数目大于 k,则弹出栈顶元素。
  3. 将当前元素入栈,前提是栈的大小小于 k

mostCompetitive函数

int* mostCompetitive(int* nums, int numsSize, int k, int* returnSize) {
    *returnSize = k;
    int* res = (int*)malloc(sizeof(int) * k);
    int top = -1;  // 栈顶指针,表示当前子序列的最后一个元素的位置

    for (int i = 0; i < numsSize; i++) {
        // 如果当前元素比栈顶元素小,并且栈中元素数目加上剩余的元素数目大于k,则弹出栈顶元素
        while (top >= 0 && nums[i] < res[top] && top + numsSize - i > k - 1) {
            top--;
        }
        // 如果当前栈的大小小于k,则将当前元素入栈
        if (top < k - 1) {
            res[++top] = nums[i];
        }
    }

    return res;
}

returnSize 用于记录返回数组的大小,并将其设置为 k。
为存储最终结果的数组 res 分配了 k 个整数的内存空间。
top 初始化为 -1,表示栈为空,后续将用于指示栈顶元素的位置。

时间复杂度分析

  • for 循环: 该循环遍历了整个输入数组 nums,时间复杂度为 O(n),其中 n 是数组 nums 的长度。

  • while 循环: 在每次遍历中,while 循环最多执行栈中元素的数量(最多 k 次),因为每次循环都可能将栈顶元素弹出,最多进行 k 次操作。在最坏情况下,每个元素都需要进栈或出栈一次,所以 while 循环的总体时间复杂度为 O(n)。

综上所述,代码的总体时间复杂度为 O(n)。

空间复杂度分析

  • res 数组: 空间复杂度为 O(k),其中 k 是返回数组的大小,也是最终结果数组的长度。

  • top 变量: 使用了一个整数变量来表示栈顶指针,不占用额外的空间,因此空间复杂度为 O(1)。

综上所述,代码的总体空间复杂度为 O(k)。

这段代码的时间复杂度是线性的,因为它只对输入数组进行了一次线性遍历。而空间复杂度取决于返回数组的大小 k

结果

结果

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值