Leetcode 870. 优势洗牌(中等) 田忌赛马策略
题目:
给你输入两个长度相等的数组 nums1
和 nums2
,请你重新组织 nums1
中元素的位置,使得 nums1
的「优势」最大化。
如果 nums1[i] > nums2[i]
,就是说 nums1
在索引 i
上对 nums2[i]
有「优势」。优势最大化也就是说让你重新组织 nums1
,尽可能多的让 nums[i] > nums2[i]
。
比如输入:
nums1 = [12,24,8,32]
nums2 = [13,25,32,11]
你的算法应该返回 [24,32,8,12]
,因为这样排列 nums1
的话有三个元素都有「优势」。
思路:
我们暂且把田忌的一号选手称为 T1
,二号选手称为 T2
,齐王的一号选手称为 Q1
。
如果 T2
能赢 Q1
,你试图保存己方实力,让 T2
去战 Q1
,把 T1
留着是为了对付谁?
显然,你担心齐王还有战力大于 T2
的马,可以让 T1
去对付。
但是你仔细想想,现在 T2
已经是可以战胜 Q1
的,Q1
可是齐王的最快的马耶,齐王剩下的那些马里,怎么可能还有比 T2
更强的马?
所以,没必要节约,最后我们得出的策略就是:
将齐王和田忌的马按照战斗力排序,然后按照排名一一对比。如果田忌的马能赢,那就比赛,如果赢不了,那就换个垫底的来送人头,保存实力。
将nums1从大到小排序,按照num2从大到小的顺序,逐个比较num1对应位置的大小,如果nums1[left]>nums2,就设为left值,否则设为right值(最小值)
class Solution { public: vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) { //记录nums2的值及位置 priority_queue<Node> q; for(int i=0;i<nums2.size();++i){ q.push(Node(i,nums2[i])); } //nums1从大到小排序 sort(nums1.begin(),nums1.end(),[](int a,int b){ return a>b; }); //使用双指针记录nums1的最大值和最小值 int left=0,right=nums1.size()-1; vector<int> ret(nums1.size()); for(int i=0;i<nums1.size();++i){ Node node=q.top(); q.pop(); int val=node.val; int id=node.id; //如果nums1对应位置大于nums2,设为该值 if(nums1[left]>val){ ret[id]=nums1[left++]; }else{ //如果小于,则设为nums1的最小值 ret[id]=nums1[right--]; } } return ret; } struct Node{ int id; int val; Node(int i,int v){ id=i; val=v; } //priority_queue默认为大根堆,因此使用less来比较 bool operator<(const Node& b) const{ return val<b.val; } }; };
联系方式:emhhbmdfbGlhbmcxOTkxQDEyNi5jb20=