首页 > 其他分享 >C语言中的窗口滑动技术

C语言中的窗口滑动技术

时间:2023-04-04 11:38:01浏览次数:42  
标签:窗口 int sum C语言 Enter 滑动 array

学习文章:C语言中的窗口滑动技术

  • C语言中的窗口滑动技术

循环几乎是每个复杂问题的一部分。太多的循环/嵌套循环会增加所需的时间,从而增加程序的时间复杂性。窗口滑动技术是一种计算技术,用于减少程序中使用的嵌套循环的数量,通过用单个循环代替嵌套循环来提高程序的效率。

如果你熟悉计算机网络中的滑动窗口协议,这种技术也很类似,本教程通过不同的例子解释了这种技术的使用方法。

一般来说,当我们使用这样的嵌套循环时

for(i = 1; i <= n; i++)
{
    for(j = i; j < k; j++)
    {
    }
}

迭代: 外循环执行\(n\)次;每执行一次外循环,内循环就执行\((k-i)\)次。执行整个循环所需的平均时间大约为$O(N^2) $。因此,开发人员不建议使用循环。

让我们举一个例子来清楚地理解这个概念

假设我们要找到一个数组中\(’k’\)个连续元素的最大和,用户提供\(k\)值:

首先,如果我们使用传统的方法,对于数组中的每个元素\(i\),我们将从\(i+1\)到\(n-1\)遍历数组,其中\(n\)是数组的大小,我们需要对每个元素都这样做,然后比较总和,得到最大总和。

  • 暴力方法
#include<stdio.h>
int main()
{
/*
    找到一个数组中’k’个连续元素的最大和
*/
    int n, size, sum=0, max = 0, j;

    printf("Enter the size of the array: ");
    scanf("%d", &n);

    int arr[n], i;
    printf("Enter the elements of the array: ");
    for(i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }

    printf("Enter the size of sub-array: ");
    scanf("%d", &size);

    for(i = 0; i < (n - size) + 1; i++)
    {
        /*
            其实也是滑动窗口的思想
        */
        sum = 0;
        for(j = i; j < i + size; j++)
        {
            sum = sum + arr[j];
        }
        if(sum > max)
        {
            max = sum;
        }
    }
    printf("The maximum sum of %d consecutive elements of the array: %d\n", size, max);
}

输出

Enter the size of the array: 10
Enter the elements of the array: 8 2 1 7 3 2 5 8 1 3
Enter the size of the sub-array: 3
The maximum sum of 3 consecutive elements of the array: 20

现在,滑动窗口技术来了

这里的概念是,我们创建一个大小为\(k\)的窗口,我们将通过一个单位指数不断地滑动它。在这里,窗口并不是什么技术术语。我们不是像在循环中那样使用一个单一的值,而是在每次迭代中同时使用多个元素。

比如说给定一个大小为10的数组:

C语言中的窗口滑动技术

假设我们需要3个连续索引的最大和,创建一个3个大小的窗口,并在整个数组中不断滑动(遍历)它。这里有一个形象的表示。

迭代1:

C语言中的窗口滑动技术

迭代2 :

C语言中的窗口滑动技术

迭代3:

C语言中的窗口滑动技术

迭代4:

C语言中的窗口滑动技术

迭代5:

C语言中的窗口滑动技术

迭代6:

C语言中的窗口滑动技术

迭代7:

C语言中的窗口滑动技术

迭代8:

C语言中的窗口滑动技术

  • 使用这种方法,将没有内循环,一个单循环的迭代次数将是\((n – k + 1)\),在这种情况下是8。
  • 所以,滑动窗口是一种用于减少嵌套循环的技术,用一个单循环代替它,以减少总的时间复杂性。
  • 请注意,在每次迭代中,当窗口滑动到下一个索引时, 我们都会删除前一个窗口的第一个元素,并添加一个新的元素,即下一个继任索引。

下面是代码:

#include <stdio.h>

int maxsum(int a[], int k, int n);
int main()
{
    int n, i, k;

    printf("Enter the size of the array: ");
    scanf("%d", &n);
    int arr[n];
    printf("Enter the elements: ");

    for (i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }
    printf("Enter the value of k: ");
    scanf("%d", &k);

    int max = maxsum(arr, k, n);
    printf("The maximum sum of %d consecutive elements in the array: %d\n", k, max);
}
int maxsum(int a[], int k, int n)
{
    int i, sum, maxm = 0;
    for (i = 0; i < k; i++)
    {
        maxm = maxm + a[i];     //记录第一个窗口元素和
    }
    sum = maxm;                 //初始化sum
    for (i = k; i < n; i++)
    {
        sum += a[i] - a[i - k]; //当窗口滑动到下一个索引时, 我们都会删除前一个窗口的第一个元素,并添加一个新的元素
        if (sum > maxm)
        {
            maxm = sum;
        }
    }
    return maxm;
}

