数据结构_第一周编程作业_C++题解

DS_Lecture 1 Assignments_C++题解

中国大学MOOC_陈越、何钦铭_数据结构_第一周编程作业

1. 最大子列和问题

本次课最后讲到的4种算法的实验题,属于基本要求,必做

算法2_双层循环

#include<cstdio>
using namespace std;
int main()
{
	int n;
	scanf("%d",&n);
	int *data = new int[n];
	for (int i = 0; i < n; i++){
		scanf("%d",&data[i]);
	}
	int maxsum = 0;
	for (int i = 0; i < n; i++){
		int subseqsum = 0;
		for (int j = i; j < n; j++){
			subseqsum += data[j];
			if (subseqsum > maxsum) maxsum = subseqsum;
		}
	}
	printf("%d",maxsum);
	return 0;
}

时间复杂度:\(O(n^2)\)

算法3_分治法

#include<cstdio>
using namespace std;

int max3(int A, int B, int C){
	return A > B ? (A > C ? A : C) : (B > C ? B : C);
}

int DivideAndConquer(int* data, int left, int right)
{
	if (left == right){
		if (data[left] > 0)	return data[left];
		else return 0;
	}
	
	int center = (left + right) / 2;
	int leftmaxsum = DivideAndConquer(data, left, center);
	int rightmaxsum = DivideAndConquer(data, center+1, right);
	
	int leftmaxbordersum = 0; int leftbordersum = 0;
	for (int i = center; i >= left; i--){
		leftbordersum += data[i];
		if (leftbordersum > leftmaxbordersum) leftmaxbordersum = leftbordersum;
	}
	int rightmaxbordersum = 0; int rightbordersum = 0;
	for (int i = center+1; i <= right; i++){
		rightbordersum += data[i];
		if (rightbordersum > rightmaxbordersum) rightmaxbordersum = rightbordersum;
	}
	
	return max3(leftmaxsum, rightmaxsum, leftmaxbordersum + rightmaxbordersum);
}

int main()
{
	int n;
	scanf("%d",&n);
	int *data = new int[n];
	for (int i = 0; i < n; i++){
		scanf("%d",&data[i]);
	}
	int maxsum = DivideAndConquer(data, 0, n-1);
	printf("%d",maxsum);
	return 0;
}

时间复杂度:\(O(n\log n)\)

注意递归的写法

算法4_在线处理

#include<cstdio>
using namespace std;
int main()
{
	int n;
	scanf("%d",&n);
	int *data = new int[n];
	int maxsum = 0;
	int subseqsum = 0;
	for (int i = 0; i < n; i++){
		scanf("%d",&data[i]);
		subseqsum += data[i];
		if (subseqsum > maxsum) maxsum = subseqsum;
		if (subseqsum < 0) subseqsum = 0;
	}
	printf("%d",maxsum);
	return 0;
}

时间复杂度:\(O(n)\)

当前子列和为负时清零,因为必然对后面的和没有正的贡献

2. PAT(A) 1007 Maximum Subsequence Sum

2004年浙江大学计算机专业考研复试真题,是本次课最后讲到的算法的改造,要求略高,选做。

#include<cstdio>
using namespace std;
int main()
{
	int n;
	scanf("%d",&n);
	int *data = new int[n];
	int maxsum = -1;
	int subseqsum = 0;
	int maxleft = 0; int maxright = n-1;
	int left = 0; int right = 0;
	for (int i = 0; i < n; i++){
		scanf("%d",&data[i]);
		subseqsum += data[i];
		right = i;
		if (subseqsum > maxsum){
			maxsum = subseqsum;
			maxleft = left;
			maxright = right;
		}
		if (subseqsum < 0){
			subseqsum = 0;
			left = i + 1;
		}
	}
	printf("%d %d %d", maxsum<0 ? 0 : maxsum, data[maxleft], data[maxright]);
	return 0;
}
  • 时间复杂度:\(O(n)\)
  • 测试点:负数和零=》maxsum不能初始化为0,而应初始化为负数
  • 由于最后要给出子列的起始坐标,用leftright记录,每当maxsum更新时,maxleftmaxright也跟着更新

3. 二分查找

Position BinarySearch( List L, ElementType X ){
	int left = 1; int right = L->Last;
	while(left <= right){
		int mid = (left + right) / 2;
		if (L->Data[mid] == X) return mid;
		if (L->Data[mid] < X) left = mid + 1;
		else right = mid - 1;
	}
	return NotFound;
}
posted @ 2019-04-15 20:47  鲸90830  阅读(329)  评论(0)    收藏  举报