机试旧题新讲一

最近在准备学校复试,刷一些老题旧题,在N诺oj和牛客网上都有提交。今天就总结部分题目,只写我觉得值得写的(当然还有一些我不会写,不想去学了)
1、二进制数

输入输出格式
输入描述:
每行有一个数字n(0<=n<=10^8),表示要求的二进制串。
输出描述:
输出共T行。每行输出求得的二进制串。
输入输出样例
输入样例#:
23
输出样例#:
10111

reverse函数必须使用首尾指针,可以反转vector数组也可以反转string字符串。

#include<bits/stdc++.h>
using namespace std;
int main(){
	unsigned int n;
	cin>>n;
	vector<int> res;
	while (n != 0) {
		int tmp = n%2;
		n = n/2;
		res.push_back(tmp);
	}
	reverse(res.begin(),res.end());
	for (auto i : res) {
		cout<<i;
	}
}

2、查找第K小数

查找一个数组的第K小的数,注意同样大小算一样大。 如 2 1 3 4 5 2 第三小数为3。

输入输出格式
输入描述:
输入有多组数据。
每组输入n,然后输入n个整数(1<=n<=1000),再输入k。
输出描述:
输出第k小的整数。
输入输出样例
输入样例#:
6
2 1 3 5 2 2
3
输出样例#:
3

因为要找第k小不同的数,因此不能使用堆来写,因为必须经过一次排序,时间复杂度最快O(nlogn),然后对比前后不相同的第几个值。

#include<bits/stdc++.h>
using namespace std;
int main () {
	int n;
	while (cin>>n) {
		vector<int> record(n);
		for (int i = 0; i < n; i++) {
			cin>>record[i];
		}
		sort(record.begin(), record.end());
		int k;
		cin>>k;
		int count = 1;
		for (int i = 1;i < n; i++) {
			if (record[i] != record[i-1]){
				count++;
				if (count == k) {
					cout<<record[i]<<endl;
				}
			}
		}
	}
	return 0;
}	

3、查找1

输入数组长度 n
输入数组 a[1…n]
输入查找个数m
输入查找数字b[1…m]
输出 YES or NO 查找有则YES 否则NO 。
输入输出格式
输入描述:
输入有多组数据。
每组输入n,然后输入n个整数,再输入m,然后再输入m个整数(1<=m<=n<=100)。
输出描述:
如果在n个数组中输出YES否则输出NO。
输入输出样例
输入样例#:
6
3 2 5 4 7 8
2
3 6
输出样例#:
YES
NO

哈希表法,直接定为每个元素是否出现过。

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n, m;
	while (cin>>n) {
		vector<int> nums1(n);
		vector<int> record(10000, 0);
		for (int i = 0; i < n; i++) {
			cin>>nums1[i];
			record[nums1[i]] = 1;
		}
		cin>>m;
		vector<int> nums2(m);
		for (int i = 0; i < m; i++) {
			cin>>nums2[i];
			if (record[nums2[i]] == 1)
				cout<<"YES"<<endl;
			else
				cout<<"NO"<<endl;
		}
		return 0;
	}
}

4、哈夫曼树

哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。
输入输出格式
输入描述:
输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。
输出描述:
输出权值。
输入输出样例
输入样例#:
5
1 2 2 5 9
输出样例#:
37

这里用到了优先队列priority_queue,再强调一遍,优先队列默认是less比较仿函数,大顶堆(与sort排序相反)。因此如果需要小顶堆(求最大的k个值,出现最多次的k个数),要在优先队列的第三个参数使用greater<int>。求WPL。

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n;
	while (cin>>n) {
		vector<int> nums(n);
		for (int i = 0; i < n; i++) {
			cin>>nums[i];
		}
		priority_queue<int ,vector<int>, greater<int>> q;
		for (int i = 0; i < n; i++) {
			q.push(nums[i]);
		}
		int res = 0;
		while (q.size()>1) {
			int tmp1 = q.top();
			q.pop();
			int tmp2 = q.top();
			q.pop();
			int sum = tmp1 + tmp2;
			res += sum;
			q.push(sum);
		}
		cout<<res<<endl;
	}
}		

5、查找 - 北邮

读入一组字符串(待操作的),再读入一个int n记录记下来有几条命令,总共有2中命令:1、翻转 从下标为i的字符开始到i+len-1之间的字符串倒序;2、替换 命中如果第一位为1,用命令的第四位开始到最后的字符串替换原读入的字符串下标 i 到 i+len-1的字符串。每次执行一条命令后新的字符串代替旧的字符串(即下一条命令在作用在得到的新字符串上)。 命令格式:第一位0代表翻转,1代表替换;第二位代表待操作的字符串的起始下标int i;第三位表示需要操作的字符串长度int len。
输入输出格式
输入描述:
输入有多组数据。
每组输入一个字符串(不大于100)然后输入n,再输入n条指令(指令一定有效)。
输出描述:
根据指令对字符串操作后输出结果。
输入输出样例
输入样例#:
bac
2
003
112as
输出样例#:
cab
cas

