2026-09-01:限制有序数组中的元素出现次数。用go语言,给定一个已经按从小到大排好的整数列表 nums,以及一个整数 k。现在需要生成一个

🤖 AI总结

主题

使用Go语言实现限制有序数组元素出现次数不超过k次的算法。

摘要

文章介绍了一种在有序数组中限制每个元素最多出现k次的算法,并提供了Go、Python、C++的代码实现。

关键信息

  • 1 利用有序数组特性,通过比较当前元素与结果区倒数第k个元素判断是否保留。
  • 2 提供Go、Python、C++三种语言实现,时间复杂度O(n),空间复杂度O(1)。
  • 3 文章末尾推广了AI知识分享公众号。

2026-09-01:限制有序数组中的元素出现次数。用go语言,给定一个已经按从小到大排好的整数列表 nums,以及一个整数 k。现在需要生成一个新列表,这个列表要满足:原列表中的每个数值,在新列表中最多只能重复出现 k 次,并且所有元素的先后顺序必须和原列表中的顺序完全一致。最后返回这个新列表。

1 <= nums.length <= 100。

1 <= nums[i] <= 100。

nums 按非递减顺序排序。

1 <= k <= nums.length。

输入: nums = [1,1,1,2,2,3], k = 2。

输出: [1,1,2,2,3]。

解释:

每个元素最多可以出现 2 次。

元素 1 出现了 3 次,因此只保留其中 2 次。

元素 2 出现了 2 次,因此全部保留。

元素 3 出现了 1 次,因此保留。

因此,结果数组为 [1, 1, 2, 2, 3]。

题目来自力扣3940。

算法步骤详细描述

