NJU-高级算法-数组和窗口

Description

给定一个整型数组arr和一个大小为w的窗口,窗口从数组最左边滑动到最右边,每次向右滑动一个位置,求出每一次滑动时窗口内最大元素的和。

Input

输入第一行为用例个数, 每个测试用例输入的第一行为数组,每一个元素使用空格隔开;第二行为窗口大小。

Output

输出每个测试用例结果。

Sample Input 1 

1
4 3 5 4 3 3 6 7
3

Sample Output 1

32

 

思路

方法一

暴力法

窗口每次向右移动一位时,我们每次遍历窗口内的w个元素,然后求出此时窗口的最大值就可以了,用这种方法的时间复杂度是 O(wn)。代码如下:

#include <iostream>
#include <vector>
#include <string.h>
#include <string>
#include <deque>
#include <sstream>
using namespace std;

int main()
{
    int t;
	cin >> t;
	for (int turn = 0; turn < t; turn++) {
		int res = 0, len;
		//将一组未知个数的数字读入一个数组a[]
		string str;
		cin.ignore();
		getline(cin, str);
		char aChar[90];
		strcpy_s(aChar, str.c_str());

		int a[999] = { 0 };

		int index = 0, alen = -1;
		while (aChar[index] != '\0') {
			if (aChar[index] == ' ') {
				index++;
			}
			else {
				alen++;
				a[alen] = aChar[index] - '0';
				index++;
			}
		}
		alen++;

        /*另一种输入数组的方式,将数组输入vector
		 *stringstream ss;
		 *string str;
		 *int sin;
		 *cin.ignore();
		 *getline(cin, str);
         *    
		 *vector<int> a;
		 *ss << str;
         *
		 *while (ss >> sin) {
		 *	a.push_back(sin);
		 *}
		 *int aLen = a.size();
         */

		cin >> len;

		//题目变为对数组a中aLen个数字进行滑动查找
		int sum = 0;
		if (len < 1 || alen < len || alen<1) {
			if (turn + 1 == t) {
				printf("%d", res);
			}
			else {
				printf("%d\n", res);
			}
		}
		else {
			int maxNum = 0;
			for (int i = len - 1; i < alen; i++) {
				maxNum = a[i];
				for (int j = i - 1; j > i - len; j--) {
					if (maxNum < a[j]) {
						maxNum = a[j];
					}
				}
				sum += maxNum;
			}
			res = sum;

			if (turn + 1 == t) {
				printf("%d", res);
			}
			else {
				printf("%d\n", res);
			}
		}
	}
	return 0;
}

 

方法二

双向队列

使用双向队列,用来保存有可能是滑动窗口最大值的数组的下标。在存入一个数字的下标之前,首先要判断队列里已有数字是否小于待存入的数字。如果已有的数字小于待存入的数字,那么这些数字已经不可能是滑动窗口的最大值,因此需要在队列尾部删除(pop_back)。同时,如果队列头部的数字已经从窗口里滑出,那么滑出的数字也需要从队列的头部删除(pop_front)。
————————————————
版权声明:本文为CSDN博主「SCS199411」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/SCS199411/article/details/92414455

代码如下:

#include <iostream>
#include <vector>
#include <string.h>
#include <string>
#include <deque>
using namespace std;

int main()
{
	int t;
	cin >> t;
	for (int turn = 0; turn < t; turn++) {
		int res = 0, len;
		//将一组未知个数的数字读入一个数组a[]
		string str;
		cin.ignore();
		getline(cin, str);
		char aChar[90];
		strcpy(aChar, str.c_str());

		vector<int> a;

		int ind = 0, aLen = 0;
		while (aChar[ind] != '\0') {
			if (aChar[ind] == ' ') {
				ind++;
			}
			else {
				a.push_back(aChar[ind] - '0');
				ind++;
			}
		}
		aLen = a.size();

		cin >> len;

		//题目变为对数组a中aLen个数字进行滑动查找
		int sum = 0;

		if (a.empty() || len < 1 || len > aLen) {
			if (turn + 1 == t) {
				printf("%d", res);
			}
			else {
				printf("%d\n", res);
			}
		}
		else {
			deque<int> dq;
			for (int i = 0; i < len; ++i) {
				while (!dq.empty() && a[i] >= a[dq.back()]) {
					dq.pop_back();
				}
				dq.push_back(i);
			}
			for (int i = len; i < a.size(); ++i) {
				res += a[dq.front()];
				while (!dq.empty() && a[i] >= a[dq.back()])
					dq.pop_back();
				if (!dq.empty() && dq.front() <= (int)(i - len))
					dq.pop_front();
				dq.push_back(i);
			}
			res += a[dq.front()];
			if (turn + 1 == t) {
				printf("%d", res);
			}
			else {
				printf("%d\n", res);
			}
		}
	}
	return 0;
}

 

转载自:

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31561266/viewspace-2286701/

转载于:http://blog.itpub.net/31561266/viewspace-2286701/

https://blog.csdn.net/congce9794/article/details/100304453

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值