滑动窗口(双指针的应用)

本文详细介绍了滑动窗口的概念,如何通过它优化计算,以及在多个力扣编程题目中的应用,如学生分数的最小差值、子数组最大平均数、最长和谐子序列等,展示了其在解决特定问题时的高效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 滑动窗口是什么 ?

它是双指针的一种应用。

2. 使用滑动窗口的目的 ?

能够减少重合部分的计算,提高代码执行的效率,只需要使用一层循环即可。

3. 使用情况 ?

例如: 找出以 K 为长度的和最大或最小值。

力扣刷题

1984. 学生分数的最小差值

题目详情

给你一个 下标从 0 开始 的整数数组 nums ,其中 nums[i] 表示第 i 名学生的分数。另给你一个整数 k 。

从数组中选出任意 k 名学生的分数,使这 k 个分数间 最高分 和 最低分 的 差值 达到 最小化 。

返回可能的 最小差值 。
示例 1:

输入:nums = [90], k = 1
输出:0
解释:选出 1 名学生的分数,仅有 1 种方法:

  • [90] 最高分和最低分之间的差值是 90 - 90 = 0
    可能的最小差值是 0
    示例 2:

输入:nums = [9,4,1,7], k = 2
输出:2
解释:选出 2 名学生的分数,有 6 种方法:

  • [9,4,1,7] 最高分和最低分之间的差值是 9 - 4 = 5
  • [9,4,1,7] 最高分和最低分之间的差值是 9 - 1 = 8
  • [9,4,1,7] 最高分和最低分之间的差值是 9 - 7 = 2
  • [9,4,1,7] 最高分和最低分之间的差值是 4 - 1 = 3
  • [9,4,1,7] 最高分和最低分之间的差值是 7 - 4 = 3
  • [9,4,1,7] 最高分和最低分之间的差值是 7 - 1 = 6
    可能的最小差值是 2

题解

int cmp(const void* a, const void* b) { return (*(int*)a - *(int*)b); }

int minimumDifference(int* nums, int numsSize, int k) {
    qsort(nums, numsSize, sizeof(int), cmp);
    int start, end, res, min;
    min = nums[k - 1] - nums[0];
    res = min;
    for (start = 1, end = k; end < numsSize; start++, end++) { // 进行遍历
        min = nums[end] - nums[start];                         // 计算差值
        res = min < res ? min : res;
    }
    return res;
}

643. 子数组最大平均数 I

题目详情

给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。

请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。

任何误差小于 10-5 的答案都将被视为正确答案。

示例 1:

输入:nums = [1,12,-5,-6,50,3], k = 4
输出:12.75
解释:最大平均数 (12-5-6+50)/4 = 51/4 = 12.75
示例 2:

输入:nums = [5], k = 1
输出:5.00000

题解

double findMaxAverage(int* nums, int numsSize, int k) {
    int i, start, end;
    double sum = 0, res;
    // 计算前k个数字之和
    for (i = 0; i < k; i++)
        sum += nums[i];
    res = sum;
    for (start = 0, end = k; end < numsSize; end++, start++) {
        sum += nums[end] - nums[start]; 
        res = sum > res ? sum : res;
    }
    return res / k;
}

594. 最长和谐子序列

题目详情

和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。

现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。

数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。

示例 1:

输入:nums = [1,3,2,2,5,2,3,7]
输出:5
解释:最长的和谐子序列是 [3,2,2,2,3]
示例 2:

输入:nums = [1,2,3,4]
输出:2
示例 3:

输入:nums = [1,1,1,1]
输出:0

题解

int cmp(const void* a, const void* b) { return (*(int*)a - *(int*)b); }

int findLHS(int* nums, int numsSize) {
    qsort(nums, numsSize, sizeof(int), cmp);
    int begin = 0, end, count = 0, res = 0;
    for (end = 0; end < numsSize; end++) {
        while((nums[end] - nums[begin]) > 1) begin++;
        if (nums[end] - nums[begin] == 1)
            res = (end - begin + 1) > res ? (end - begin + 1) : res;
    }
    return res;
}

219. 存在重复元素 II

题目详情

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。
示例 1:

输入:nums = [1,2,3,1], k = 3
输出:true
示例 2:

输入:nums = [1,0,1,1], k = 1
输出:true
示例 3:

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

题解

typedef struct{
    int data;
    int index;
}record;

int cmp(int* a,int* b){
    return (*(record*)a).data-(*(record*)b).data;
}


bool containsNearbyDuplicate(int* nums, int numsSize, int k) {
    record temp[numsSize]; // 采用辅助数组
    for(int i=0;i<numsSize;i++){
       temp[i].data=nums[i];
       temp[i].index=i;
    }
    qsort(temp,numsSize,sizeof(record),cmp);

    for (int i = 0; i < numsSize-1; i++) {
            if (temp[i].data == temp[i+1].data && abs(temp[i].index - temp[i+1].index) <= k)
                return true;
    }
    return false;
}

485. 最大连续 1 的个数

题目详情

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例 1:

输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.
示例 2:

输入:nums = [1,0,1,1,0,1]
输出:2

提示:

1 <= nums.length <= 105
nums[i] 不是 0 就是 1.

题解

int findMaxConsecutiveOnes(int* nums, int numsSize) {
    int begin=0,end,res=0;
    for(end=0;end<numsSize;end++){
        if(nums[end]==1)
            res=(res>end-begin+1)?res:end-begin+1;
        else
            begin=end+1;
    }
    return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CPanMirai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值