算法系列-优势洗牌

引言

该题为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一个月,略贵。
看来后面得天天练了,毕竟不能浪费钱啊…

怎么说呢,写代码,思路还是比较重要,在没思路前,最好不要先动手。等你想好后,再写,会水到渠成!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值