算法(42)-数组等值切割-前缀累加和-哈希表Map-set版-C++

题目:给定正整数,返回该数组能不能分成4部分,且每个部分累加和相等。切分位置的数不要。
比如:arr[]=[3,2,4,1,4,9,5,10,1,2,2] 返回 true
           三个切割点下标为2,5,7.[3 2][1 4] [5] [1 2 2]

思路:预处理结构技巧,前缀累加和模型
           set和map两种哈希表类型。其实没啥本质差别。
1.unordered_set版
 

bool canSplits_set(vci arr) 
{
	if (arr.size() < 7) 
	{
		return false;
	}
	unordered_set <string> myset;                  //1.预处理结构
	int sum = 0;
	for (int i = 0; i < arr.size(); i++)          //2.预处理 得到累加和
	{
		sum += arr[i];                            //累加和计算
	}
	int leftSum = arr[0];
	for (int i = 1; i < arr.size() - 1; i++)    //3.放入 key 为 value index
	{
		string str = to_string(leftSum) + "_" + to_string(sum - leftSum - arr[i]);
	    myset.insert(str);
		leftSum += arr[i];
	}
	int l = 1;
	int lsum = arr[0];     
	int r = arr.size() - 2;
	int rsum = arr[arr.size() - 1];
	while (l < r - 3)
	{
		if (lsum == rsum) 
		{
			string lkey = to_string(lsum * 2 + arr[l]);
			string rkey = to_string(rsum * 2 + arr[r]);
			if (myset.count(lkey + "_" + rkey))
			{
				return true;
			}
			lsum += arr[l++];
		}
		else if (lsum < rsum) {
			lsum += arr[l++];
		}
		else {
			rsum += arr[r--];
		}
	}
	return false;
}

2.unordered_map版

bool canSplits_map(vci arr) 
{
	if (arr.size() < 7)
	{
		return false;
	}
	unordered_map <int, int> mymap;//1.预处理结构
	int sum = arr[0];//1.0
	for (int i = 1; i < arr.size(); i++)             //2.预处理 得到累加和
	{
		mymap.insert(make_pair(sum, i));
		sum += arr[i];                               //累加和计算
	}
	                                          
	int lsum = arr[0];                            //第一刀左侧的累加和
	for (int s1 = 1; s1 < arr.size() - 5; s1++) 
	   {
		int checkSum = lsum * 2 + arr[s1];        //3.s1第一刀的位置 从1开始试  第一刀不会过右的
		if (mymap.count(checkSum))            //第2刀
		{
			int s2 = mymap.find(checkSum)->second;                    
			checkSum += lsum + arr[s2];
			if (mymap.count(checkSum))
			{
				int s3 = mymap.find(checkSum)->second;
				if (checkSum + arr[s3] + lsum == sum)//第3刀和最后的累加和对上
				{
					return true;
				}
			}
		}
		lsum += arr[s1];
	}
	return false;
}

3.主程序调用

void canSplit_main() 
 {
	 cout << "***********canSplit_main**********" << endl;
	 vci vci1;
	 vci1.insert(vci1.begin(), { 3, 2, 4, 1, 4, 9, 5, 10, 1, 2, 2 });
	 cout << "arr[3, 2, 4, 1, 4, 9, 5, 10, 1, 2, 2]   canSplits_set  返回true---"  << canSplits_set(vci1) << endl;

	 cout << "arr[3, 2, 4, 1, 4, 9, 5, 10, 1, 2, 2]   canSplits_map  返回true---" << canSplits_map(vci1) << endl;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值