比赛题目:https://leetcode-cn.com/contest/weekly-contest-223/.

解码异或后的数组

题目:1720. 解码异或后的数组

还记得数列求和的「累加法」?

已知 encoded[i] = arr[i] ^ arr[i + 1] ,展开之:

e[0] = a[0] ^ a[1]
e[1] = a[1] ^ a[2]
e[2] = a[2] ^ a[3]
...
e[i-1] = a[n-1] ^ a[i]

等号两边所有数字同时异或:

e[0] ^ ... ^ e[i-1] = a[0] ^ a[i]
==>
a[i] = a[0] ^ e[0] ^ ... ^ e[i-1]

代码:

class Solution {
public:
vector<int> decode(vector<int>& encoded, int first) {
int n = encoded.size();
vector<int> a(n+1, first);
int x = 0;
for (int i=1; i<=n; i++)
{
x ^= encoded[i-1];
a[i] ^= x;
}
return a;
}
};

交换链表中的节点

题目:1721. 交换链表中的节点

双指针。

class Solution {
public:
ListNode* swapNodes(ListNode* head, int k) {
if (head == nullptr || head->next == nullptr) return head;
auto p = head, q = head;
int i=0;
for (i=1; i<k && q != nullptr; i++) q = q->next;
// 第 k 个节点
auto t = q;
q = q->next;
if (q == nullptr && i<k) return head;
// 倒数第 k 个节点
while (q != nullptr) p = p->next, q = q->next;
swap(t->val, p->val);
return head;
}
};

执行交换操作后的最小汉明距离

题目:1722. 执行交换操作后的最小汉明距离

类题题目:1202. 交换字符串中的元素

对于 swaps 给出的序列对,可以构成一个图,允许交换的节点(节点的标识符是下标)组成一个联通分量。通过并查集来「分离」出联通分量,记录在 map<int, vector> 中,其 key 值为联通分量的根。

对于每个连通分量,从 sourcetarget 中都能够得到一个对应的集合(具有重复元素的集合),记为 st。该连通分量所贡献的汉明重量就是 st 中不同的元素个数。实际上,这里求的是 st 的对称差集的大小(某些教材称这种运算为环和 \(\bigoplus\))。

下面以输入 source = [1,2,3,4], target = [2,1,4,5], allowedSwaps = [[0,1],[2,3]] 为例。

可以得到 2 个联通分量:

table[0] = [0, 1]
table[2] = [2, 3]

对于连通分量 [0,1],所得集合 s = {1,2}, t = {1,2},没有元素不同,因此贡献的汉明重量为 0 。

对于连通分量 [2,3],所得集合 s = {3,4}, t = {4,5},不同元素个数为 1,因此汉明重量为 1 。

由于输入可能存在重复元素,因此需要使用 multiset .

class Solution {
public:
vector<int> root;
int minimumHammingDistance(vector<int>& source, vector<int>& target, vector<vector<int>>& allowedSwaps) {
int n = source.size();
root.resize(n, -1);
for (auto &v: allowedSwaps) merge(v[0], v[1]);
unordered_map<int, vector<int>> table;
for (int i=0; i<n; i++) table[find(i)].push_back(i); int w = 0;
for (auto &[k,v]: table)
{
unordered_multiset<int> s,t;
for (int i: v) s.insert(source[i]), t.insert(target[i]);
for (int x: s)
{
auto itor = t.find(x);
if (itor == t.end()) w++;
else t.erase(itor);
}
}
return w;
}
int find(int x) { return root[x] == -1 ? x : root[x] = find(root[x]); }
void merge(int x, int y)
{
x = find(x), y = find(y);
if (x != y) root[y] = x;
}
};

完成所有工作的最短时间

题目:1723. 完成所有工作的最短时间

原本的想法是基于贪心实现,初始化一个大小为 k 的优先队列,每次选出当前工作时间最小的工人,分配一个工作,最后求出所有工人工作时间的最大值。但很显然,样例 2 就不满足了。

这是最大值极小化(最小值极大化)类型的题目,使用状态压缩的动态规划。

参考题解

设 \(n\) 为 jobs 的长度,那么 jobs 产生的子集个数为 \(2^n\) , 我们使用 \([0, 2^n]\) 上的整数来标记每个子集。例如:

n = 3, jobs = [1,2,3]
000 => []
001 => [1]
010 => [2]
011 => [1,2]
100 => [3]
101 => [1,3]
110 => [2,3]
111 => [1,2,3]

total[x] 为子集 x 的总工作时间,设子集 x 中的任意一个元素为 j ,则 x - (1 << j) 表示去除元素 j 后的子集,因此有:

total[x] = total[x - (1 << j)] + jobs[j]

注意:这里我们只需要任意的一个 j 即可,比如子集 [1,2,3] ,我们可以通过下面 3 种方法计算:

  • total([1,2,3]) = total([1,2]) + jobs[3]
  • total([1,2,3]) = total([1,3]) + jobs[2]
  • total([1,2,3]) = total([2,3]) + jobs[1]

然后,令 dp[j][i] 为前 j 个工人(包括第 j 个),完成任务集合 i 的最小工作时间。其中,\(0 \le j \le k-1, 0 \le i \le 2^n-1\) . 工人标号从 0k-1 .

对于 dp[j][i] 而言,j 号工人必然完成了某一个子集,因此需要遍历 i 的每一个子集 smax(total[s], dp[j-1][i-s]) 为工人 j 完成子集 s 时的最佳工作时间,然而我们需要的是一个全局最佳的工作时间,所以需要挑选一个最优的子集。

因此状态转移方程为:

