2021.3.21笔试

第一题:链表遍历+链表复制

题解:由于查询是随机的,跟遍历顺序无关,因此通过哈希记录所有需要查询的节点值。通过前序遍历树并更新路径,在遍历树的过程中判断,哈希表中存在的值就将当前路径链表复制,并将头指针存储在对应节点的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;
}

猜你喜欢

转载自blog.csdn.net/Yanpr919/article/details/115061230
今日推荐