力扣第406场周赛
100352. 交换后字典序最小的字符串 - 力扣(LeetCode)
贪心,从 0 0 0开始扫描到 n n n如果有一个可以交换的就立马交换
class Solution {
public:
string getSmallestString(string s) {
for(int i=1;i<s.size();i++)
{
if(s[i]%2==s[i-1]%2)
{
if(s[i]<s[i-1])
{
swap(s[i],s[i-1]);
break;
}
}
}
return s;
}
};
思路:用 s e t set set把 n u m s nums nums中的元素全放在 s e t set set里,遍历 l i s t list list只要 l i s t − > v a l list->val list−>val在 s e t set set中就删除。
t i p : tip: tip:要创建一个虚拟节点防止越界
class Solution {
public:
ListNode* modifiedList(vector<int>& nums, ListNode* head) {
set<int> st(nums.begin(), nums.end());
ListNode* t = new ListNode(0);
t->next = head;
ListNode* p = t;
while (p->next != nullptr) {
if (st.count(p->next->val)) {
p->next = p->next->next;
} else {
p = p->next;
}
}
ListNode* res = t->next;
return res;
}
};
100367. 切蛋糕的最小总开销 II - 力扣(LeetCode)
T 3 T3 T3和 T 4 T4 T4是一样的无非是 n n n的范围不一样。
比赛的时候没想那么多,直接上了个贪心,没想到AC了
思路是,不管是水平的切还是垂直的切,每次都先把最大的切了,然后再切小的,这个思路是看样例一的动画图猜出来的。
具体证明步骤:
假设水平切第 i i i行的价值 h i h_{i} hi大于竖着切第 i i i列的价值 v i v_{i} vi也就是: h i > v i h_{i}>v_{i} hi>vi
每次切完以后会多出一块。如果是水平切完以后,竖着就要多切一块
例如这样水平切以后,竖着切每次都要多切一次,同理,如果竖着切了一次后,水平也要多切一次
我们记水平块数是 h c i hc_{i} hci,竖块是 v c i vc_{i} vci
我们得先水平切的后竖着切所需要的花费是:
h c i ∗ h i + ( v c i + 1 ) ∗ v i = h c i ∗ h i + v c i ∗ v i + v i hc_{i}*h_{i}+(vc_{i}+1)*v_{i}=hc_{i}*h_{i}+vc_{i}*v_{i}+v_i hci∗hi+(vci+1)∗vi=hci∗hi+vci∗vi+vi①
然后我们先竖着切后水平切的花费是
v c i ∗ v i + ( h c i + 1 ) ∗ h i = v c i ∗ v i + h c i ∗ h i + h i vc_i*v_i+(hc_i+1)*h_i=vc_i*v_i+hc_i*h_i+h_i vci∗vi+(hci+1)∗hi=vci∗vi+hci∗hi+hi②
因为 h i > v i h_{i}>v_{i} hi>vi所以①<②得证
typedef pair<int,char>pii;
class Solution {
public:
long long minimumCost(int m, int n, vector<int>& h, vector<int>& v) {
priority_queue<pii>q;
for(auto x:h)
q.push({x,'h'});
for(auto x:v)
q.push({x,'v'});
int hc=1,vc=1;
long long res=0;
while(q.size())
{
auto t=q.top();
q.pop();
if(t.second=='h')
{
res+=hc*t.first;
vc++;
}
else
{
res+=vc*t.first;
hc++;
}
}
return res;
}
};