引言
该题为leetcode 第870道题。 是看到了 labuladong微信公众号的 算法大师-孙膑 文章,学习了相关的解题技巧,准备再刷以便。但毋庸置疑,肯定会是知道归知道,上手就犯难。故在此,专门记录刷题心路之旅,记录自己的成长。
labladong pc端访问地址: https://labuladong.gitee.io/algo/
开刷
一组牌位置固定,不能动。B
另一组牌,A,位置可变,选出最合适的方式,让优势牌数最大。所谓优势牌,就是在对应位置,比如索引为i上,A[i] > B[i],这就叫优势牌。
我们就是要让这类i的位置尽可能最多。
作者给的思路是,让两组牌,按照大小顺序排序,进行两两对比。 如果能赢,则不换,不能赢,则用当前最小的牌去替换。
就比如田忌赛马:
齐王: 上 中 下
田忌: 上 中 下
如果按照这种顺序比试,赢者必为齐王。因为齐王的马好啊。
那索性:
第一场:田 上 打不过 齐上, 就用田下 打 齐上。
第二场:田上还没用,就用田上,打齐中。 这肯定能打过。
第三场:田中还没用,就用田中,打齐下。这肯定是赢了。
同样的,对于这道题,作者(labuladong)给出了双指针的解法。指针一,指向最大顺序 (也即比赛顺序),指针二,指向最小顺序。当指针一干不过时,上指针二。问题就能解决。
好, 看着懂了。 开始上手!
wait a miniutes…
话说,数组二,不能排序,这个怎么搞? 没关系,用另外的数据结构。用一个优先队列,给定优先级。值为数组二的索引。那么从优先队列取出的索引,就是最大的。问题得到解决。
wait a minitutes…
额,优先队列怎么用? 怎么设置优先级? 又怎么取值?。。。还是查下吧!
升序队列,小根堆:priority_queue <int,vector<int>,greater<int> > p;
·降序队列,大根堆:priority_queue <int,vector<int>,less<int> >q;
·对于基础数据类型,默认是大顶堆:priority_queue<int> r; //等同于 priority_queue<int, vector<int>, less<int> > r;
以上是标准类型。但我们需要记录 数组二的索引信息,因此需要配合pair使用。还需要查下pair的用法。
priority_queuq<type, container, function>;
//默认的情况是priority_queue<int, vector<int>, greater<int>>,即大顶堆,排序显示的从小到大
struct cmp1{
bool operator()(const pair<int, int> &a, const pair<int, int> &b){
return a.first + a.second < b.first + b.second;
}
};
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp1> mp;
//这样在执行mp.push(make_pair(nums[i], nums1[j]));时就会自动的就行排序.
//使用优先队列来模拟堆的运行在c++中是很方便的.
//堆的函数
额,数组或项量的排序,有点忘了,再查下…
可以使用C++内置函数 sort
升序:sort(begin,end,less<data-type>())
降序:sort(begin,end,greater<data-type>())
equal_to<Type>: 等于
not_equal_to<Type>: 不等于
greater<Type>: 大于
greater_equal<Type>: 大于等于
less<Type>: 小于
less_equal<Type>: 小于等于
等等,项量怎么初始化来着?
1.vector < int > v;
v.resize(m); v.resize(n,m)
2.vector < int > v = {1,2,3,4,5};
3.vector < int > v(n); vector < int > v(n,m);
4.vector < int > v(vector1);
5.vector < int > v(*p, *q); 指针或迭代器
好了,下面是调试完成的代码:
#include<queue>
#include<algorithm>
class Solution {
public:
struct cmp{
bool operator ()(pair<int,int>&a,pair<int,int>&b)
{
if(a.first > b.first)
{
return true;
}
else if (a.first <= b.first)
{
return false;
}
return false;
};
};
vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {
vector<int> res=nums1;
if(nums1.size() <=0 || nums2.size() <=0 || nums1.size() != nums2.size())
{
return res;
}
//创建大顶堆优先队列
priority_queue<pair<int,int>,vector<pair<int,int> > > bigQueue;
for(int nIndex=0; nIndex < nums2.size(); nIndex++)
{
pair<int,int>ap(nums2[nIndex],nIndex);
bigQueue.push(ap);
}
//给nums1排序
sort(nums1.begin(),nums1.end(),greater<int>());
//开始比较
int nLeft =0; //左指针
int nRight = nums1.size() - 1; //右指针
while(nLeft <= nRight)
{
pair<int,int> temp = bigQueue.top();
bigQueue.pop();
if(nums1[nLeft] <= temp.first)
{
res[temp.second] = nums1[nRight--];
}
else
{
res[temp.second] = nums1[nLeft++];
}
}
return res;
}
};
总结
开始上手代码时,各种坑,先是语法忘了,后是调试结果不对。没办法,准备放到VS调试,结果发现vs过期了。下载麻烦,于是干脆买了会员。78一个月,略贵。
看来后面得天天练了,毕竟不能浪费钱啊…
怎么说呢,写代码,思路还是比较重要,在没思路前,最好不要先动手。等你想好后,再写,会水到渠成!