PAT (Advanced Level) Practice 1009 Product of Polynomials 多项式相乘

一、概述

输入两个多项式,输出它们的乘积。

有两种思路:

其一是时间复杂度较低,根据输入的多项式的系数最高为1000,那么选用长度为2000的数组存储结果可以使时间复杂度为O(n)。

其二是空间复杂度较低,根据输入的项数最多为10,则输出的项数最多为100,选用长度为100的数组储存结果。但是这会造成一个问题,虽然长度为100,但是并不是按次数由高到低的顺序存储的,还需要再对结果进行排序,因此时间复杂度为O(n^2)。

我当时选择了思路二,算是石乐志,当时是这样想的:

思路一需要长度为2000,多遍历几次那时间可就没个准了,还会多耗费那么多空间。辣鸡。

思路二就是手算多项式的想法,直观易懂还好写。但是当时没想到顺序问题,于是在检查点3那里卡壳很久。

二、分析

先以我的思路二为例。思路一的代码全网都是,也就说说罢了。虽然我这个蠢得不行,但写出来就要对代码负责啊。

1、输入

新建三个二维数组存储输入和输出的多项式。数组没法选一行int一行float,那么只能选全部float,之后才发现可以用结构体来实现两行不一样。像如下所示:

struct Poly{
    int exp;
    double cof;
}poly[1001];

这样就是一个结构数组了,十分方便。当然我的也可以用,只是在格式化输出时指数的输出不能用%d,而是要用%.0f。这一点要注意。

2、计算

计算就是按第二个多项式的第一项分别乘第一个多项式的所有项,指数相加系数相乘,然后在结果多项式中从头遍历,如果遇到指数相同的,加上去,如果没有系数相同的,那么就新建一项。

这个方法得到的结果只在第二个多项式只有一项或者有两项但是一项是常数的时候结果才是有序的。

关键问题就在于,oj上五个检查点,有四个都是满足的。只有一个检查点3不满足。这可就蛋疼了,我一直以为是有关0的问题没有处理好,不然这么大的bug怎么只有一个检查点没过呢?后来自己选了一个长一点的多项式,才发现了错误所在。所以对于这种测试一次要输入很多数据的题目,想找到一个bug真的是蛮麻烦,加之思维定式没有想到顺序问题,就出现了这种情况。

for (i = 0; i < Acount; i++)
	{
		for (j = 0; j < Bcount; j++)
		{
			res = A[0][i] + B[0][j];
			for (k = 0; k < Ccount; k++)
			{
				if (C[0][k] == res)
				{
					C[1][k] += A[1][i] * B[1][j];
					break;
				}
			}
			if (k == Ccount)
			{
				C[0][k] = res;
				C[1][k] = A[1][i] * B[1][j];
				Ccount++;
			}
		}
	}

3、排序

最后我发现,要想拯救我这破算法,只好在最后加一个排序了,随便写个冒泡就行,毕竟上面的算法已经到了O(n^2)的地步,你再怎么优化也没什么卵子用了。

4、输出

我说两点:

一是小数保留一位,别想得太多,如:如何四舍五入,2.16是输出2.1还是2.2,你会发现输出2.1是对的;如果结果只有零是输出1 0 0还是0 0 0还是0还是1,仔细想想发现应该输出0,这不是废话,第一个数代表结果项数,全是0项数肯定是0,0作为系数不用输出。

二是对于float的格式化输出,.0f和.1f的应用十分方便。

三、总结

这代码写的真鸡儿丢人,除了空闲空间较少以外毫无优点,冗长且效率低,需要继续学习啊。

代码如下:

#include<stdio.h>
int main()
{
	float A[2][11] = { 0 }, B[2][11] = { 0 }, C[2][101] = { 0 };
	int Acount, Bcount;
	scanf("%d", &Acount);
	int i;
	for (i = 0; i < Acount; i++)
	{
		float N, aN;
		scanf("%f%f", &N, &aN);
		A[0][i] = N;
		A[1][i] = aN;
	}
	scanf("%d", &Bcount);
	for (i = 0; i < Bcount; i++)
	{
		float N, bN;
		scanf("%f%f", &N, &bN);
		B[0][i] = N;
		B[1][i] = bN;
	}
	int j, k;
	int Ccount = 0;
	float res = 0;
	for (i = 0; i < Acount; i++)
	{
		for (j = 0; j < Bcount; j++)
		{
			res = A[0][i] + B[0][j];
			for (k = 0; k < Ccount; k++)
			{
				if (C[0][k] == res)
				{
					C[1][k] += A[1][i] * B[1][j];
					break;
				}
			}
			if (k == Ccount)
			{
				C[0][k] = res;
				C[1][k] = A[1][i] * B[1][j];
				Ccount++;
			}
		}
	}
	int num = 0;
	for (i = 0; i < Ccount; i++)
		if (C[1][i] != 0)
			num++;
	printf("%d", num);
	float min1, min2;
	int minnum;
	for (i = Ccount-1; i >= 0; i--)
	{
		min1 = 2001;
		min2 = 0;
		minnum = 0;
		for (j = 0; j < i+1; j++)
		{
			if (C[0][j] < min1)
			{
				min1 = C[0][j];
				minnum = j;
			}
		}
		min2 = C[1][minnum];
		C[0][minnum] = C[0][i];
		C[1][minnum] = C[1][i];
		C[0][i] = min1;
		C[1][i] = min2;
	}
	if (num == 0)
		;
	else
		for (i = 0; i < Ccount; i++)
		{
			if (C[1][i] != 0)
				printf(" %.0f %.1f", C[0][i], C[1][i]);
		}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值