1.输入与初始设定
给定一个已按非递减顺序排好的整数数组nums,以及一个正整数k(表示每个不同元素最多允许出现的次数)。数组长度记为n

  • 2.前 k 个元素默认保留
    由于数组已经排序,任何元素在数组中都是连续出现的。前k个元素(索引0k-1)中,同一个值的出现次数不可能超过k(因为总共才k个位置),因此它们一定满足“最多出现k次”的条件,可以直接纳入最终结果。
    为此,定义一个指针writePos(或称为栈大小),初始值为k,表示当前已保留的有效元素个数,也即下一个可写入位置。

  • 3.从第 k 个元素开始逐个检查
    从索引i = k开始,依次遍历数组的剩余元素(直到末尾)。对于每个元素nums[i],需要判断是否应该保留。

  • 4.判断是否保留当前元素的依据
    想要保留nums[i],必须确保该元素在已保留的结果中出现的次数还没有达到k次。
    因为数组是有序的,相同的元素必定连续出现。在已经保留的结果中,如果当前元素已经出现了k次,那么这k个相同元素必然位于结果区的末尾(因为有序)。结果区的末尾部分就是索引从writePos - kwritePos - 1的位置,其中倒数第k个就是索引writePos - k
    因此,只需比较当前元素nums[i]与结果区中倒数第k个元素(即nums[writePos - k])是否相等:

    若不相等:说明当前元素在结果区中的出现次数尚未达到k次(因为如果已经达到,那么倒数第k个元素必然等于当前元素)。此时该元素可以保留,将其写入nums[writePos](覆盖原值),然后将writePos加 1。

  • 若相等:说明当前元素已经在结果区中出现了k次,再添加就会超过限制,因此跳过该元素,不进行写入,继续处理下一个元素。

    5.原地更新与覆盖的安全性
    由于writePos总是小于或等于当前遍历的索引i(因为要么写入并增加,要么跳过,所以writePos不会超过i),因此写入操作不会覆盖尚未检查到的未来元素,保证了算法的正确性。

    6.遍历结束
    当循环结束后,所有原数组元素都被检查完毕。此时,数组的前writePos个元素(即nums[0:writePos])就是满足条件的结果序列,它们保持了原顺序,且每个不同元素最多出现k次。

    7.返回结果
    返回切片nums[:writePos]作为最终的新列表(此处返回的是原数组的视图,不复制数据,符合原代码做法)。

    复杂度分析

    时间复杂度:只对数组进行了一次线性扫描,从索引kn-1,每个元素执行常数次比较和可能的赋值操作,因此总时间复杂度为O(n),其中n是数组长度。

  • 额外空间复杂度:除了几个整型变量(如writePos、循环变量i)外,没有使用任何额外数组或数据结构,所有修改都在原数组上完成。返回的切片只是原数组的一部分引用,不产生新的数据副本。因此额外空间复杂度为O(1)(常数级别)。

    Go完整代码如下:

    package main

    import (
    "fmt"
    )

    func limitOccurrences(nums []int, k int) []int {
    stackSize := k // 栈的大小,前 k 个元素默认保留
    for i := k; i < len(nums); i++ {
    if nums[i] != nums[stackSize-k] { // 和栈的倒数第 k 个数比较
    nums[stackSize] = nums[i] // 入栈
    stackSize++
    }
    }
    return nums[:stackSize]
    }

    func main() {
    nums := []int{1, 1, 1, 2, 2, 3}
    k := 2
    result := limitOccurrences(nums, k)
    fmt.Println(result)
    }

    2026-09-01:限制有序数组中的元素出现次数。用go语言,给定一个已经按从小到大排好的整数列表 nums,以及一个整数 k。现在需要生成一个

    Python完整代码如下:

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

    def limit_occurrences(nums, k):
    """
    原地修改 nums,使每个不同元素最多出现 k 次,并返回新列表(切片)。
    保持原数组的相对顺序,要求 nums 已按升序排列。
    """
    if k <= 0:
    return [] # 无效 k,返回空列表(可按需调整)
    if len(nums) <= k:
    return nums[:] # 长度不足,无需修改,返回副本

    stack_size = k # 结果区域大小,初始保留前 k 个元素
    for i in range(k, len(nums)):
    # 比较当前元素与结果区中倒数第 k 个元素
    if nums[i] != nums[stack_size - k]:
    nums[stack_size] = nums[i]
    stack_size += 1
    return nums[:stack_size]

    def main():
    nums = [1, 1, 1, 2, 2, 3]
    k = 2
    result = limit_occurrences(nums, k)
    print(result)

    if __name__ == "__main__":
    main()

    2026-09-01:限制有序数组中的元素出现次数。用go语言,给定一个已经按从小到大排好的整数列表 nums,以及一个整数 k。现在需要生成一个

    C++完整代码如下:

      
    


    /**
    * 原地修改 nums,使每个不同元素最多出现 k 次,
    * 返回一个新的 vector,包含处理后的有效元素。
    * 要求 nums 已按升序排列。
    */
    std::vector limitOccurrences(std::vector& nums, int k) {
    // 处理 k <= 0 的情况(原 Go 未处理,这里增加防御)
    if (k <= 0) {
    return {};
    }

    int n = static_cast(nums.size());
    if (n <= k) {
    // 长度不足,直接返回原数组副本
    return nums;
    }

    int stackSize = k; // 结果区域大小,前 k 个元素默认保留
    for (int i = k; i < n; ++i) {
    // 比较当前元素与结果区中倒数第 k 个元素
    if (nums[i] != nums[stackSize - k]) {
    nums[stackSize] = nums[i]; // 入栈(原地覆盖)
    ++stackSize;
    }
    }

    // 返回有效部分构成的 vector
    return std::vector(nums.begin(), nums.begin() + stackSize);
    }

    int main() {
    std::vector nums = {1, 1, 1, 2, 2, 3};
    int k = 2;

    std::vector result = limitOccurrences(nums, k);

    // 输出结果
    for (int x : result) {
    std::cout << x << " ";
    }
    std::cout << std::endl;

    return 0;
    }

    2026-09-01:限制有序数组中的元素出现次数。用go语言,给定一个已经按从小到大排好的整数列表 nums,以及一个整数 k。现在需要生成一个

    我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。

    © 版权声明

    相关文章