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=

浙公网安备 33010602011771号