这里涉及到string的substr、erase、insert函数,需要指出三个函数都可以采用角标(非迭代器)定位首地址,所有左右区间的都是左闭右开,insert函数插入的必须是string类型,不能是char类型。swap函数,老朋友了,交换string,vector都可以。

#include<bits/stdc++.h>
using namespace std;
void reverse(string &s, int begin, int end) {
	for (int i = begin, j = end; i < j; i++,j--) {
		swap(s[i],s[j]);
	}
}
int main() {
	string str;
	while (cin>>str) {
		int n;
		cin>>n;
		for (int i = 0; i < n; i++) {
			string s;
			cin>>s;
			//反转
			if (s[0] == '0') {
				int begin = s[1]-'0';
				int end = s[2]-'0'+begin-1;
				reverse(str, begin, end);
				cout<<str<<endl;
			}
			else if (s[0] == '1') {
				int begin = s[1]-'0';
				int end = s[2]-'0'+begin-1;
				string s1 = s.substr(3, s.size());
				str.erase(str.begin()+begin, str.begin()+end+1);
				str.insert(begin,s1);
				cout<<str<<endl;
			}
		}
	}
	return 0;
}		

6、二叉树(北京邮电大学)

输入二叉树的前序遍历和中序遍历结果,输入二叉树的后序遍历结果。
输入输出格式
输入描述:
第一行为二叉树先序遍历结果。
第二行为二叉树中序遍历结果。
输出描述:
二叉树后续遍历结果
输入输出样例
输入样例#:
426315
623415
输出样例#:
632514

构造二叉树,太难辣!这次是前序加中序构建二叉树,那么下次万一是后序加中序构建二叉树呢!于是勤奋的我把两种都给出来了!然后注意定义树怎么定义:

