网易游戏8.11笔试洪水题优化思路

因为第三题浪费了点时间,第四题没什么时间做,直接Brute Force走了o(nq)的解法,毫无疑问只剩40%的AC率。。。
然后看时间不够,就懒得继续写了。
搞完之后想想优化思路,有以下一个优化思路,估计应该是最优解了。

建立一个辅助数据结构标注 高度,种类,下标。
种类分为水位:-1/尚未被淹的基站:0/被淹的基站:1
然后把基站和洪水放一起根据高度排序,记录当前基站集群的数量,初始为1。
然后从头遍历,每遇到一个洪水,遍历该洪水淹的基站。
若该基站左右的基站都尚未被淹,则集群数量+1;
若该基站左右的基站其中一个被淹,或本就是边缘基站,则集群数量不变;
若该基站左右的基站都已经被淹,则集群数量-1;
最后将计算完的集群数量放在数组里,对应该洪水的下标位置。

最后统一输出

时间复杂度:O((n+q)log(n+q))

-----
昂,有点无聊,贴一下代码吧。
#include <stdio.h>
#include <vector>
#include <algorithm>
#pragma warning(disable:4996)
using namespace std;
class Node{
public:
	int h;
	int type;
	int idx;
	Node(int h, int type, int idx):h(h),type(type),idx(idx) {}
};
int main() {
	int n, q, y, group = 1;
	scanf("%d", &n);
	Node **base = new Node*[n];
	for (int i = 0; i < n; ++i) {
		scanf("%d", &y);
		base[i] = new Node(y, 0, i);
	}
	scanf("%d", &q);
	int size = n + q;
	Node ** nodes = new Node*[size];
	for (int i = 0; i < q; ++i) {
		scanf("%d", &y);
		nodes[i] = new Node(y, -1, i);
	}
	for (int i = 0; i < n; ++i) nodes[i + q] = base[i];
	sort(nodes, nodes + n + q, [](Node* pre, Node* post) {return pre->h == post->h ? pre->type > post->type : pre->h < post->h;});

	vector<Node*> vec;
	int* res = new int[q];
	for (int i = 0; i < size; ++i) {
		switch (nodes[i]->type)
		{
		case -1:
			for (Node* node : vec) {
				int sink = 0;
				if (node->idx == 0 || base[node->idx - 1]->type == 1) ++sink;
				if (node->idx == n - 1 || base[node->idx + 1]->type == 1) ++sink;
				group += (sink == 0 ? 1 : (sink == 1 ? 0 : -1));
				node->type = 1;
			}
			res[nodes[i]->idx] = group;
			vec.clear();
			break;
		case 0:
			vec.push_back(nodes[i]);
			break;
		}
	}
	for_each(res, res + q, [](int v) {printf("%d\n", v); });
	return 0;
}
/*
10
6 12 20 14 15 15 7 19 18 13
6
15 23 19 1 17 24

*/



#笔试题目#
全部评论
昂,还可以继续优化:应该不需要对两个数组进行合并。两个分别排序就行了。。。然后按洪水组遍历就行
点赞 回复 分享
发布于 2019-08-11 20:41

相关推荐

头像
10-22 19:18
上海大学 后端
jopajhhdjwnqk:水印都叠杀人书了
点赞 评论 收藏
分享
10-31 14:54
已编辑
门头沟学院 算法工程师
点赞 评论 收藏
分享
点赞 3 评论
分享
牛客网
牛客企业服务