IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 一道水题引发的尺取思想(有图解,简单易懂) -> 正文阅读

[数据结构与算法]一道水题引发的尺取思想(有图解,简单易懂)

关于一些简单算法的思想


前言

前几天做了HDU的一道水题,感觉自己的想法挺有趣的,仔细查找后发现这种想法原来叫做“尺取思想”


一、尺取思想是什么?

尺取思想:就是面对一组数据时,如同尺子一样,去一段一段的截取你所需要的序列

具体是如何呢,例题如下。


二、例题


1.题目概括(HDU-5776)

2.思维图

该题目核心考察的是:当给你一大段连续序列时,你是否能 从中找到一段连续子序列,使得该一段连续子序列的和等于M。例如:

?此时总和 M 为34,我们不妨从第一项 “1” 开始当作连续序列的开头。

我们往后增加子序列元素,此时子序列为{1、3},总和为4,远远不到34,我们继续。

?直到第五步,所选连续序列中已经有了“1”,“3”,“5”,“6”,“8”,“9”,总和为32,很接近M的大小,我们继续。

判断点:到第六步,序列中增加了一个“15”,此时总和达到了47,明显大于34,已经超出M的大小,说明再往后添加是不可行的,这也说明了,我们用 “?1 ”当作序列开始不可行,我们决定把“1”减掉。

然后我们发现采取减开头的方法,直到第七步,“6”减去,让“8”当作子序列的开头时,此时子序列总和等于32,小于M。我们可以意识到子序列需要往后添加元素,才有可能使得子序列总和等于M,因此有了第八步

经过我们一番折腾,终于在第九步,发现有一个子序列的总和与M的大小相匹配,该子序列为{15、19}


总结

不难发现规律,当子序列大于M总和时,我们需要将 子序列 前端元素进行删减,当子序列小于M总和,我们需要 往后增加 子序列 元素,一直进行如此操作,直到子序列总和与M匹配或者增加了总序列的最后一位元素,也没有与M匹配,判断为“没有子序列使得总和等于M”。? ? ?而这样的操作,就如同尺子般,一段一段去截取序列,然后进行判断,这就是所谓的“尺取思想”

该题的AC代码实现:(当时做的时候想到这么做就写上去了,AC以后也没进行进一步的优化了,如果各位前来阅读的佬们 有什么特别好的想法,也可以私信我(让我白嫖代码)。)

#include<stdio.h>
#include<string.h>
int arr[100009] = { 0 };
int main()
{
	int T,n, M, i, j, k, l,flag;
	int add=1, dec=1,sum=0;
	scanf("%d", &T);  //表示有T组数据
	for (i = 1; i <= T; i++)
	{
		memset(arr, 0, sizeof(arr));//每次输入一组数据前,将上组存入 数组 中的 数据 初始化
		scanf("%d %d", &n, &M);//M是总和
		for (j = 1; j <= n; j++)
		{
			scanf("%d", &arr[j]);//将总序列存入 数组 arr
		}
		
		flag = 0;sum = 0;add = 1;dec = 1;//计算部分
		
		while (sum != M)
		{   
			//判断跳出
			if (add == n+1 && sum != M)
			{
				flag = 1;//如果总序列最后一位元素进去也没有与M匹配的子序列,将flag标记为 1 ,然后跳出循环判断
				break;
			}

			for (int i = add; i<=n && sum < M; i++)//循环在子序列总和没有 大于M 之前不会停止,同时add的标记也不会停止
			{
				sum += arr[i];
				add = i;  //add作用是:标记当前 需要往后增加的 元素 在数组中的位置
				if (sum == M)
					break;
			}
			add++;
			for (int i = dec; i<=n && sum > M; i++)//循环在子序列总和 没有小于M 之前不会停止,同时dec的标记也不会停止
			{
				sum -= arr[i];
				dec = i;  //dec作用是:标记当前 需要往前删减的 元素 在数组中的位置
				if (sum == M)
					break;
			}
			dec++;
		}
		if (flag == 1)//flag为 1 即没有子序列的总和与 M 匹配
			printf("NO\n");
		if (flag == 0)
			printf("YES\n");
	}
	return 0;
}


  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-02 17:01:12  更:2021-12-02 17:02:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:23:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码