序列平衡点

题目一:

一个序列的平衡点是这样的,它的左边的所有的元素的和应该等于右边的所有的元素的和,比如在下面的序列A:

A[0] = -7 A[1] = 1 A[2] = 5 A[3] = 2 A[4] = -4 A[5] = 3 A[6] = 0

3是一个平衡点因为:

  • A[0] + A[1] + A[2] = A[4] + A[5] + A[6]

6也是一个平衡点因为:

  • A[0] + A[1] + A[2] + A[3] + A[4] + A[5] = 0

(零个元素的和是零) 索引7不是平衡点,因为它不是序列A的有效索引。

如果你仍然不是很清楚,那么这里给出了明确的定义:0 ≤ k < n 并且 sum[i=0]k-1 A[i] =sum[i=k+1]n-1 A[i]。时, 整数k是序列A[0], A[1], ..., A[n−1] 的平衡点,这里我们假定零个元素的和为零。

请写一个函数

int solution(vector<int> &A);

返回给定序列的平衡点(任意一个)如果没有平衡点则返回−1,假设这个序列可达到非常大。

假定:

  • N 是 [0..100,000] 内的 整数;
  • 数组 A 每个元素是取值范围 [−2,147,483,648..2,147,483,647] 内的 整数 .

复杂度:

  • 最坏-情况下,期望的时间复杂度是 O(N);
  • 最坏-情况下,期望的空间复杂度是 O(N), 输入存储除外 (不计输入参数所需的存储空间).

输入数组中的元素可以修改.

代码如下:

#include <iostream>
#include <vector>
using namespace std;

int solution(vector<int>& A) {
	if (A.size() == 1) return 0;
	if (A.size() == 0) return -1;

	int left_sum = 0, right_sum = 0;

	for (size_t i = 1; i < A.size(); i++) {
		right_sum += A[i];
	}

	if (left_sum == right_sum) return 0;

	for (size_t i = 1; i < A.size(); i++) {
		left_sum += A[i-1];
		right_sum -= A[i];
		if (left_sum == right_sum) {
			return i;
		}
	}
	return -1;
}

int main() {
	size_t n;
	int val;
	vector<int> A;
	while (cin >> n) {
		for (size_t i = 0; i < n; i++) {
			cin >> val;
			A.push_back(val);
			cout << solution(A) << endl;
		}
		A.clear();
	}
	return 0;
}

变形

题目二:

给定一个元素个数至少为5的正整数数组,两个索引将数组分为三段(其中索引指定的元素不计算在段内),并且每段都至少有一个元素。求是否有这样的索引对使得这三段元素中每段之和都相等。若存在这样索引对,则返回1,否则返回0。


#include <iostream>
#include <vector>
using namespace std;

int solution(vector<int>& A) {
	size_t N = A.size();
	if (N < 5) return 0;
	int left_sum = A[0];
	int middle_sum = 0;
	int right_sum = A[N-1];
	size_t head = 1;
	size_t tail = N-2;

	for (size_t i = 2; i < N-2; i++) {
		middle_sum += A[i];
	}

	while (head < tail - 1) {
		if (left_sum  == right_sum) {
			if (left_sum == middle_sum) {
				return 1;
			}
		} else if (left_sum < right_sum) {	
			middle_sum -= A[head-1];
			left_sum += A[head++];
		} else {
			middle_sum -= A[tail-1];
			right_sum += A[tail--];
		}
	}
	return 0;
}

int main() {
	int n;
	int val;
	vector<int> A;
	while (cin >> n) {
		for (size_t i = 0; i < n; i++) {
			cin >> val;
			A.push_back(val);
		}
		cout << solution(A) << endl;
		A.clear();
	}
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值