\[dp[j][i] = \min_{s \subseteq i}{\{ \max(total[s], dp[j-1][i-s]) \}}
\]

代码:

class Solution
{
public:
int minimumTimeRequired(vector<int> &jobs, int k)
{ int n = jobs.size();
const int m = 1 << n;
vector<int> total(m, 0);
for (int i = 1; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if ((i & (1 << j)) != 0)
{
total[i] = total[i - (1 << j)] + jobs[j];
break;
}
}
}
vector<vector<int>> dp(k, vector<int>(m, 0));
for (int i = 0; i < m; i++) dp[0][i] = total[i];
for (int j = 1; j < k; j++)
{
for (int i = 1; i < m; i++)
{
int val = 0x7fffffff;
for (int s = i; s; s = (s - 1) & i)
val = min(val, max(total[s], dp[j - 1][i - s]));
dp[j][i] = val;
}
}
return dp[k-1][m-1];
}
};

[leetcode] 周赛 223的更多相关文章

  1. 【Leetcode周赛】从contest-111开始。(一般是10个contest写一篇文章)

    Contest 111 (题号941-944)(2019年1月19日,补充题解,主要是943题) 链接:https://leetcode.com/contest/weekly-contest-111 ...

  2. 【一天一道LeetCode】#223. Rectangle Area

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Find th ...

  3. 拼写单词[哈希表]----leetcode周赛150_1001

    题目描述: 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我 ...

  4. 【Leetcode周赛】从contest-41开始。(一般是10个contest写一篇文章)

    Contest 41 ()(题号) Contest 42 ()(题号) Contest 43 ()(题号) Contest 44 (2018年12月6日,周四上午)(题号653—656) 链接:htt ...

  5. 【Leetcode周赛】从contest-51开始。(一般是10个contest写一篇文章)

    Contest 51 (2018年11月22日,周四早上)(题号681-684) 链接:https://leetcode.com/contest/leetcode-weekly-contest-51 ...

  6. 【Leetcode周赛】从contest-71开始。(一般是10个contest写一篇文章)

    Contest 71 () Contest 72 () Contest 73 (2019年1月30日模拟) 链接:https://leetcode.com/contest/weekly-contest ...

  7. 【Leetcode周赛】从contest-81开始。(一般是10个contest写一篇文章)

    Contest 81 (2018年11月8日,周四,凌晨) 链接:https://leetcode.com/contest/weekly-contest-81 比赛情况记录:结果:3/4, ranki ...

  8. 【Leetcode周赛】从contest-91开始。(一般是10个contest写一篇文章)

    Contest 91 (2018年10月24日,周三) 链接:https://leetcode.com/contest/weekly-contest-91/ 模拟比赛情况记录:第一题柠檬摊的那题6分钟 ...

  9. 【Leetcode周赛】从contest-121开始。(一般是10个contest写一篇文章)

    Contest 121 (题号981-984)(2019年1月27日) 链接:https://leetcode.com/contest/weekly-contest-121 总结:2019年2月22日 ...

随机推荐

  1. [GXYCTF2019] MISC杂项题

    buuoj复现 1,佛系青年 下载了之后是一个加密的txt文件和一张图片 分析图片无果,很讨厌这种脑洞题,MISC应该给一点正常的线索加部分脑洞而不是出干扰信息来故意让选手走错方向,当时比赛做这道题的 ...

  2. shell 编程 && bash 简介(shell 变量、shell操作环境、数据流重导向、管线命令、shell script)

    如何学习一门编程语言 数据类型 运算符 关键字 1 认识BASH 这个shell linux是操作系统核心,用户通过shell与核心进行沟通,达到我们想要的目的.硬件.核心.用户之间的关系: 原理:所 ...

  3. sklearn决策树应用及可视化

    from sklearn import datasets from sklearn.tree import DecisionTreeClassifier 1.载入iris数据集(from sklear ...

  4. Java基础学习之流程控制语句(5)

    目录 1.顺序结构 2.选择结构 2.1.if else结构 2.2.switch case结构 3.循环结构 3.1.while结构 3.2.do while结构 3.3.for结构 3.3.1.普 ...

  5. Flutter开发实战笔记

    下载 https://flutter.cn/docs/get-started/install/macos#get-sdk 配置环境变量 export PATH="$PATH:[PATH_TO ...

  6. DVWA各等级sql注入

    sql全等级注入 level:low <?php if( isset( $_REQUEST[ 'Submit' ] ) ) { //判断submit是否存在 // Get input $id = ...

  7. [日常摸鱼]51nod1237-最大公约数之和V3-杜教筛

    题意:求$\sum_{i=1}^n \sum_{j=1}^n gcd(i,j),n<=1e10$ 之前刚好在UVA上也做过一个这样求和的题目,不过那个数据范围比较小,一开始用类似的方法 $ans ...

  8. 处理fMRI数据的一些常用Matlab命令

    背景 处理fMRI数据常常用到MATLAB,在此记录一些常用代码及功能. 1.读取原始DICOM数据 1-1 读入dicom图像并绘图: Image = dicomread('fMRI.dcm'); ...

  9. 网站开发学习Python实现-Django的models学习-生鲜项目(6.3.2)

    @ 目录 1.说明 2.模型类的设计 3.代码的具体实现 4.详情地址 关于作者 1.说明 models是django的很重要的部分,所以深入研究. 本文章的所研究项目为黑马教育python课程中的项 ...

  10. disable_functions Bypass

    参考文章和poc(文中均有poc下载地址) : https://www.uedbox.com/post/59295/ https://www.uedbox.com/post/59402/ 当然 fre ...