可分区列表

问题描述

如果列表中的两个索引之间有一个位置,一边的数字之和等于另一边的数字之和,我们就会将列表定义为可分区的。如:
在这里插入图片描述

输入:第一行输入一个数字n,第二行输入n个数字 。
输出:输出“True”或“False”,分别表示该数组(列表)可分区/不可分区。

解题思路

本题的基本思路就是把每个位置都试一遍,既然要判断是否有分界点,那就一个一个试,先将位置定好,将该位置前和该位置后的所有元素分别求和,判断是否相等,相等则可分区,所有位置都试完了还没有出现相等的情况则不能分区。这种思路通过两层循环即可实现,时间复杂度为O(n^2)。

代码

#include <bits/stdc++.h>
using namespace std;
int main(){
	int n, flag = 0;
	cin >> n;
	int list[n];
	for(int i = 0; i < n; i++)
		cin >> list[i];
	for(int i = 1; i < n; i++){
		int suml = 0, sumr = 0;
		for(int j = 0; j < i; j++)
			suml += list[j];
		for(int k = i; k < n; k++)
			sumr += list[k]; 
		if(suml == sumr){
			flag = 1;
			break;
		}
	}
	(flag == 1) && (cout << "True");
	(flag == 0) && (cout << "False");
	return 0;
}
/*
5
1 1 1 2 1
6
3 4 6 2 5 20
6
25 8 5 3 7 2
*/

最后的注释里为三个简单样例。

进阶思路

由于上述方法的时间复杂度为O(n^2),当数据规模较小时不会出什么问题,而当数据规模较大时则会超时。为此,我们采用前缀和来优化。具体做法为:另开两个数组,分别从前往后、从后往前求前缀和,再由两个前缀和数组判断是否可分区。这种思路的时间复杂度为O(n)。

代码

#include <bits/stdc++.h>
using namespace std;
int main(){
	int n, flag = 0;
	cin >> n;
	int list[n], Psum[n], rPsum[n];
	for(int i = 0; i < n; i++)
		cin >> list[i];
	//to get the prefix sum
	Psum[0] = list[0];
	for(int i = 1; i < n; i++)
		Psum[i] = Psum[i - 1] + list[i];
	//to get the reverse prefix sum
	rPsum[n - 1] = list[n - 1];
	for(int i = n - 2; i >= 0; i--)
		rPsum[i] = rPsum[i + 1] + list[i];
	//to check out the flag
	for(int i = 0; i < n - 1; i++)
		if(Psum[i] == rPsum[i + 1]){
			flag = 1;
			break;
		}
	(flag == 1) && (cout << "True");
	(flag == 0) && (cout << "False");
	return 0;
}
/*
5
1 1 1 2 1
6
3 4 6 2 5 20
6
25 8 5 3 7 2
*/

Psum[i]为Psum[0],Psum[1],···,Psum[i]的和。
rPsum[i]为rPsum[i],rPsum[i + 1],···,rPsum[n - 1]的和。
判断条件:Psum[i] == rPsum[i + 1]的理解可以参照以下图片:
(以输入6 3 4 6 2 5 20为例)
在这里插入图片描述

结语

文中如果出现错误还请广大读者批评指正(o°ω°o)。
如果对各位看官有帮助不妨留下一个点赞 ̄ω ̄=。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值