【快手】获得最多的奖金
知识点:双指针
题目地址
解题思路:要求红包数组相对位置不变,分成三部分,第一部分和第三部分加和相等,且和最大。可以前序累计和,后序累计和,双指针移动,如果前序累计和小于后续累计和,则前序指针加一,否则后续累计和减一,如果相等,两个指针都向前前进一步。
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
long n;
cin >> n;
long long nums[n];
for (int i = 0; i < n; i++)
cin >> nums[i];
//双指针p1, p2
int p1 = 0;
int p2 = n - 1;
long long forward[n];
long long backward[n];
forward[0] = nums[0];
backward[n-1] = nums[n-1];
for (long i = 1; i < n - 1; i++)
{ //前序后续累计求和
forward[i] = forward[i-1] + nums[i];
backward[n - i - 1] = backward[n - i] + nums[n - i - 1];
}
long long res = -1;
while (p1 < p2)
{ //双指针
if (forward[p1] < backward[p2])
p1++;
else if (backward[p2] < forward[p1])
p2--;
else
{
res = forward[p1];
p1++;
p2--;
}
}
if (res > 0)
cout << res << endl;
else
cout << 0 << endl;
}
【快手】将满二叉树转换为求和树
知识点:递归,树遍历,给定中序遍历和先序遍历重构树
题目地址
解题思路:
1.直接重构树
2.递归求和
3.中序遍历返回结果
但是题目中说明是满二叉树,只需中序遍历即可重构出树,在中序数组上原位求和,节省空间
#include <bits/stdc++.h>
using namespace std;
int dfs(vector<int>& inorder, int start, int end)
{ //满二叉树只需中序遍历
if (start == end)
{
int tmp = inorder[start];
inorder[start] = 0;
return tmp;
}
int mid = (end - start) / 2 + start;
int root = inorder[mid];
int left = dfs(inorder, start, mid - 1);
int right = dfs(inorder, mid + 1, end);
inorder[mid] = left + right;
return root + inorder[mid];
}
int main()
{
vector<int> nums;
vector<int> preorder;
vector<int> inorder;
vector<int> res;
int num;
while (cin >> num)
{
nums.push_back(num);
}
for (int i = 0; i < nums.size() / 2; i++)
{
preorder.push_back(nums[i]);
inorder.push_back(nums[i+nums.size() / 2]);
}
dfs(inorder, 0, inorder.size()-1);
copy(inorder.begin(), inorder.end(), ostream_iterator<int>(cout, " "));
}
【快手】搭积木
还未想出解题思路,等待明白填坑。。。
#【快手】魔法深渊
知识点:动态规划
题目地址
解题思路:和爬梯子一个类型的题,典型的动态规划
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int M;
cin >> M;
int N = -1;
int steps[M];
for (int i = 0; i < M; i++)
{
cin >> steps[i];
N = max(N, steps[i]);
}
long long dp[N+1];
long long mod = 1000000003;
for (int i = 0; i <= N; i++)
dp[i] = 0;
dp[0] = 1;
dp[1] = 1;
for (long long i = 2; i <= (long long)N; i++)
{
long long fromDiff = 1;
// dp[i]等于所有能抵达i出的所有dp[j]之和
while (i - fromDiff >= 0)
{
dp[i] += dp[i-fromDiff];
dp[i] %= mod;
fromDiff *= 2;
}
}
for (int step: steps)
cout << dp[step] << endl;
}
【快手】善变的同伴
知识点:动态规划
等待填坑,和m个字串最大和同一个问题,还没搞懂。。。
【快手】字符串归一化
题目地址
知识点:map
解题思路:怎么做都行
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<char> chars;
char c;
while(cin >> c)
{
if (c != '\n')
chars.push_back(c);
}
int freq[26] = {0};
for (char ch: chars)
{
freq[ch - 'a']++;
}
for (int i = 0; i < 26; i++)
{
if (freq[i] > 0)
cout << (char)(i + 'a') << freq[i];
}
}
【快手】字符串排序
题目地址
知识点:字符串
解题思路:初始化string数组,cin读入数组,利用string类内建substr方法读取后六位数字,调用strNum或者stdio转换为int类型
#include <iostream>
#include <algorithm>
#include <string>
#include <bits/stdc++.h>
using namespace std;
int strToNum(string str)
{
int num = 0;
for (int i = 0; i < str.size(); i++)
{
num = num * 10 + (str[i] - '0');
}
return num;
}
int main()
{
int M;
cin >> M;
string s[M];
int nums[M];
for (int i = 0; i < M; i++)
{
nums[i] = 0;
cin>>s[i];
string str = s[i].substr(s[i].size() - 6, s[i].size() - 1);
nums[i]=strToNum(str);
}
sort(nums, nums + M);
for (int i = 0; i < M; i++)
cout << nums[i] << endl;
}