struct TreeNode{
	int val;
	TreeNode *left;
	TreeNode *right;
	//构造结构
	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
//前、中序构建二叉树
#include<bits/stdc++.h>
using namespace std;
struct TreeNode{
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
TreeNode* traversal(vector<int>& preorder, vector<int>& inorder)
{
	if(preorder.size() == 0)
		return nullptr;
	int rootValue = preorder[0];
	TreeNode* root = new TreeNode(rootValue);

	// 确定中序分割点
	int Index;
	for(Index = 0; Index < inorder.size(); Index++)
	{
		if(inorder[Index] == rootValue) break;
	}
	// 分割中序
	vector<int> leftInorder(inorder.begin(), inorder.begin() + Index);
	vector<int> rightInorder(inorder.begin() + Index + 1, inorder.end());

	// 分割前序
	preorder.erase(preorder.begin());
	vector<int> leftPreorder(preorder.begin(), preorder.begin() + leftInorder.size());
	vector<int> rightPreorder(preorder.begin() + leftInorder.size(), preorder.end());

	// 开始构建树
	root->left = traversal(leftPreorder, leftInorder);
	root->right = traversal(rightPreorder, rightInorder);
	return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
	if(preorder.size() == 0 || inorder.size() == 0)
		return nullptr;
	return traversal(preorder, inorder);
}
void postTree(TreeNode *t) {
	if (t != nullptr) {
		postTree(t->left);
		postTree(t->right);
		cout<<t->val;
	}
}
int main() {
	vector<int> preTree;
	vector<int> inTree;
	string s1,s2;
	cin>>s1>>s2;
	for (int i = 0; i < s1.size(); i++) {
		preTree.push_back(s1[i] - '0');
	}
	for (int i = 0; i < s2.size(); i++) {
		inTree.push_back(s2[i] - '0');
	}
	TreeNode *t = buildTree(preTree, inTree);
	postTree(t);
	return 0;
}

resize函数可以把后面的去掉。

//中序、后序构造二叉树
class Solution {
public:
    TreeNode* traversal(vector<int>& inorder, vector<int>& postorder){
        // 空节点返回null
        if(postorder.size() == 0) return nullptr;
        int rootValue = postorder[postorder.size()-1];//后序遍历最后一个数
        // 新建的一个节点
        TreeNode* root = new TreeNode(rootValue);
        // 中序分割
        int index;
        for(index = 0; index < inorder.size(); index++)
        {
            if(inorder[index] == rootValue)
                break;
        }
        vector<int> leftInorder(inorder.begin(), inorder.begin() + index);
        vector<int> rightInorder(inorder.begin() + index + 1,inorder.end());
        // 后序分割
        postorder.resize(postorder.size() - 1);
        vector<int> leftPostorder(postorder.begin(),postorder.begin() + index);
        vector<int> rightPostorder(postorder.begin() + index, postorder.end());
        // 接上子节点
        root->left = traversal(leftInorder, leftPostorder);
        root->right = traversal(rightInorder, rightPostorder);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // 空树
        if(inorder.size() == 0 || postorder.size() == 0) return nullptr;
        return traversal(inorder, postorder);
    }
};

7、二进制数字翻转

入数据组数t

每组数据输入一个十进制数x(0<x<2^32),将其二进制位反转(共32位),然后输出对应的十进制数
输入输出格式
输入描述:
如题
输出描述:
如题
输入输出样例
输入样例#:
2
2
3
输出样例#:
1073741824
3221225472
提示
2^32-1超出了int的范围,请使用long long

他真的,我哭死,他居然提醒我用long long,好贴心啊!

#include<bits/stdc++.h>
using namespace std;
int main() {
	int t;
	cin>>t;
	while(t--) {
		long long n;
		cin>>n;
		vector<int> Binary(32, 0);
		for (int i = 0; i <32; i++) {
			Binary[i] = n%2;
			n /= 2;
			if (n == 0)
				break;
		}
		//reverse(Binary.begin(), Binary.end());
		long long sum = 0;
		for (int i = 0; i < 32; i++){
			sum *= 2;
			sum += Binary[i];
		}
		cout<<sum<<endl;
	}
	return 0;
}
		

8、发财数

一个大于等于2的整数,如果可以分解为8个或8个以上的素数相乘,则称其为发财数,让你输出第n个发财数
输入输出格式
输入描述:
输入一个整数t,代表有t组数据(t<1000)
输入一个正整数n,(n<=10000)
输出描述:
输出第n个发财数。
输入输出样例
输入样例#:
1
1
输出样例#:
256

枚举遍历,每一次都除以一个数,如果可以除尽。接着除,否则除的数加一,往后看,看是否可以被八个数整除。

#include<bits/stdc++.h>
using namespace std;
int main () {
	int t;
	cin>>t;
	vector<int> nums;
	while (t--) {
		int n;
		cin>>n;
//		if (n <= nums.size()) {
//			cout<<nums[n-1]<<endl;
//		}
		for (int i = (nums.size() > 0 ? nums.back() + 1 : 256); nums.size() <= n+1; i++) {
			int value = i;
			int count = 8;
			for (int j = 2; j*j <= value;) {
				if (value % j == 0) {
					count--;
					value /= j;
					if (count == 1) {
						nums.push_back(i);
					}
				}
				else {
					j++;
				}
			}
		}
//		for (int i = 0; i < nums.size();i++) {
//			cout<<nums[i]<<" ";
//		}
		cout<<nums[n-1]<<endl;
	}
	return 0;
}					

9、复数集合

一个复数(x+iy)集合,两种操作作用在该集合上: 1、Pop 表示读出集合中复数模值最大的那个复数,如集合为空 输出 empty ,不为空就输出最大的那个复数并且从集合中删除那个复数,再输出集合的大小SIZE; 2 Insert a+ib 指令(a,b表示实部和虚部),将a+ib加入到集合中 ,输出集合的大小SIZE; 最开始要读入一个int n,表示接下来的n行每一行都是一条命令。
输入输出格式
输入描述:
输入有多组数据。
每组输入一个n(1<=n<=1000),然后再输入n条指令。
输出描述:
根据指令输出结果。
模相等的输出b较小的复数。
a和b都是非负数。
输入输出样例
输入样例#:
3
Pop
Insert 1+i2
Pop
输出样例#:
empty
SIZE = 1
1+i2
SIZE = 0

排序固然可,但是堆更妙。在结构体里构建排序函数,重载运算符<号可以自定义堆的排序方式。这样出来的大顶堆是按照我们自己定义的方式排序的大顶堆。还有一件事,就是出入如果不符合,那么就会卡住,比如你出入一个字符,但是我用int来接,就接不了,会卡在缓冲区,因此如果有一个字符你不要可以用一个临时变量将其取出,然后不作处理。还有一件事,就是比如234+345这样的式子,可以用int,char,int分别取出三个部分这个真的有用哎!如果一串1 2 3 5,如果想当做字符串,可以getline(cin,str)。

#include<bits/stdc++.h>
using namespace std;
struct Complex{
	int x;
	int y;
	bool operator< (Complex node) const{
		if (x*x+y*y == node.x*node.x+node.y*node.y) {
			return y > node.y;
		}
		return x*x+y*y < node.x*node.x+node.y*node.y;
	}
};

int main() {
	int n;
	while (cin>>n) {
		string cmd;
		priority_queue<Complex> q;
		while (n--) {
			cin>>cmd;
			Complex C;
			if (cmd == "Pop") {
				if (q.size() == 0) {
					cout<<"empty"<<endl;
				}
				else {
					cout<<q.top().x<<"+i"<<q.top().y<<endl;
					q.pop();
					cout<<"SIZE = "<<q.size()<<endl;
				}
			}
			else if (cmd == "Insert") {
				char o,c;
				cin>>C.x>>o>>c>>C.y;
				q.push(C);
				cout<<"SIZE = "<<q.size()<<endl;
			}
		}
	}
	return 0;
}

10、矩阵幂

给定一个n*n的矩阵,求该矩阵的k次幂,即P^k。
输入输出格式
输入描述:
第一行:两个整数n(2<=n<=10)、k(1<=k<=5),两个数字之间用一个空格隔开,含义如上所示。
接下来有n行,每行n个正整数,其中,第i行第j个整数表示矩阵中第i行第j列的矩阵元素Pij且(0<=Pij<=10)。另外,数据保证最后结果不会超过10^8。
输出描述:
对于每组测试数据,输出其结果。格式为:
n行n列个整数,每行数之间用空格隔开,注意,每行最后一个数后面不应该有多余的空格。
输入输出样例
输入样例#:
2 2
9 8
9 3
输出样例#:
153 96
108 81

其实不用快速幂也可以完成,但是可以用更dio的方法为什么不用呢对吧!快速幂,类似求01串转化为十进制数,从低位开始,结果值初始化为1,如果低位为零,则不作处理,低位自己平方;否则结果值乘前面说的低位平方(一直累计)。本题是模板题,要背!
咱就是自己归纳三部曲:
1、重载运算符
,返回值为二维数组,其实就是将普通乘法变为矩阵乘法。矩阵乘矩阵返回矩阵。
2、初始化结果矩阵,结果矩阵必须初始化为单位阵。
3、快速幂方法:
*

//快速幂方法
	while (k>0) {
		if (k % 2 == 1) {
			Q = Q * P;
		}
		P = P * P;
		k /= 2;
	}
#include<bits/stdc++.h>
using namespace std;
//重载运算符*变为矩阵乘法,返回一个矩阵
vector<vector<int>> operator*(const vector<vector<int>> &a,const vector<vector<int>> &b) {
	int n = a.size();
	vector<vector<int>> tmp(n, vector<int>(n, 0));
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			for (int k = 0; k < n; k++) {
				tmp[i][j] += a[i][k] * b[k][j];
			}
		}
	}
	return tmp;
}
	
	
int main () {
	int n,k;
	while (cin>>n>>k) {	
		vector<vector<int>> P(n, vector<int>(n, 0));
		vector<vector<int>> Q(n,vector<int>(n, 0));
		//结果矩阵对角线为1
		for (int i = 0; i < n; i++) {
			Q[i][i] = 1;
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				cin>>P[i][j];
			}
		}
		//快速幂方法
		while (k>0) {
			if (k % 2 == 1) {
				Q = Q * P;
			}
			P = P * P;
			k /= 2;
		}
		for (int i = 0; i < n; i++) {
			 cout<<Q[i][0];
			 for (int j = 1; j < n; j++) {
				 cout<<" "<<Q[i][j];
			 }
			 cout<<endl;
		}
	}
}

