02-1. Reversing Linked List
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 33218Sample 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. 一元多项式求导
设计函数求一元多项式的导数。
输入格式:以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过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. 求前缀表达式的值
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如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;
}