LeetCode周賽 223
阿新 • • 發佈:2021-01-10
223th
5649. 解碼異或後的陣列
分類:數學
class Solution { public: vector<int> decode(vector<int>& encoded, int first) { vector<int> res(encoded.size() + 1); res[0] = first; for(int i=0; i<res.size()-1; i++){ res[i+1] = res[i]^encoded[i]; } return res; } };
5652. 交換連結串列中的節點
分類:連結串列
class Solution { public: ListNode* swapNodes(ListNode* head, int k) { ListNode *faster = head, *slower = head; for(int i=1; i!=k; i++) { faster=faster->next; } //找到第k個 ListNode* mark = faster; while(faster->next!=NULL) { faster=faster->next; slower=slower->next; } //找到倒數第k個 swap(mark->val, slower->val); return head; } };
// 參考 class Solution { public: ListNode* swapNodes(ListNode* head, int k) { ListNode* p = head;//遍歷用 ListNode* a = head;//指向第k ListNode* b = head;//指向倒數第k for(int i=1; p; i+=1){ if(i<k) a = a->next; if(i>k) b = b->next; p = p->next; } swap(a->val, b->val); return head; } };
5650. 執行交換操作後的最小漢明距離
分類:圖、並查集
如果i
和j
可以交換,j
和k
可以交換,顯然有i
和k
可以交換。用並查集維護這一關係
source
中下標屬於同一個連通分量的對應元素構成一個連同分量,target
同理。
source
和target
對應連通分量的差集的和,即為最小漢明距離
class Solution {
public:
int root(int *u, int i){
while(i != u[i]) i = u[i];
return i;
}
void connect(int *u, int i, int j){
u[root(u, j)] = root(u, i);
}
bool isConnected(int* u, int i, int j){
return root(u, i) == root(u, j);
}
int minimumHammingDistance(vector<int>& source, vector<int>& target, vector<vector<int>>& allowedSwaps) {
int n = source.size(), *u = new int[n];
map<int, multiset<int> > s, t;
for(int i=0; i<n; i++) u[i]=i;
for(int i=0; i<allowedSwaps.size(); i++)
connect(u, allowedSwaps[i][0], allowedSwaps[i][1]);
for(int i=0; i<n; i++){
int r = root(u, i);
if(s.find(r) == s.end()){
s[r] = multiset<int>();
t[r] = multiset<int>();
}
s[r].insert(source[i]);
t[r].insert(target[i]);
}
int res=0;
for(auto it1=s.begin(), it2=t.begin(); it1!=s.end(); ++it1, ++it2){
multiset<int> *s1 = &(*it1).second, *s2 = &(*it2).second;
vector<int> vec_c(max(s1->size(), s2->size()));
auto iter = std::set_difference(s1->begin(), s1->end(), s2->begin(), s2->end(), vec_c.begin());
res += iter - vec_c.begin();
}
return res;
}
};
我麻了,這就是周賽嗎,光理解就花了好久
5639. 完成所有工作的最短時間
分類:動態規劃
關於狀態壓縮
設有一個狀態i∈[0, 2^N)
代表完成這些工作需要的總時間tot[i]
,它的前一個狀態,即某個1改成0,可記為i-2^x
,故tot[i] = tot[i-2^x] + jobs[x]
設dp[j][i]
為前j
個工人,完成狀態i
需要花費的必要工作時間,再假設在這之前有j-1
個工人完成了狀態為i-s
的工作,即第j
個工人完成了狀態為s
的工作,那麼dp[j][i] = max(dp[j-1][i-s], tot[s])
遍歷所有的s
,即可得到最短必要時間dp[j][i]=min(max{dp[j-1][i-s], tot[s]})
class Solution {
public:
int minimumTimeRequired(vector<int>& jobs, int k) {
int n = jobs.size();
vector<int> tot(1<<n, 0);
vector<vector<int> > dp(k+1, vector<int>(1<<n, 0));
//init tot[]
for(int i=1; i<(1<<n); i++){ //i==0時顯然為0
for(int x=0; x<n; x++){
if( (i & (1<<x)) == 0) continue; //說明沒有交集
int left = i - (1<<x);
tot[i] = tot[left] + jobs[x];
break; //?
}
}
//init dp[1] 前1個工人完成狀態i需要時間tot[i]
for(int i=0; i<(1<<n); i++){
dp[1][i] = tot[i];
}
for(int j=2; j<k+1; j++){
for(int i=0; i<(1<<n); i++){
int _min = INT_MAX;
for(int s=i; s; s = (s-1)&i){//遍歷i的子集
int t = max(dp[j-1][i-s], tot[s]);
_min = min(_min, t);
}
dp[j][i] = _min;
}
}
return dp[k][(1<<n)-1];
}
};
弄到現在,累了累了
2021/01/10 2/4