开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
[870. 优势洗牌]
本题结果数组要满足ret[i] > nums2[i]的个数最多, 本质是田径赛马问题!讨论田忌的下等马(nums1的最小值):
- 如果它能比过齐威王的下等马(nums2的最小值),那这一分田忌直接拿下
- 如果它比不过齐威王的下等马,则用田忌的下等马比齐威王的上等马(nums2的最大值)
从对手战力最弱的🐎开始,每次从 自己未出场 且 战力大于对手的这匹🐎 的🐎中挑选战力最小的一匹,如果没有🐎可以匹配,则用自己最弱的🐎去丢掉这一局
做法1:超时 每次在nums1中寻找大于nums2的最小值,若没有,则使用nums1中的最小值 O(N^2)
class Solution {
public:
vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {
vector<int> ans;
sort(nums1.begin(),nums1.end());//对nums1进行排序
for(int i = 0;i<nums2.size();i++)
{
bool flag = false;
for(int j = 0;j<nums1.size();j++)
{
if(nums1[j] > nums2[i])
{
ans.push_back(nums1[j]);
nums1.erase(nums1.begin()+j);//移除nums1[j]这个元素
flag = true;
break;
}
}
//当前nums1的,没有任何数比nums2[i]大,则使用nums1中最小的数字
if(!flag)
{
ans.push_back(nums1[0]);
nums1.erase(nums1.begin());
}
}
return ans;
}
};
方法2: 利用multiset 二分查找法
那么对于nums2[i],只要从数组nums1中找到第一个比nums2[i]大且没用过的元素即可,很容易想到二分法
class Solution {
public:
vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {
//将nums1存入multiset(会自动进行排序)
//遍历nums2,假设当前值为x,在multiset中二分查找>x的值的位置(upper_bound)返回的是迭代器
//如果找到:就使用该位置的值填入对应位置(该位置有优势) ,并从multiset删除该元素
//如果找不到,就使用multiset当前最小的值填入当前位置(放弃该位置的优势),并从multiset中删除该最小值
multiset<int> mt(nums1.begin(),nums1.end());//自动排好序
for(int i = 0;i<nums2.size();i++)
{
auto pos = mt.upper_bound(nums2[i]);//二分查找>nums2[i]的值的位置
if(pos == mt.end())//没有找到
{
pos = mt.begin();//用当前最小的数匹配
}
nums1[i] = *pos;//复用nums1的空间,不需要额外开辟空间!
mt.erase(pos);//把这个数删除掉
}
return nums1;
}
};
[856. 括号的分数]
求各个 '()' 在它所在层的分数, 然后加起来
class Solution {
public:
//出现 '(' 代表层数+1 , 出现 ')' 代表层数 -1
//(()(()))
//(() +2^(2-1)
//((() +2^(3-1))
//求的是(2的(当前括号的深度-1))的平方的值,
int scoreOfParentheses(string S) {
int deep=0,ans=0;
for(int i=0;i<S.length();i++){
if(S[i] == '(')
deep++;
else
deep--;
if(S[i]==')' && S[i-1]=='(')
ans += 1 << deep;
}
return ans;
}
};