第一题:链表遍历+链表复制
题解:由于查询是随机的,跟遍历顺序无关,因此通过哈希记录所有需要查询的节点值。通过前序遍历树并更新路径,在遍历树的过程中判断,哈希表中存在的值就将当前路径链表复制,并将头指针存储在对应节点的map中,最后根据查询顺序输出。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 你需要返回m个指针,第i个指针指向一条链,表示第i个问题的答案
* @param root TreeNode类 指向链表树的根
* @param b int整型vector 表示每个问题是什么
* @return ListNode类vector
*/
vector<ListNode*>res;
ListNode* head;
map<int, ListNode*>shuchu;
void find_res(TreeNode* root, unordered_set<int>room, ListNode* front) {
if (root == nullptr)
return;
if (room.count(root->val) != 0) {
ListNode* k = head;
ListNode* save;
save = new ListNode(k->val);
ListNode* p = save;
k = k->next;
while (k != NULL) {
save->next = new ListNode(k->val);
if (k->val == root->val)
break;
save = save->next;
k = k->next;
}
shuchu[root->val] = p;
}
ListNode *cur = new ListNode(0);
if (root->left != nullptr) {
cur->val = root->left->val;
front->next = cur;
find_res(root->left, room, front->next);
}
if (root->right != nullptr) {
cur->val = root->right->val;
front->next = cur;
find_res(root->right, room, front->next);
}
}
vector<ListNode*> solve(TreeNode* root, vector<int>& b) {
unordered_set<int>room(b.begin(), b.end());
head = new ListNode(root->val);
ListNode* front = head;
//res.push_back(front);
find_res(root, room, front);
for (auto k : b) {
res.push_back(shuchu[k]);
}
return res;
}
};
第二题:动态规划(75%)
题解:通过构建dp数组,自底向上依次遍历结果,根据查询输出。不过数据n最大位2*10^9,内存不够,只通过了75%
此题与https://leetcode-cn.com/problems/minimum-number-of-days-to-eat-n-oranges/solution/chi-diao-n-ge-ju-zi-de-zui-shao-tian-shu-by-leetco/一样,更好的方法是自顶向下+记忆化搜索的方法。
vector<char>dp(100000001, 0);
void count_change() {
int res = 0;
for (int i = 1; i < dp.size(); ++i) {
dp[i] = dp[i - 1] + 1;
if (i % 2 == 0)
dp[i] = (char)min((int)dp[i], (int)dp[i / 2] + 1);
if (i % 3 == 0)
dp[i] = (char)min((int)dp[i], (int)dp[i / 3] + 1);
}
}
int main()
{
int T;
cin >> T;
count_change();
for (int i = 0; i < T; ++i) {
int k;
cin >> k;
cout << (int)dp[k] << endl;
}
return 0;
}
第三题:排序+优先队列(90%)
对给定的每个数组先进行排序,然后对每次查询,构建一个最大堆,来维护最小的K个数,在填充时,对每个子数组,当其遍历至值大于堆顶时,退出(因为已经有序,后序的必然都大于堆顶)。
更好的方法:排序+二分,判断方法:对每个中值,二分找到最每个子数组中小于它的数量(lower_bound),所有数量求和,大于K说明中值太大,调整边界即可。
vector<vector<int>>All_data;
int main()
{
int T;
cin >> T;
for (int i = 0; i < T; ++i) {
int k;
cin >> k;
vector<int>mid(k);
for (int j = 0; j < k; ++j) {
cin >> mid[j];
}
sort(mid.begin(), mid.end());
All_data.push_back(mid);
}
int Q;
cin >> Q;
for (int i = 0; i < Q; ++i) {
int num, k;
cin >> num;
priority_queue<int>D;
vector<int>index(num);
for (int j = 0; j < num; ++j) {
cin >> index[j];
}
cin >> k;
for (int j = 0; j < num; ++j) {
for (auto d : All_data[index[j] - 1]) {
//cout << d << ' ';
if (D.size() < k)
D.push(d);
else {
if (d < D.top()) {
D.pop();
D.push(d);
}
else
break;
}
}
//cout << endl;
}
cout << D.top() << endl;
}
return 0;
}
第四题:二分(40%)
题解:对排序后的数组进行进行中位数二分,judge函数写的有问题,有情况灭考虑到,只A了40%。
更好的方法:排序方式不对,按照min从小到达排序,再按max从大到小排序,修改好judge函数即可。
bool judge(vector<vector<int>>&data, int target, int W) {
int num = data.size() / 2 + 1;
int Sum = 0;
for (int i = data.size() - 1; i >=0; --i) {
//cout << i << ' ';
if (data[i][1] >= target && num > 0) {
num--;
Sum += target;
}
else if (data[i][1] < target&& num > 0)
return 0;
else{
Sum += data[i][0];
}
}
//cout << endl;
return Sum <= W;
}
int main()
{
int N, W;
cin >> N >> W;
vector< vector<int>>data(N, vector<int>(2));
int l = 1, r = INT32_MIN;
for (int i = 0; i < N; ++i) {
cin >> data[i][0] >> data[i][1];
r = max(r, data[i][1]);
}
sort(data.begin(), data.end());
while (l < r) {
int mid = (l + r) >> 1;
//cout << mid << endl;
if (judge(data, mid, W) == 0)
r = mid;
else
l = mid + 1;
}
if (judge(data, l, W))
cout << l;
else
cout << l - 1;
return 0;
}