复数乘法
问题描述:
输入两个表示复数的字符串,输出它们相乘的结果的字符串
复数字符串用a+bi表示(a, b 为整数, i为虚数单位,i2=1)
输入例子:
1±2i
3+4i
输出例子:
11±2i
例子说明:
(1±2i)(3+4i) = (3 + 4i - 6i - 8i * i) = 11±2i
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int strToInt(string& str)
{
int ret = 0;
int flag = 1;
for(auto& ch : str)
{
if(ch == '-')
flag = -1;
if(ch >= '0' && ch <= '9')
ret = ret * 10 + ch - '0';
}
return ret * flag;
}
int main()
{
string str1, str2;
cin >> str1 >> str2;
string sr1 = str1.substr(0, str1.find('+'));
string sf1 = str1.substr(str1.find('+')+1);
string sr2 = str2.substr(0, str2.find('+'));
string sf2 = str2.substr(str2.find('+')+1);
int srInt1 = strToInt(sr1);
int sfInt1 = strToInt(sf1);
int srInt2 = strToInt(sr2);
int sfInt2 = strToInt(sf2);
int sr = srInt1 * srInt2 - sfInt1 * sfInt2;
int sf = srInt1 * sfInt2 + sfInt1 * srInt2;
cout << sr << "+" << sf << "i" << endl;
return 0;
}
一年中的第几天
问题描述:
输入一个"YYYY-MM-dd"格式的日期字符串,输出该天是当年的第几天(1 月 1 日是每年的第 1 天)
输入描述:
一个"YYYY-MM-dd"格式的表示日期的字符串
输出描述:
该天是当年的第几天
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int strToInt(string s)
{
int ret = 0;
for(auto ch : s)
{
ret = ret * 10 + ch - '0';
}
return ret;
}
int main()
{
string s;
cin >> s;
vector<string> strV;
string tmp = "";
for(int i = 0; i < s.size(); i++)
{
if(s[i] == '-')
{
strV.push_back(tmp);
tmp = "";
}
else
{
tmp += s[i];
}
}
strV.push_back(tmp);
int year = strToInt(strV[0]);
int month = strToInt(strV[1]);
int day = strToInt(strV[2]);
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int ret = 0;
for(int i = 1; i < month; i++)
{
ret += days[i];
}
ret += day;
if(month > 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 ==0))
++ret;
cout << ret << endl;
return 0;
}
k个一组翻转链表
问题描述:
给你一个链表,每 k 个节点一组进行翻转,请返回翻转后的链表。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
输入描述:
第一行:依次输入链表中的各个元素,以"#“结束
第二行:每组数量k
输出描述:
处理后的链表中的各个元素,以”->"连接
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void reverseStr(vector<string>& sv, int start, int end)
{
while(start < end)
sv[start++].swap(sv[end--]);
}
int main()
{
string s;
vector<string> sv;
while(cin >> s)
{
if(s != "#")
sv.push_back(s);
else
break;
}
int k;
int start = 0;
cin >> k;
while(sv.size() - start >= k)
{
reverseStr(sv, start, start + k - 1);
start += k;
}
for(int i = 0; i < sv.size() - 1; i++)
{
cout << sv[i] << "->";
}
cout << sv[sv.size()-1] << endl;
return 0;
}
递增子序列
问题描述:
判断一个无序数组中是否存在长度为3的递增子序列。(不要求连续)(满足O(n)的时间复杂度和O(1)的空间复杂度。)
输入描述:
第一行一个正整数 1 <= n <= 100000
第二行n个整数a1,a2,…,an,(1<=ai<=1e9)
输出描述:
如果存在,输出"true",否则输出"false"。(不含引号)。
记录遍历当前位置时的最小的两个值,如果当前位置的值大于第二小的值,则可以说明存在这样的递增序列。第二小的值必须在第一小的值之后,所以如果更新了第一小的值,则也需要更新第二小的值。
#include <iostream>
#include <vector>
#include <limits.h>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> a(n);
for(int i = 0; i < n; i++)
cin >> a[i];
int first = a[0];
int second = INT_MAX;
for(int i = 0; i < n; i++)
{
if(a[i] < first)
{
first = a[i];
//如果更新了最小值,则second需要在后面找,所以先给一个最大值
second = INT_MAX;
}
else if(a[i] > first && a[i] < second)
{
second = a[i];
}
else if(a[i] > second )
{
cout << "true" << endl;
return 0;
}
}
cout << "false" <<endl;
return 0;
}
求表达式f(n)结果末尾0的个数
问题描述:
输入一个自然数n,求表达式 f(n) = 1! * 2! * 3!..n! 的结果末尾有几个连续的0?
如果要产生0,则需产生因子10,相当于需要计算出10的数量。但10不是最小的因子,他还可以分解成2*5,所以需要找出2和5的个数并取两者中最小的,即为0的个数。(也可以直接取5的个数)
例如:1053000000 = 1053 *10 *10 *10 *10 *10 *10
而f(10): 1!2!3!..10! : 2!3!… 10!都包含2
5!6!… 10!都包含5
所以 i:i中2或5的个数 * 表达式中i的个数
例如 i = 4:2的个数是2,5的个数是0;4!5!6!… 10!都包含4
即 f(i)中2的个数:2 *(10 - 4 +1) 5的个数:0
#include <iostream>
using namespace std;
int num(int i, int n)
{
int cnt = 0;
while(i >= n && i%n == 0)
{
cnt++;
i /= n;
}
return cnt;
}
int main()
{
int n;
cin >> n;
int num2 = 0, num5 = 0;
for(int i = 1; i <= n; i++)
{
num2 += num(i, 2) * (n - i + 1);
num5 += num(i, 5) * (n - i + 1);
}
cout << min(num2, num5);
return 0;
}
字符串压缩算法
输入一串字符,请编写一个字符串压缩程序,将字符串中连续出现的重复字母进行压缩,并输出压缩后的字符串。
例如:
aac 压缩为 1ac
xxxxyyyyyyzbbb 压缩为 3x5yz2b
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
getline(cin, s);
for(int i = 0; i < s.size(); i++)
{
int cnt = 0;
while(s[i] == s[i+1])
{
++cnt;
++i;
}
if(cnt != 0)
cout << cnt << s[i];
else
cout << s[i];
}
cout << endl;
return 0;
}
硬币划分
问题描述:
有1分,2分,5分,10分四种硬币,每种硬币数量无限,给定n分钱(n <= 100000),有多少中组合可以组成n分钱?
输入描述:输入整数n.(1<=n<=100000)
输出描述:输出组合数,答案对1e9+7取模。
本题可以使用DFS,但如果n过大可能会超出时间限制
动态规划:
1.状态F(i, j): 用i种硬币组成j分钱的方法总数
2.转移方程:
如果第j个硬币面值大于j,则只能用i-1种硬币进行组合。F(i, j) = F(i-1, j);
如果第j个硬币面值小于j,则可以用,也可以不用,两种选择互斥F(i, j) = F(i - 1, j) + F(i, j - coins[i - 1])
此处F(i, j - coins[i - 1])表示:第i个硬币可能使用了多次
3.初始化:
F(0, j) = 0
F(i, 0) = 1 //辅助值
4.返回值
F(coins.size(), n)
#include <iostream>
#include <vector>
using namespace std;
//f(i, j) 前i种硬币 j分钱 = f(i-1, j) + f(i, j-a[i])
int main()
{
int n;
cin >> n;
vector<int> coins = {1, 2, 5, 10};
vector<vector<int>> result(5, vector<int>(n+1, 0));
//初始化 f(i, 0)=1;//辅助值
for(int i = 0; i < 5; i++)
result[i][0] = 1;
for(int i = 1; i < 5; i++){
for(int j = 0; j <= n; j++){
if(j >= coins[i-1]){
result[i][j] = (result[i-1][j] + result[i][j-coins[i-1]]) % 1000000007;
}
else{
result[i][j] = result[i-1][j];
}
}
}
cout << result[4][n];
return 0;
}
合并二叉树
问题描述:
已知两颗二叉树,将它们合并成一颗二叉树。合并规则是:都存在的结点,就将结点值加起来,否则空的位置就由另一个树的结点来代替。
1.输入描述:第一行输入整数n,m。(分别表示树1和树2的节点数,1<=n,m<=100)接下来n行,第i行三个整数l,r,v, (0<=l,r<=n , 0<=v<=100) ,表示第一棵树的第i个结点的左儿子编号,右儿子编号和权值。接下来m行,第i行三个整数l,r,v, (0<=l,r<=n , 0<=v<=100) ,表示第二棵树的第i个结点的左儿子编号,右儿子编号和权值。(对于左右儿子,如果编号为0表示空。保证如果儿子不为空,则儿子编号大于父亲编号。)
2.输出描述: 输出合并后树按层遍历的各结点权值,相邻权值之间以一个空格相间。
输入例子1:
4 5
2 3 1
4 0 3
0 0 2
0 0 5
2 3 2
0 4 1
0 5 3
0 0 4
0 0 7
输出例子1: 3 4 5 5 4 7
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct Node{
int val;
Node* left;
Node* right;
Node(int x = 0)
:val(x)
,left(nullptr)
,right(nullptr)
{}
};
Node* creatTree(vector<Node>& tree, int num)
{
//从第一个孩子结点开始
for(int i = 1; i <= num; i++){
int l, r, v;
cin >> l >> r >> v;
if(l != 0){
tree[i].left = &tree[l];
}
if(r != 0){
tree[i].right = &tree[r];
}
tree[i].val = v;
}
return &tree[1];
}
Node* mergeTree(Node* root1, Node* root2)
{
if(root1 != nullptr && root2 != nullptr)
{
root1->left = mergeTree(root1->left, root2->left);
root1->right = mergeTree(root1->right, root2->right);
root1->val += root2->val;
}
return root1 != nullptr ? root1 : root2;
}
void DFS(Node* root)
{
queue<Node*> q;
q.push(root);
while(!q.empty()){
Node* curNode = q.front();
q.pop();
if(curNode->left)
q.push(curNode->left);
if(curNode->right)
q.push(curNode->right);
cout << curNode->val << " ";
}
}
int main()
{
int n, m;
cin >> n >> m;
vector<Node> tree1(n+1);
vector<Node> tree2(m+1);
Node* root1 = creatTree(tree1, n);
Node* root2 = creatTree(tree2, m);
Node* root = mergeTree(root1, root2);
DFS(root);
return 0;
}