《数据结构与算法分析:C语言描述》习题2.12

a.求数列 { A n } \{A_n\} {An}最小子序列和相当于求 { − A n } \{-A_n\} {An}最大子序列和。本题采用书中2.4.3节和算法3类似的算法。C语言代码如下:

#include<stdio.h>
#include<stdlib.h>

int MinSubSum(int* arr, int left, int right);//求数组的最小连续子列的和
int Min3(int a, int b, int c);//求这三者最小值

int main(void)
{
	int arr[] = {-14,-2,59,-11, 0,-1,2,-3 };
	int length = sizeof(arr) / sizeof(int);
	int left = 0;
	int right = length - 1;

	int MinSum = MinSubSum(arr, left, right);
	printf("%d\n", MinSum);

	return 0;
}

int MinSubSum(int* arr, int left, int right)
{
	if (left > right)
	{
		printf("输入错误!\n");
		exit(-1);
	}

	if (left == right)
		return arr[left];

	int mid = (left + right) / 2;
	int LeftMinSum = MinSubSum(arr, left, mid); //左半部分最小和
	int RightMinSum = MinSubSum(arr, mid + 1, right);//右半部分最小和

	/* 求中间部分最小和 相当于 求$\{-A_n\}$的中间部分的最大子序列和 */
	int i,temp;
	int negative_left_max, negative_right_max;

	temp = 0;
	negative_left_max = -arr[mid];
	for (i = mid ; i >= left; i--)
	{
		temp = temp - arr[i];
		if (temp > negative_left_max)
			negative_left_max = temp;
	}

	temp = 0;
	negative_right_max = -arr[mid + 1];
	for (i = mid + 1; i <= right; i++)
	{
		temp = temp - arr[i];
		if (temp > negative_right_max)
			negative_right_max = temp;
	}

	int MidMinSum = -(negative_left_max + negative_right_max);

	return Min3(LeftMinSum, RightMinSum, MidMinSum);


	
}

int Min3(int a, int b, int c)
{
	int min = a;
	if (b < min)
		min = b;
	if (c < min)
		min = c;

	return min;
}

b.求数列 { A n } \{A_n\} {An}最小正子序列和。如果 { A n } \{A_n\} {An}全为负数就返回0.
解题思路:
1 1 1.求出前n项和 S [ n ] S[n] S[n],其中 S [ 0 ] = 0 S[0]=0 S[0]=0
2 2 2.对 S [ n ] S[n] S[n]进行排序,计算 S [ i + 1 ] − S [ i ] S[i+1]-S[i] S[i+1]S[i]的的最小值(最小值一定出现在相邻项),并且位置要满足: p o s [ i + 1 ] > p o s [ i ] pos[i+1]>pos[i] pos[i+1]>pos[i],。
详细过程可以参考:参考链接.

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

typedef struct Node
{
	int sum; //用于记录前pos项和
	int pos;
}NODE,*PNODE;

int MinPositiveSubSum(int* arr, int length);//求出最小正子序列和
void QuickSort(PNODE count,int left, int right);//快速排序
int FindPos(PNODE count, int left, int right);//用于排快速排序中第一个元素

int main(void)
{
	int arr[] = { 4, 0, 4, -1, -1 };
	int length = sizeof(arr) / sizeof(int);

	int MinSum = MinPositiveSubSum(arr, length);

	printf("%d\n", MinSum);

	return 0;
}

int MinPositiveSubSum(int* arr, int length)
{
	//初始化
	PNODE count = (PNODE)malloc(sizeof(NODE) * length); 
	count[0].sum = 0;
	count[0].pos = 0;

	int i;
	for (i = 1; i <= length; i++)
	{
		count[i].pos = i;
		count[i].sum = count[i - 1].sum + arr[i-1];
	}
	QuickSort(count, 0, length);

	int MinSum = count[0 + 1].sum - count[0].sum;
	for (int i = 0; i < length; i++)
	{
		if (count[i].pos < count[i + 1].pos && count[i].sum < count[i + 1].sum)
		{
			if(MinSum> (count[i + 1].sum - count[i].sum))
				 MinSum = count[i + 1].sum - count[i].sum;
		}
	}

	return MinSum;
}

void QuickSort(PNODE count,int left,int right)
{
	if (left >= right)
		return;
	else
	{
		int pos = FindPos(count, left, right);
		QuickSort(count, left, pos - 1);
		QuickSort(count, pos + 1, right);
	}
}

int FindPos(PNODE count, int left, int right)
{
	if (left > right)
	{
		printf("2.输入错误!left=%d, right=%d\n", left, right);
		exit(-1);
	}

	if (left == right)
		return left;

	int temp_sum = count[left].sum;
	int temp_pos = count[left].pos;

	while (left < right)
	{
		while (left < right && temp_sum <= count[right].sum)
			right--;
		count[left].sum = count[right].sum;
		count[left].pos = count[right].pos;

		while (left<right && temp_sum >= count[left].sum)
			left++;
		count[right].sum = count[right].sum;
		count[right].pos = count[right].pos;
	}

	count[right].sum = temp_sum;
	count[right].pos = temp_pos;
	return right;
}

c.求数列 { A n } \{A_n\} {An}最大子序列乘积 两个 f o r for for循环暴力计算。C语言代码如下:

#include<stdio.h>
#include<malloc.h>

int MaxSubProduct(int* arr, int length);//输入数组及其长度

int main(void)
{
	int arr[] = { 1,2,-3,4,0,5,-6,7,8 };
	int length = sizeof(arr) / sizeof(int);
	int answer = MaxSubProduct(arr, length);
	printf("最大子序列的乘积为:%d\n", answer);

	return 0;
}

int MaxSubProduct(int* arr, int length)
{
	int temp_product = 1;
	int product = arr[0];

	for (int f = 0; f < length; f++)
	{
		temp_product = 1;
		for (int r = f; r < length; r++)
		{
			temp_product = temp_product * arr[r];
			if (temp_product > product)
				product = temp_product;
		}
	}

	return product;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值