力扣第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;}
};