输出:

Enter the size of the array: 10
Enter the elements: 8 2 1 7 3 2 5 8 1 3
Enter the value of k: 3
The maximum sum of 3 consecutive elements in the array: 15
  • 暴力方法在两个嵌套循环中需要\(O(k*n)\)时间。
  • 通过使用滑动窗口技术,时间复杂度降低到\(O(n)\)。

以下是将该技术应用于手头任何问题的步骤:

  1. 首先,我们必须看到,窗口的大小是恒定的,不应该改变。我们可以只对这样的问题使用该技术。
  2. 在确保窗口大小没有变化后,计算第一个窗口的结果,与数组其他部分的计算结果进行比较。
  3. 现在,用一个循环来逐个滑动窗口的索引,直到最后,不断更新所需的值。

标签:窗口,int,sum,C语言,Enter,滑动,array
From: https://www.cnblogs.com/pam-sh/p/17285796.html

相关文章

  • 滑动窗口-leetcode344-反转字符出啊
    编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间解决这一问题。示例1:输入:s=["h","e","l","l","o"]输出:["o","l","l","e","h"]示例......
  • 滑动窗口-leetcode-167-俩树之和
    以长度为2的整数数组[index1,index2]的形式返回这两个整数的下标index1和index2。你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。你所设计的解决方案必须只使用常量级的额外空间。示例1:输入:numbers=[2,7,11,15],target=9输出:[1,2]......
  • 学习C语言第五天
    一.指针1.1认识它1.2指针==地址inta=10; 变量名能访问,通过地址也能访问&取地址运算符*将地址内的值读出运算符1.3指针变量==存放地址的变量*的标识作用只产生在指针变量定义或声明的时候*的运算作用变量访问的两种方式直接访......
  • 单调队列与滑动窗口一
    单调队列--滑动窗口最值问题显然O(n^2)的时间复杂度是无法接受的我们先考虑滑动窗口滑动过程中最大值的问题过程即为我们想要维护每个滑动区间的最大值,当新插入一个元素前,我们把这个区间的第一个元素移除,插入新元素,并想在尽可能贴近O(1)的时间内得到该区间的最大值......
  • C语言逆向——指针
    指针类型在C语言里面指针是一种数据类型,是给编译看的,也就是说指针与int、char、数组、结构体是平级的,都是一个类型。带"*"号的变量我们称之为指针类型,例如:char*x;short*y;int*a;float*b;...任何类型都可以带这个符号,格式就是:类型*名称;星号可以是多个。指针变量......
  • C语言逆向——预处理之宏定义、条件编译与文件包含
    预处理之宏定义、条件编译与文件包含预处理一般是指在程序源代码被转换为二进制代码之前,由预处理器对程序源代码文本进行处理,处理后的结果再由编译器进一步编译。预处理功能主要包括宏定义、文件包含、条件编译三部分。宏定义简单的宏:#define标识符字符序列#defineFALS......
  • 【数据结构】二叉树先序、中序、后序及层次遍历(C语言版)
    一、图示展示1.先序遍历先序遍历可以想象为,一个小人从一棵二叉树根节点为起点,沿着二叉树外沿,逆时针走一圈回到根节点,路上遇到的元素顺序,就是先序遍历的结果先序遍历结果为:ABDHIEJCFKG动画演示:记住小人沿着外围跑一圈(直到跑回根节点),多看几次动图便能理解2.......
  • C语言再学习 -- 详解C++/C 面试题 2
    (经典)C语言测试:想成为嵌入式程序员应知道的0x10个基本问题。参看:嵌入式程序员面试问题集锦1、用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #defineSENCONDS_PER_YEAR(60*60*24*365)UL解答:#define声明一个常量,使用计算常量表达式的值来表明一年中有多少......
  • C语言再学习 -- 输入/输出
    一、缓冲区输入字符的立即回显是非缓冲或直接输入的一个实例,它表示你说键入的字符被收集并存储在一个被成为缓冲区的临时存储区域中。按下回车可使你所键入的字符块对程序变成可用。为什么需要缓冲区?首先,将若干个字符作为一个块传输比逐个发送这些字符耗费的时间少。其次,如果你输入......
  • C语言再学习 -- 运算符与表达式
    分三部分来讲一、左值与右值参看:左值与右值首先我们需要理解左值和右值的定义:左值指的是如果一个表达式可以引用到某一个对象,并且这个对象是一块内存空间且可以被检查和存储,那么这个表达式就可以做为一个左值。      右值指的是引用了一个存储在某个内存地址里的数据。从上面......