1. 高精度数加法
高精度数是指大大超出了标准数据类型能表示的范围的数,例如10000位整数。很多计算问题的结果都很大,因此,高精度数极其重要。
一般使用一个数组来存储高精度数的所有数位,数组中的每个元素存储该高精度数的1位数字或多位数字。
请尝试计算:N个高精度数的加和。这个任务对于在学习数据结构的你来说应该是小菜一碟。
。输入格式:
第1行,1个整数N,表示高精度整数的个数,(1≤N≤10000)。
第2至N+1行,每行1个高精度整数x, x最多100位。
输出格式:
1行,1个高精度整数,表示输入的N个高精度数的加和。
代码长度限制-16 KB
时间限制-100 ms
内存限制-1 MB
完整代码:
利用字符数组存储高精度数,两数相加看成一个新的加数再与另一个数相加,如此循环下去,需要注意的是进位的处理。
这里为了方便先将字符串反序求得结果再返回来
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
char a[1000], b[1000], c[1000];
//利用y对字符串x反序
void turn(char x[], char y[])
{
int len, i, j;
len = strlen(x);
j = len - 1;
for (i = 0; i < len; i++)
{
y[i] = x[j];
j--;
}
y[len] = '\0';
strcpy(x, y);
}
int main()
{
int i, lena, lenb;
//加数和与进位
int sum = 0, up = 0;
int n;
scanf("%d", &n);
//第一个加数
cin >> a;
//只有一个加数时
if (n == 1)
{
cout << a;
return 0;
}
//循环,每次两个数相加
for (int k = 1; k < n; k++)
{
//第二个加数
cin >> b;
//因为要从后往前计算,所以将字符串反序方便进位操作
turn(a, c);
turn(b, c);
lena = strlen(a); lenb = strlen(b);
//处理和和进位
for (i = 0; i < lena && i < lenb; i++)
{
sum = up + (a[i] - '0') + (b[i] - '0');
if (sum >= 10)
{
up = 1;
sum -= 10;
}
else up = 0;
//用c保存a与b相加的结果,赋值给a方便继续操作
c[i] = sum + '0';
}
if (lena > lenb)
{
for (; i < lena; i++)
{
sum = a[i] + up - '0';
if (sum >= 10)
{
up = 1;
sum -= 10;
}
else up = 0;
c[i] = sum + '0';
}
}
if (lenb > lena)
{
for (; i < lenb; i++)
{
sum = b[i] + up - '0';
if (sum >= 10)
{
up = 1;
sum -= 10;
}
else up = 0;
c[i] = sum + '0';
}
}
if (up == 1) c[i++] = '1';
up = 0;
c[i] = '\0';
//清空方便进入下一次循环
memset(a, 0, sizeof(char) * 1000);
memset(b, 0, sizeof(char) * 1000);
//将最终结果c反序成正确的顺序
turn(c, a);
//看成一个新的加数,再次循环
strcpy(a, c);
}
cout << c;
return 0;
}
2.二叉树的最长路径
给定一棵二叉树T,求T中的最长路径的长度,并输出此路径上各结点的值。若有多条最长路径,输出最右侧的那条。
输入格式:
第1行,1个整数n,表示二叉树有n个结点, 1≤n≤100000.
第2行,2n+1个整数,用空格分隔,表示T的扩展先根序列, -1表示空指针,结点用编号1到n表示。
输出格式:
第1行,1个整数length,length表示T中的最长路径的长度。
第2行,length+1个整数,用空格分隔,表示最右侧的最长路径。
代码长度限制-16 KB
时间限制-100 ms
内存限制-5 MB
完整代码:
扩展先根遍历创建二叉树以及求深度算法课上都讲过,比较基础一定要会。
输出具体路径时类比先根遍历,依据“根右左”顺序遍历,当找到一个叶子结点的时候判断高度与最大高度是否相同即可
题目有一定难度,代码还要多看
#include<iostream>
#include<cstdio>
using namespace std;
//树的结点
typedef struct node
{
int data;
struct node* left;
struct node* right;
} TreeNode, * Tree;
//扩展先根序列建立二叉树
void creat(Tree& T)
{
int ch;
cin >> ch;
if (ch == -1) T = NULL;
else
{
T = new TreeNode;
T->data = ch;
//递归建树,算法之前写过直接copy
creat(T->left);
creat(T->right);
}
}
//求树的深度,算法之前写过
int depth(Tree T)
{
if (T == NULL)
return 0;
else
{
//递归,一个树的深度就是左右子树中大的一个+1
int m = depth(T->left);
int n = depth(T->right);
if (m > n) return (m + 1);
else return (n + 1);
}
}
//输出最长路径
//大概思路是向先根遍历一样根右左遍历并将结点存在数组中,如果有一条恰好是最长路径则输出
void printpath(Tree T, int path[], int pathlen, int d)
{
int i;
if (T != NULL)
{
//记录当前路径,一棵树的根节点
path[pathlen] = T->data;
//递归出口,只要找到叶子结点向上只有一条路,判断是否最长即可
if (T->left == NULL && T->right == NULL)
{
if (pathlen == d - 1)
{
for (i = 0; i <= pathlen; i++)
{
if (i == 0)
cout << path[i];
else cout << " " << path[i];
}
cout << endl;
exit(0);
}
}
//递归,一路向右找到最深处再往上遍历,右子树没有再找左子树
else
{
printpath(T->right, path, pathlen + 1, d);
printpath(T->left, path, pathlen + 1, d);
}
}
}
int main()
{
int n;
cin >> n;
Tree T;
//扩展先根序列建树
creat(T);
//求长度,先求深度然后长度是深度-1
int d = depth(T);
cout << d - 1 << endl;
//寻找最长路径保存在数组中,pathlen记录下标
int path[100001];
int pathlen = 0;
printpath(T, path, pathlen, d);
}
3. 稀疏矩阵之和
矩阵A和B都是稀疏矩阵。请计算矩阵的和A+B.如果A、B不能做和,输出“Illegal!”
输入格式:
矩阵的输入采用三元组表示,先A后B。对每个矩阵:
第1行,3个整数N、M、t,用空格分隔,分别表示矩阵的行数、列数和非0数据项数,10≤N、M≤50000,t≤min(N,M).
第2至t+1行,每行3个整数r、c、v,用空格分隔,表示矩阵r行c列的位置是非0数据项v, v在32位有符号整型范围内。三元组默认按行列排序。
输出格式:
矩阵A+B,采用三元组表示,默认按行列排序,非零项也在32位有符号整型范围内。
代码长度限制-16 KB
时间限制-100 ms
内存限制-10 MB
完整代码:
不算特别难,情况比较复杂要仔细一点写
#include<iostream>
#include<stdio.h>
#include<malloc.h>
#define MAX 60000
using namespace std;
//矩阵中的一个整数信息
struct node {
int r, c, v;
};
//一个矩阵
typedef struct {
int rs, cs, num;
struct node data[MAX];
}Matrix;
//求两矩阵之和
void MatAdd(Matrix a, Matrix b, Matrix* c) {
int i = 0, j = 0;
int temp;
int va, vb, vc;
//矩阵行数或列数不相等
if (a.rs != b.rs || a.cs != b.cs) { printf("Illegal!"); exit(0); }
//结果矩阵的行数和列数与A,B相同
c->rs = a.rs;
c->cs = a.cs;
c->num = 0;
while (i < a.num && j < b.num)
{
//同一位置的数作和
if (a.data[i].r == b.data[j].r && a.data[i].c == b.data[j].c)
{
temp = a.data[i].v + b.data[j].v;
if (temp)
{
c->data[c->num].r = a.data[i].r;
c->data[c->num].c = a.data[i].c;
c->data[c->num++].v = temp;
}
i++; j++;
}
//A比B位置小
if ((a.data[i].r == b.data[j].r && a.data[i].c < b.data[j].c) || a.data[i].r < b.data[j].r)
{
c->data[c->num].r = a.data[i].r;
c->data[c->num].c = a.data[i].c;
c->data[c->num++].v = a.data[i].v;
i++;
}
//A比B位置大
if ((a.data[i].r == b.data[j].r && a.data[i].c > b.data[j].c) || a.data[i].r > b.data[j].r)
{
c->data[c->num].r = b.data[j].r;
c->data[c->num].c = b.data[j].c;
c->data[c->num++].v = b.data[j].v;
j++;
}
}
while (i < a.num)
{
c->data[c->num].r = a.data[i].r;
c->data[c->num].c = a.data[i].c;
c->data[c->num++].v = a.data[i].v;
i++;
}
while (j < b.num)
{
c->data[c->num].r = b.data[j].r;
c->data[c->num].c = b.data[j].c;
c->data[c->num++].v = b.data[j].v;
j++;
}
}
int main() {
//保存三个矩阵,分别是A,B,A+B的和C
Matrix* a, * b, * c;
a = (Matrix*)malloc(sizeof(Matrix));
b = (Matrix*)malloc(sizeof(Matrix));
c = (Matrix*)malloc(sizeof(Matrix));
scanf("%d%d%d", &a->rs, &a->cs, &a->num);
int i;
for (i = 0; i < a->num; i++)
{
scanf("%d%d%d", &a->data[i].r, &a->data[i].c, &a->data[i].v);
}
scanf("%d%d%d", &b->rs, &b->cs, &b->num);
for (i = 0; i < b->num; i++)
{
scanf("%d%d%d", &b->data[i].r, &b->data[i].c, &b->data[i].v);
}
//求和
MatAdd(*a, *b, c);
//输出最终结果
printf("%d %d %d\n", c->rs, c->cs, c->num);
for (i = 0; i < c->num; i++)
{
printf("%d %d %d\n", c->data[i].r, c->data[i].c, c->data[i].v);
}
return 0;
}
4. 序列调度
有一个N个数的序列A:1,2,……,N。有一个后进先出容器D,容器的容量为C。如果给出一个由1到N组成的序列,那么可否由A使用容器D的插入和删除操作得到。
输入格式:
第1行,2个整数T和C,空格分隔,分别表示询问的组数和容器的容量,1≤T≤10,1≤C≤N。
第2到T+1行,每行的第1个整数N,表示序列的元素数,1≤N≤10000。接下来N个整数,表示询问的序列。
输出格式:
T行。若第i组的序列能得到,第i行输出Yes;否则,第i行输出No,1≤i≤T。
代码长度限制-16 KB
时间限制-100 ms
内存限制-10 MB
完整代码:
先入栈,如果栈顶元素小于序列元素->下一个进栈继续比较;如果栈顶元素等于序列元素->弹栈,下一个进栈继续比较;如果栈顶元素大于序列元素->输出No
#include<iostream>
#include<stack>
#define maxsize 10005
using namespace std;
int main()
{
int flag;
stack<int>t;
int data[maxsize];
int T, C, N, x;
int k,i,j;
//组数和容器容量
cin >> T >> C;
for (k = 1; k <= T; k++)
{
//每一组的元素个数与序列
cin >> N;
flag = 1;
for (i = 1; i <= N; i++)
cin >> data[i];
i = 1;
//清空栈,方便下一轮循环时使用
while (!t.empty())
t.pop();
for (j = 1; j <= N; j++)
{
//栈顶元素等于序列,弹出后继续
if (!t.empty() && t.top() == data[j])
{
t.pop();
continue;
}
//栈顶元素大于序列
if (i > data[j]) {
flag = 0;
printf("No\n");
break;
}
//栈顶元素小于序列一直进栈
for (; i <= data[j]; i++) t.push(i);
if (t.size() > C) {
flag = 0;
printf("No\n");
break;
}
//最后必将i=data[j],要弹出
t.pop();
}
if (flag)
printf("Yes\n");
}
return 0;
}