今天就先总结十道题吧,如果明天状态好,总结剩下的题。其他都写了。

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
近年来,随着科技的快速发展,计算机相关的职业越来越受到重视。华为作为全球领先的科技公司,已经开始在兴技术上进行布局,其中华为OD是重点发力的领域之一。华为OD是一套完整的云计算解决方案,包括了云端计算、边缘计算、混合云等多个方面。随着OD的逐步完善,需要各种计算机相关专业的人才来支持其发展。为了吸引人才,华为OD机试开始逐步普及。下面是对华为OD机试2023年最题库的免费解析。 第一部分是选择题,主要是基础知识的考察。第二部分是实验题,目的在于考察测试人员的实践能力。考生需要开发一款基于华为OD的应用程序,进行整个产品的设计开发和测试。在开发过程中,需要考虑如何使用OD的各项服务和资源,包括存储、计算和网络等。在测试过程中,需要进行功能测试、性能测试和安全测试等多个方面的测试。同时,还需要进行最终的用户验收测试,确保产品的质量。 对于考生来说,通过华为OD机试的考核,不仅可以验证自己在计算机方面的技术水平,同时也可以增加自己的竞争力和就业机会。作为一家技术领先的企业,华为OD的市场需求将逐渐增加。拥有OD相关技能的专业人才将变得越来越重要。因此,通过参加华为OD机试,对于计算机相关专业的考生来说,是一个难得的机会。相信在未来的职场中,拥有OD相关技能的人才将能够更好地适应市场需求,取得更高的职业成就。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值