当前位置: 首页 > article >正文

LeetCode LCR180文件组合

滑动窗口算法:寻找连续文件编号组合

问题描述

在文件传输过程中,待传输的文件被切分成多个部分,每个部分的文件编号为一个正整数(至少有两个文件)。传输的要求是:找到所有连续文件编号的组合,使得这些文件编号的总和等于接收方指定的数字 target。返回的结果需要满足以下规则:

  1. 每种组合按照文件编号升序排列。

  2. 不同组合按照第一个文件编号升序排列。

例如,当 target = 15 时,符合条件的组合有:

  • [1, 2, 3, 4, 5](因为 1 + 2 + 3 + 4 + 5 = 15

  • [4, 5, 6](因为 4 + 5 + 6 = 15

  • [7, 8](因为 7 + 8 = 15

解题思路

这个问题可以看作是一个典型的滑动窗口问题。我们需要找到所有连续的文件编号组合,使得它们的总和等于 target。滑动窗口算法非常适合解决这种连续子数组或子序列的问题。

滑动窗口的核心思想

滑动窗口算法通过维护一个窗口(通常是一个连续的子数组或子序列),在满足一定条件的情况下,动态调整窗口的起始和结束位置。具体到这个问题:

  1. 初始化窗口:使用两个指针 left 和 right,分别指向窗口的起始和结束位置。

  2. 计算窗口内的总和

    • 如果总和小于 target,则扩大窗口(移动 right 指针)。

    • 如果总和大于 target,则缩小窗口(移动 left 指针)。

    • 如果总和等于 target,则记录当前的组合,并继续寻找下一个可能的组合。

  3. 终止条件:当 left 指针超过 target / 2 时,停止搜索(因为至少需要两个文件编号)。

为什么滑动窗口适合这个问题?

  • 连续子序列:文件编号是连续的,滑动窗口天然适合处理连续子序列的问题。

  • 高效性:滑动窗口的时间复杂度为 O(n),远优于暴力枚举的 O(n²)。

  • 简洁性:代码实现简单,逻辑清晰。 

代码实现

#include <stdio.h>
#include <stdlib.h>

int** fileCombination(int target, int* returnSize, int** returnColumnSizes) {
    // 初始化结果数组
    int** result = (int**)malloc(1000 * sizeof(int*));
    *returnColumnSizes = (int*)malloc(1000 * sizeof(int));
    *returnSize = 0;

    int left = 1, right = 1; // 窗口的起始和结束位置
    int sum = 0; // 窗口内文件编号的总和

    while (left <= target / 2) {
        if (sum < target) {
            // 总和小于 target,扩大窗口
            sum += right;
            right++;
        } else if (sum > target) {
            // 总和大于 target,缩小窗口
            sum -= left;
            left++;
        } else {
            // 找到符合条件的组合
            int* combination = (int*)malloc((right - left) * sizeof(int));
            for (int i = left; i < right; i++) {
                combination[i - left] = i;
            }
            (*returnColumnSizes)[*returnSize] = right - left;
            result[*returnSize] = combination;
            (*returnSize)++;

            // 移动左指针,继续寻找下一个组合
            sum -= left;
            left++;
        }
    }

    return result;
}

int main() {
    int target = 15;
    int returnSize;
    int* returnColumnSizes;
    int** result = fileCombination(target, &returnSize, &returnColumnSizes);

    // 输出结果
    for (int i = 0; i < returnSize; i++) {
        for (int j = 0; j < returnColumnSizes[i]; j++) {
            printf("%d ", result[i][j]);
        }
        printf("\n");
        free(result[i]); // 释放每个组合的内存
    }

    // 释放结果数组和列大小数组
    free(result);
    free(returnColumnSizes);

    return 0;
}

代码解析

初始化

  • result 用于存储所有符合条件的组合。

  • returnColumnSizes 用于存储每个组合的大小。

  • returnSize 用于记录符合条件的组合数量。

滑动窗口逻辑

  • 使用 left 和 right 指针维护窗口的起始和结束位置。

  • 通过调整 left 和 right 指针,动态计算窗口内的总和。

记录结果

  • 当找到符合条件的组合时,将其存储在 result 数组中,并更新 returnColumnSizes 和 returnSize

内存管理

  • 在 main 函数中,释放动态分配的内存,避免内存泄漏。

复杂度分析

  • 时间复杂度:O(target)。由于我们最多遍历到 target / 2,因此时间复杂度为线性。

  • 空间复杂度:O(1)。除了存储结果的空间外,只使用了常数级别的额外空间。

总结

通过滑动窗口算法,我们可以高效地解决这个问题。滑动窗口的核心思想是通过动态调整窗口的大小,找到满足条件的连续子序列。这种方法不仅代码简洁,而且时间复杂度较低,非常适合处理类似的问题。

希望这篇博客对你有所帮助!如果你有任何问题或建议,欢迎在评论区留言。


http://www.kler.cn/a/529162.html

相关文章:

  • 个人笔记(很没营养,纯备忘录)
  • mysql大表的解决方案,及Hive分页查询
  • 用c语言实现驱动表,用于对驱动的管理及输入输出
  • 精准化糖尿病知识问答(LLM+机器学习预测模型)
  • SARIMA介绍
  • 网站快速收录:如何设置robots.txt文件?
  • 进阶数据结构——双向循环链表
  • 8.攻防世界Web_php_wrong_nginx_config
  • pandas中的str使用方法
  • 【回溯+剪枝】电话号码的字母组合 括号生成
  • 五.简单函数
  • 【学习笔记】深度学习网络-正则化方法
  • 【NLP251】Transformer中的Attention机制
  • 【Proteus】NE555纯硬件实现LED呼吸灯效果,附源文件,效果展示
  • 设计心得——平衡和冗余
  • C语言:输入正整数链表并选择删除任意结点
  • ComfyUI安装调用DeepSeek——DeepSeek多模态之图形模型安装问题解决(ComfyUI-Janus-Pro)
  • 一文学会HTML编程之视频+图文详解详析
  • Selenium 使用指南:从入门到精通
  • 17.2 图形绘制8
  • ASP.NET Core与配置系统的集成
  • redex快速体验
  • 力扣动态规划-16【算法学习day.110】
  • 《苍穹外卖》项目学习记录-Day5在Java中操作Redis_Spring Data Redis
  • torch numpy seed使用方法
  • Easy系列PLC尺寸测量功能块(激光微距应用)