题目记不太清了,主要是存下代码
第一题
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <sstream>
#include <queue>
using namespace std;
struct compare
{
bool operator()(int &a, int &b)
{
if ((a & 0x1) && !(b & 0x1))
return true;
else if (!(a & 0x1) && (b & 0x1))
return false;
else
{
if (a < b)
return true;
else
return false;
}
}
};
int main()
{
string s; int N;
while (cin >> s)
{
for (auto &t : s)
if (t == ',' || t == ';')
t = ' ';
istringstream input(s); vector<int> out;
priority_queue<string, vector<int>, compare> m_queue;
//最后一个就是N
while (input >> N)
m_queue.push(N);
bool flag = false;
for (int i = 0; i < N; i++)
{
if (!flag && m_queue.top() == N)
{
flag = true;
i--;
continue;
}
out.push_back(m_queue.top());
m_queue.pop();
}
for (int i = 0; i < out.size() - 1; i++)
cout << out[i] << ",";
cout << out[out.size() - 1] << endl;
}
return 0;
}
第二题
/*
第二题:女朋友和男朋友玩纸牌,各抽n1 n2张牌,女朋友有三种策略:
d:丢弃手牌中最左边的牌
l:将手牌中最左边的牌放到新牌堆最左边
r:将手牌中最左边的牌放到新牌堆最右边。
求能使女朋友和男朋友纸牌顺序及顺序相同的策略。
示例:女朋友抽到三张牌,分别为:1 2 3,男朋友抽到一张牌,为:3
则策略为:d d l或者d d r
第二题是bfs,让每一次的操作为d l r,操作完N次看看形成的串是否等于男朋友的串,是就加入到答案,最后可能会有多个答案,对答案进行升序排序即可。
难点:女朋友的初始串等于男朋友的串,答案为“”,也算是一个答案。
*/
void dfsfind(set<string> &save, string path, int s, string news, string m, string &b)
{
if (s == 0 && news == b)
{
save.insert(path);
return;
}
if (s < 0 || m.size() < 1)
return;
dfsfind(save, path + "d", s - 1, news, m.substr(1), b);
dfsfind(save, path + "l", s - 1, m[0] + news, m.substr(1), b);
dfsfind(save, path + "r", s - 1, news + m[0], m.substr(1), b);
}
int main_pdd2()
{
int s; string m, b;
cin >> s;
for (int i = 0; i < s; i++)
{
set<string> save;
cin >> m >> b;
dfsfind(save, string(), s, string(), m, b);
cout << "{" << endl;
for (auto &t : save)
cout << t << endl;
cout << "}" << endl;
}
return 0;
}
第三题
/*
几乎每一个人都用 乘法表。但是你能在乘法表中快速找到第k小的数字吗?
给定高度m 、宽度n 的一张 m * n的乘法表,以及正整数k,你需要返回表中第 k 小的数字。
*/
class Solution
{
public:
//函数功能:获得在m*n的乘法表中,找出有多少个值 <= num。返回满足条件的值的数量
int fun(int m, int n, int num)
{
int count = 0;
for (int i = 1; i <= m; ++i) //行从第一行开始
{
count += min(num / i, n);//此表达式的含义:num在乘法表的第i行中,有多少个值小于或等于该值(<=num的个数)(这个除i简直神仙思想)
}
return count;
}
int findKthNumber(int m, int n, int k)
{
if (k == 1)
return 1;
if (k == m*n)
return m*n;
int lo = 1, hi = m*n, mi = 0;
//跟普通二分不一样,普通二分把下标来当作边界,而这里的二分则是把值来当作边界
while (lo < hi)
{
mi = (lo + hi) >> 1;
int temp = fun(m, n, mi);
if (temp < k)
lo = mi + 1;
else
hi = mi; //核心在于这里的收敛,不直接跳出
//temp >= k, 在temp>k时,为什么不取 right = mid-1,而是right = mid。
//因为我们的目标值可能存在重复,比如 123334,如果我选择要找第3小的数,而mid当前恰好=3,那么temp得到的结果会是5(<=mid)。
//如果我们选择right = mid-1=2。那么将会运行错误导致结果错误。
//在temp = k时,为什么不能立马返回结果呢,而是继续运行缩小边界?
//因为我们当前的mid可能是一个不在乘法表中的值,毕竟mid=(left+right) >> 1; 所以立即返回可能返回错误答案。
//所以一定收缩范围 直到left=right,最终返回的一定是正确值
//(若答案t的temp = k, 而某一非表值x的temp也=k, 那么t一定比x小,最终x也会被right缩小导致出局)。
}
return lo;
}
};