数据结构(陈越)PAT练习题 第二周:线性结构

02-1. Reversing Linked List

时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CHEN, Yue

Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K = 3, then you must output 3→2→1→6→5→4; if K = 4, you must output 4→3→2→1→5→6.

Input Specification:

Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (<= 105) which is the total number of nodes, and a positive K (<=N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Data Next

where Address is the position of the node, Data is an integer, and Next is the position of the next node.

Output Specification:

For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

看到这一题,比较容易想到的是构建一个结构数组,每个元素存放 Address Data Next 这三个信息。由于输入的数据节点并不是按顺序来的,所以需要根据输入数据,把”链表“从头到尾排好序。即,数组的第一个位置代表第一个节点,第二个位置代表第二个节点,依次类推。输入的数据中有些是无效的节点,因此需要额外的操作把这些无效的节点去掉,其实只要修改数组的”有效长度“即可。最后再要根据题意要求,把前k个节点反向排列。当然也并不需要真的把前k个节点进行重排序的操作,只把它们倒序输出就可以了,这样可以减少程序的运行时间。

似乎这道题就这样完成了,但是!但是,测试点中有一组大数据,只要像这样进行排序或者数组元素移动等操作,必定会超时。在我走投无路的时候,出现了一位大神,这里要感谢 Maples7 童鞋提供的方法,构建一个数组来模拟内存中的地址,在这个”模拟内存“中存放Data和Next数据,这也正是姥姥最后给出的答案。这种解法的时间复杂度只有O(n)。原文链接在这里:http://www.cnblogs.com/maples7/p/4153984.html

我基本上是照搬他的代码通过的(惭愧 T_T...),下面是我的代码:

#include<iostream>
using namespace std;

const int ADDRMAX = 100000;

struct ansNode
{
	int addr, data;
};

int main()
{
	int n, k, i, j, block, rest, top=0;
	int start, temp;

	cin >> start >> n >> k;

	int* data = new int [ADDRMAX];
	int* next = new int [ADDRMAX];

	ansNode* ans = new ansNode [n+1];

	for( i=0; i<n; ++i )
	{
		cin >> temp;
		cin >> data[temp] >> next[temp];
	}

	while( start!=-1 )
	{
		ans[top].data = data[start];
		ans[top].addr = start;
		start = next[start];
		++top;
	}
	n = top;

	block = n/k;
	rest = n%k;
	cout.fill('0');
	for( j=0; j<block; ++j )
	{
		for( i=(j+1)*k-1; i>j*k; --i )
		{
			cout.width(5);
			cout << ans[i].addr << ' ' << ans[i].data << ' ';
			cout.width(5);
			cout << ans[i-1].addr << endl;
		}
		cout.width(5);	cout << ans[i].addr << ' ' << ans[i].data << ' ';
		if( rest==0 )
		{
			if( j==block-1 )
				cout << "-1";
			else
			{
				cout.width(5);	cout << ans[(j+2)*k-1].addr;
			}
		}
		else
		{
			if( j==block-1 )
			{
				cout.width(5); cout << ans[(j+1)*k].addr;
			}
			else
			{
				cout.width(5); cout << ans[(j+2)*k-1].addr;
			}
		}
		cout << endl;
	}
	if( rest!=0 )
	{
		for( i=block*k; i<n-1; ++i )
		{
			cout.width(5);
			cout << ans[i].addr << ' ' << ans[i].data << ' ';
			cout.width(5);
			cout << ans[i+1].addr << endl;
		}
		cout.width(5);
		cout << ans[i].addr << ' ' << ans[i].data << " -1\n";
	}

	delete [] data;
	delete [] next;
	delete [] ans;
	return 0;
}

02-2. 一元多项式求导

时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard

设计函数求一元多项式的导数。

输入格式:以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是0,但是表示为“0 0”。

输入样例:
3 4 -5 2 6 1 -2 0
输出样例:
12 3 -10 1 6 0

这一题比较简单。对于某一项axn(n>0),求导之后结果为anxn-1;而当n=0时,即常数项,求导结果为0,系数也为0,而不是-1。我这里并没有把求导结果保存下来,而是将其直接输出。对于输入数据,虽然没有预先给出有多少项,不过似乎都是以0次项结束的,因为我正是这样做的,而且都通过了。下面是完整的代码:

#include<iostream>
using namespace std;

struct term
{
	int coef;
	int expon;
	term* next;
};

int main()
{
	term head, *link;
	cin >> head.coef >> head.expon;
	link = &head;
	while( link->expon!=0 )
	{
		link->next = new term;
		link = link->next;
		cin >> link->coef >> link->expon;
	}
	link->next = nullptr;

	//边求导边输出
	link = &head;
	if( link->expon==0 )	//零多项式
	{
		cout << "0 0";
	}
	else
	{
		cout << link->coef*link->expon << ' ' << link->expon-1;
		while( link->next )
		{
			link = link->next;
			if( link->expon==0 )
				break;
			cout << ' ' << link->coef*link->expon << ' ' << link->expon-1;
		}
	}
	return 0;
}

02-3. 求前缀表达式的值

时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。

输入格式说明:

输入在一行内给出不超过30个字符的前缀表达式,只包含+、-、*、\以及运算数,不同对象(运算数、运算符号)之间以空格分隔。

输出格式说明:

输出前缀表达式的运算结果,精确到小数点后1位,或错误信息“ERROR”。

样例输入与输出:

序号 输入 输出
1
+ + 2 * 3 - 7 4 / 8 4
13.0
2
/ -25 + * - 2 3 4 / 8 4
12.5
3
/ 5 + * - 2 3 4 / 8 2
ERROR
4
+10.23
10.2

对于前缀表达式,计算符号在两个元素的前面,如 + a b ,表示a+b,其中a和b是两个数。当有多个前缀表达式嵌套时,a和b则有可能是其它表达式的计算结果。例如 + a b 的实际形式可能为 + * 3 4 2 ,这时 a 即 * 3 4,b为2。因此,对于前缀表达式,很自然会想到可以用递归方法来实现。需要注意的是,对于除法运算,可能会遇到除数为0的情况,这时需要输出”ERROR“。下面是完整的代码:

#include <iostream>
#include <string>
#include <sstream>
#include <stdlib.h>
using namespace std;

float getOp()
{
	string str;
	cin >> str;
	if( str=="+") 
	{
		return getOp() + getOp();
	}
	else if( str=="-" )
	{
		return getOp() - getOp();
	}
	else if( str=="*" )
	{
		return getOp() * getOp();
	}
	else if( str=="/" )
	{
		float a, b;
		a = getOp();
		b = getOp();
		if( b<1e-6 && b>-1e-6 )
		{
			cout << "ERROR";
			exit( 0 );
		}
		else
			return a/b;
	}
	else
	{
		float a;
		istringstream istr;
		istr.str( str );
		istr >> a;
		return a;
	}
}

int main()
{
	cout.setf(ios::fixed);
	cout.precision(1);
	cout << getOp();
	return 0;
}


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值