最近在准备学校复试,刷一些老题旧题,在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;
}
}
查找一个数组的第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;
}
输入数组长度 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;
}
}
哈夫曼树,第一行输入一个数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;
}
}
读入一组字符串(待操作的),再读入一个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;
}
输入二叉树的前序遍历和中序遍历结果,输入二叉树的后序遍历结果。
输入输出格式
输入描述:
第一行为二叉树先序遍历结果。
第二行为二叉树中序遍历结果。
输出描述:
二叉树后续遍历结果
输入输出样例
输入样例#:
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);
}
};
入数据组数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;
}
一个大于等于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;
}
一个复数(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;
}
给定一个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;
}
}
}
今天就先总结十道题吧,如果明天状态好,总结剩下的题。其他都写了。