题目描述
一、思路
用最大堆来实现。然后再加上用个bfs来扫描周围的最大值。
即:
- 将右下角唯一知道的最大值压入最大堆;
- 弹出最大堆中最大的值,这个值就可以加入最终结果中;
- 将这个最大值的左边节点和上边节点加入最大堆中。
- 继续步骤2.的操作。直到压入了k个答案。
二、难点:
1、标记地址
堆中数据弹出,虽然知道是最大的,但是并不知道其所在坐标。
需要自己定一个数据结构。其中包含了val,和其坐标x、y;
然后定义最大堆的时候,用这个数据结构的val来作为构建堆时比较的值。
我使用了stl中的优先队列,定义的时候,可以声明其比较函数。
2、去重
单纯的这样bfs 可能会进到重复的坐标中。使得一个坐标的值进入两次。
我用集合 set来标记对应坐标,防止一个坐标重复进堆。
三、代码
struct nodde {
int val;
int x;
int y;
};
class mycomparison
{
public:
bool operator() (const nodde& lhs, const nodde&rhs) const
{
return (lhs.val < rhs.val);
}
};
vector<int> topK(vector<int> &arr1, vector<int>&arr2, int k)
{
int cur1 = arr1.size() - 1, cur2 = arr2.size() - 1;
priority_queue<nodde, std::vector<nodde>, mycomparison >
my_heap;
vector<int> result;
nodde temp, temp1, temp2;
temp.val = arr1[cur1] + arr2[cur2];
unordered_set<string> my_set;
temp.x = cur1;
temp.y = cur2;
my_heap.push(temp);
my_set.insert(to_string(cur1)+","+to_string(cur2));
int cnt = 0;
while (cnt < k)
{
temp = my_heap.top();
my_heap.pop();
temp1.x = temp.x - 1;
temp1.y = temp.y;
// if(temp.x>=0&&temp1.y>=0)
temp1.val = arr1[temp1.x] + arr2[temp1.y];
temp2.x = temp.x;
temp2.y = temp.y - 1;
temp2.val = arr1[temp2.x] + arr2[temp2.y];
result.push_back(temp.val);
if(my_set.count(to_string(temp1.x)+","+to_string(temp1.y)) ==0)
{
my_heap.push(temp1);
my_set.insert(to_string(temp1.x)+","+to_string(temp1.y));
}
if(my_set.count(to_string(temp2.x)+","+to_string(temp2.y)) ==0)
{
my_heap.push(temp2);
my_set.insert(to_string(temp2.x)+","+to_string(temp2.y));
}
cnt++;
}
return result;
}
四、实现:
int main()
{
int N,K;
cin>>N>>K;
vector<int> arr1(N);
vector<int> arr2(N);
vector<int> res;
for(int i=0;i<N;i++){
cin>>arr1[i];
}
for(int i=0;i<N;i++){
cin>>arr2[i];
}
res = topK(arr1,arr2,K);
for(int i=0;i<res.size();i++){
cout<<res[i]<<" ";
}
cout<<endl;
return 0;
}
五、更进一步
更进一步可以自己手撕一个最大堆。有时间可以试一试
相对来说有些费时间。
六、其他做法
看到了别人的做法,觉得很棒。思路讲出来作为这种做法的另一种实现吧。
3、思路
也是用优先队列实现,但是不用自己写一个比较函数。
直接构建数据结构的时候重载了比较函数。于是最大堆在比较的时候,直接按照sum比较。
思路一样,只是实现手段不同。记录一下。
class Node {
public:
int lindex;
int rindex;
int sum;
public:
Node(int l, int r, int s) {
lindex = l;
rindex = r;
sum = s;
}
//必须重载
friend bool operator< (Node l, Node r) {
return l.sum < r.sum;//从小到大排序
}
};
参考自:https://www.nowcoder.com/profile/417326246
考察的点:
- 优先队列的理解。
- TOP K 问题的理解。
- 数据结构的熟悉