大一下 校软 数据结构 考核题
1. 求末尾四位数字
给定100个数,求出他们乘积结果的后四位结果
5686 8908 4406 2759 8710 4788 6244 4549 6609 2609
3791 6932 7496 7447 2646 6244 1280 3913 6869 2344
1928 7182 7100 1456 3277 8958 5297 9750 1513 4649
8814 7580 1324 4880 3639 3640 6433 1211 6401 8966
9369 7901 2279 5865 8821 5900 9620 7735 9515 3542
4819 6319 6162 6211 8655 2114 6053 1898 9331 6524
6878 1763 9347 4327 7092 2770 6588 1431 2657 8627
4027 2153 5821 4444 8013 9967 8500 6007 3384 6008
4141 2834 3939 6509 5209 7466 2027 8762 7672 7180
8789 4476 4607 2365 4044 1129 5630 1115 8290 2618
你需要提交你的计算代码,使之通过编译/解释后可以得到答案。
相似题目: 人见人爱A^B
#include <bits/stdc++.h>
using namespace std;
int main(){
//freopen("data.in","r",stdin);
long long sum = 1,a , n = 10;
for(int i = 0;i < n; ++i){
for(int j = 0;j < n; ++j){
cin>>a;
sum *= a;
sum %= 10000;
}
}
cout<<sum<<endl;
return 0;
}
因为只需要后 四位的结果,所以 对 每次计算的结果 % 10000 就可以了
只有后四位的值 才会 对最终的结果产生影响,前几位的都不重要。
最终的结果为 0 ;(因为当乘到 2,2的值7100 时,答案为 17040000 ,这个数字的后四位为 0
2.不同路径 (有障碍版本)
原题 + 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
相似题目:NOIP2002过河卒 (解题的思路是一样的)
#include <bits/stdc++.h>
using namespace std;
const int N = 200;
bool pd[N][N];
int vis[N][N];
int main(){
int n , m;
cin>>n>>m;
for(int i = 0;i < n; ++i){
for(int j = 0;j < m; ++j){
cin>>pd[i][j];
}
}
for(int i = 0;i < n; ++i){
for(int j = 0;j < m; ++j){
if(i == 0 || j == 0) vis[i][j] = 1;
if(pd[i][j] == 1) vis[i][j] = 0;
}
}
for(int i = 1;i < n; ++i){
for(int j = 1;j < m; ++j){
vis[i][j] = vis[i-1][j] + vis[i][j-1];
if(pd[i][j] == 1) vis[i][j] = 0;
}
}
cout<<vis[n-1][m-1];
return 0;
}
考虑网格中没有障碍的问题
那么对于 vis[i , j] 来说 ,他的答案一定是由 vis[i-1 , j] 和 vis[i , j-1] 相加得来的
即 vis[i , j] == vis[i-1 , j] + vis[i , j-1]
(因为只能向下 或 向右,所以对于 vis[i , j] 来说,是由 vis[i - 1 , j] 向下走 或 vis[i , j - 1] 向右走得到的)
考虑 特殊情况 在 每张地图的第 0 行 ,假如一直向右走,也就是 j++ ,那么对于第0行的每一个元素来说
它的值 只能被 前一个(左边的值) 更新 ,所以 第 0 行的 值 全为 0
同理 ,第 0 列 ,假如一直向下走, 也就是 i++,那么 第 0 列 的值 全为 0
for(int i = 0;i < n; ++i) vis[i][0] = 1; for(int j = 0;j < n; ++j) vis[0][j] = 1;
所以这个简单的问题就 迎刃而解了,只需要双重循环 求 vis[i , j] ,输出 vis[i-1,j-1] 就ok了
考虑目前这个问题,就是加了一个障碍,使得,原先可以由“障碍”这个点拓展的答案都不了用,即都为 0
那么问题也就简单了,只需要把 “障碍”这个点置为 0 就ok了鸭~,
for(int i = 0;i < n; ++i){ for(int j = 0;j < m; ++j){ if(i == 0 || j == 0) vis[i][j] = 1; if(pd[i][j] == 1) vis[i][j] = 0; // 这次置0是为了防止 障碍出现在 第0行 // 和第 0 列 } } for(int i = 1;i < n; ++i){ for(int j = 1;j < m; ++j){ vis[i][j] = vis[i-1][j] + vis[i][j-1]; if(pd[i][j] == 1) vis[i][j] = 0; // 这次置0是为了防止,障碍被赋值 } }
3. 写出二叉树的遍历(7种,视情况给分)
要求,从键盘以前序遍历输入这个二叉树,保证所给节点数不会多于26
当输入一个大写字母时,表示该节点value为该大写字母
当输入一个#时,表示该节点为空
比如 输入 ABC##D##EF##G## 表示一个前序遍历为ABCDEF的三层满二叉树
(7种遍历分别指的是 前中后 的 递归与非递归写法,还有一个层序遍历)
二叉树的建立---建议参考《大话数据结构》 (这本书上也有)
- 二叉树的建立(先序遍历的方式)
char ch;
struct binaryTree{
char val;
binaryTree *lchild,*rchild;
binaryTree():lchild(NULL),rchild(NULL){}
};
typedef binaryTree* tree; // 类型替换 binaryTree* 替换成 tree ,写着舒服
tree root = new binaryTree;//定义 根节点
void creatTree(tree &bt){//以先序遍历的递归方式 创建 树
cin>>ch;
if(ch == '#') {
bt = NULL;
}
else {
bt = new binaryTree;
bt->val = ch;
creatTree(bt->lchild);
creatTree(bt->rchild);
}
}
// 调用 creatTree(root);
- 二叉树的先序遍历
//递归 ABCDEFG
void preorder(tree bt){
if(bt == NULL) return ;
cout<<bt->val<<" ";
preorder(bt->lchild);
preorder(bt->rchild);
}
// 非递归一 静态
stack<tree> s;
tree p = root;
while(p != NULL || !s.empty()){
while(p != NULL){
cout<<p->val<<" ";
s.push(p);
p = p->lchild;
}
if(!s.empty()){
p = s.top();
s.pop();
p = p->rchild;
}
}
// 非递归二 动态
s.push(root);
stack<tree> s;
tree p ;
while(!s.empty()){
p = s.top();
s.pop();
cout<<p->val<<" ";
if(p->rchild != NULL) s.push(p->rchild);
if(p->lchild != NULL) s.push(p->lchild);
}
考虑 先序遍历的输出顺序是 根左右,而栈只能在一端口进出,所以,要把所有的节点以 右左根 的形式压栈
其中 根 为每次的 左节点 或 右节点
- 二叉树的中序遍历
// 递归 CBDAFEG
void inorder(tree bt){
if(bt == NULL) return ;
inorder(bt->lchild);
cout<<bt->val<<" ";
inorder(bt->rchild);
}
// 非递归
stack<tree> s;
p = root;
while(p != NULL || !s.empty()){
while(p != NULL){
s.push(p);
p = p->lchild;
}
if(!s.empty()){
p = s.top();
s.pop();
cout<<p->val<<" ";
p = p->rchild;
}
}
一直找左孩子,等把所有的左孩子都入栈的时候,p为空,再输出,然后迭代的找右孩子。
- 二叉树的后序遍历
// 递归 CDBFGEA
void postorder(tree bt){
if(bt == NULL) return;
postorder(bt->lchild);
postorder(bt->rchild);
cout<<bt->val<<" ";
}
// 非递归
vector<char> v;
s.push(root);
while(!s.empty()){
p = s.top();
v.push_back(p->val);
s.pop();
if(p->lchild != NULL) s.push(p->lchild);
if(p->rchild != NULL) s.push(p->rchild);
}
for(int i = v.size() - 1;i >= 0; --i) cout<<v[i]<<" ";
考虑 先序遍历的输出顺序是 左右根,而栈只能在一端口进出,所以,要把所有的节点以 根右左 的形式压栈
其中 根 为每次的 左节点 或 右节点
然后再把vector中的数据倒序输出,就是后序遍历
- 二叉树的层序遍历
queue<tree> q; // ABECDFG
void bfs(){
q.push(root);
while(!q.empty()){
tree t = q.front();
q.pop();
cout<<t->val<<" ";
if(t->lchild != NULL) q.push(t->lchild);
if(t->rchild != NULL) q.push(t->rchild);
}
}
用BFS的思想,层层扩展即可。
4.字符串匹配
输入两个字符串A和B,求解B是不是A的字串,如果是,则输出B在A中出现的位置,如果不是,输出"No!"
例如,输入
xust_kcsoft_tobeone
kcsoft
则输出
5
因为kcsoft在字符串A中出现的起始位置为A[5]
#include <bits/stdc++.h>
using namespace std;
int main(){
string a , b,temp;
cin>>a>>b;
for(int i = 0,j = 0;i < a.length(); ++i){
if(b[0] == a[i]){
for(j = 0;j < b.length(); ++j){
if(b[j] != a[i + j]) break;
}
if(j == b.length() ) {
cout<<i<<endl;
return 0;
}
}
}
cout<<"No!\n";
return 0;
}
暴力整!,找到第一个相同的字母,然后从当前开始匹配后序字母,如果 j 从 0 到 b.length() 都匹配成功,
那么 j == b.length() ,然后直接 return 0,否则,中途一次 break ,j != b.length() ,继续找下一个 b[0]相等
的位置,如果找到 a 串的末尾,还没有找到,那么 就输出 No
5.二叉树的深度
求解一颗二叉树的最大、最小深度
构造二叉树方法与第三题同理
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
int h,c,mini;
bool f;
struct node{
char val;
node *lchild,*rchild;
node():val(0),lchild(NULL),rchild(NULL){}
};
typedef node* tree;
tree root = new node;
void creatTree(tree &bt){
char ch;
cin>>ch;
if(ch == '#'){
bt = NULL;
}
else {
bt = new node;
bt->val = ch;
creatTree(bt->lchild);
creatTree(bt->rchild);
}
}
void preorder(tree nt,int t){
if(nt->lchild == NULL && nt->rchild == NULL) {
h = max(h,t);
if(nt != root){
if(f == 0){
f = 1;
c = t;
}
else {
c = min(c,t);
}
}
return ;
}
else if(nt->lchild == NULL && nt->rchild != NULL){
preorder(nt->rchild,t+1);
}
else if(nt->rchild == NULL && nt->lchild != NULL){
preorder(nt->lchild,t+1);
}
else if(nt->lchild != NULL && nt->rchild != NULL){
preorder(nt->rchild,t+1);
preorder(nt->lchild,t+1);
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
//freopen("data.txt","r",stdin);
creatTree(root);
preorder(root,1);
cout<<"maxi: "<<h<<endl<<"mini: "<<c<<endl;
return 0;
}
深度和高度是一个东西,从根节点到最远叶子节点的边数,也可以叫做层数
叶子节点 是 左右孩子都为NULL的节点,注意判断