IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode 力扣周赛 256 题解 -> 正文阅读

[数据结构与算法]LeetCode 力扣周赛 256 题解

最近一直打的很烂,赛前安慰自己只要三道题不出错就算进步,结果只做出来两道题,要被自己蠢哭了。

你说是题目变难了吧,老铁们都唰唰的过题。说是自己变菜了吧,这水平下降的也太快了点,照这样下去,下次只能出一道题了。

想了半天,只能是题目变难了,老铁们也变强了,只有我留在原地了,真的太难了。

5854. 学生分数的最小差值

思路:排序,枚举

时间复杂度 O ( n lg ? n ) O(n\lg n) O(nlgn)

首先将 nums 升序排序,则答案为:
min ? 0 ≤ i < n ? k + 1 ( n u m s [ i + k ? 1 ] ? n u m s [ i ] ) \min_{0 \le i \lt n-k+1}(nums[i+k-1]-nums[i]) 0i<n?k+1min?(nums[i+k?1]?nums[i])

class Solution {
public:
    int minimumDifference(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());
        int anw = nums[k-1] - nums[0];
        for (int i = 1; i+k-1 < nums.size(); i++) {
            anw = min(anw, nums[i+k-1] - nums[i]);
        }
        return anw;
    }
};

5855. 找出数组中的第 K 大整数

思路:排序

时间复杂度 O ( n lg ? n ) O(n\lg n) O(nlgn)

因为输入数据不含前导零,所以长字符串对应的数字一定比短字符串的大。因此,可以先通过二级排序将 nums 降序排序,排序后的 nums[k-1] 即为答案。

二级排序规则为:

  • 长度不同的按长度降序排序
  • 长度相同的按字典序降序排序
class Solution {
public:
    string kthLargestNumber(vector<string>& nums, int k) {
        sort(nums.begin(), nums.end(), [](const auto &l, const auto &r) -> bool {
            if (l.size() != r.size()) {
                return l.size() > r.size();
            }
            return l > r;
        });
        return nums[k-1];
    }
};

5856. 完成任务的最少工作时间段

思路:位运算,动态规划,枚举子集

时间复杂度 O ( n ? 2 n + 3 n ) O(n*2^n + 3^n) O(n?2n+3n)

设有长度为 2 n 2^n 2n 的数组 d p dp dp d p m a s k dp_{mask} dpmask? 表示任务完成状态为 m a s k mask mask 时的最小花费。

任务完成状态 m a s k mask mask 可理解为由 n n n 个比特表示的集合,从低位到高位,如果第 i i i 位比特为 1,则表示 t a s k i task_i taski? 已完成,反之未完成。

显然,状态 m a s k mask mask 可划分为两个子状态 a a a b b b,满足:

  • a ? & ? b = 0 a\ \&\ b = 0 a?&?b=0
  • a ? ∣ ? b = m a s k a\ |\ b = mask a??b=mask

换言之, m a s k mask mask 中为 1 的比特,仅在 a a a b b b 中的一个为一,另一个为零。

于是,得到了状态转移方程:
d p m a s k = min ? a & b = 0 , a ∣ b = m a s k ( d p a + d p b ) dp_{mask} = \min_{a\&b=0,a|b=mask}(dp_a + dp_b) dpmask?=a&b=0,ab=maskmin?(dpa?+dpb?)

特别的,当 m a s k mask mask 代表的任务集合的耗时不超过 s e s s i o n T i m e sessionTime sessionTime 时, d p m a s k = 1 dp_{mask} = 1 dpmask?=1

如何枚举 a a a b b b

给定 m a s k mask mask,可通过下述方式枚举 a a a b b b

for (int a = mask, b = 0; a > b; a = (a-1)&mask, b = a^mask) {
  // do something
}

其中关键在于 a=(a-1)&mask

设有 a a a m a s k mask mask 的值如上所示,减法运算和与运算对 a a a 的影响如下图示:

减法运算将 a a a 中「值为 1 」的「最低位」的比特置为 0,并将其后的 0 全置为 1。

与运算将不应变为 1 的比特再置回 0。

这套组合拳可理解为:将 a a a 中那些「在 m a s k mask mask 中的对应比特为 0」的比特删去,然后做减法,这显然可以枚举出 m a s k mask mask 的所有子集。

一个小剪枝

设初始时, a = m a s k , b = 0 a=mask, b=0 a=mask,b=0。随着枚举进行,必然会从 a ≥ b a \ge b ab 变为 a < b a\lt b a<b。显然此时没必要继续枚举下去了,因为 ( a , b ) (a,b) (a,b) ( b , a ) (b,a) (b,a) 是对称的。

时间复杂度

对于包含 n n n 个比特且恰有 k k k 个比特为 1 的 m a s k mask mask,共有 2 k 2^k 2k 个子集,这样的 m a s k mask mask 共有 C n k C_n^k Cnk? 个。因此整体的计算量可用 ( 2 + 1 ) n (2+1)^n (2+1)n 的二项式展开来表示:
$$

\begin{align*}
\sum_{k=0}{n}C_nk2^k&= \sum_{k=0}^{n} C_nk*2k1^{n-k} \
&= (2+1)^n \
&= 3^n \
\end{align*}
$$

class Solution {
public:
    int minSessions(vector<int>& tasks, int sessionTime) {
        int n = tasks.size();
        int m = (1<<n);
        vector<int> sum(m, 0);
        for (int i = 1; i < m; i++) {
            for (int j = 0, b = 1; ; b <<= 1, j++) {
                if (i&b) {
                    sum[i] = sum[i^(b)] + tasks[j];
                    break;
                }
            }
        }

        vector<int> dp(m, numeric_limits<int>::max());
        dp[0] = 0;
        for (int i = 1; i < m; i++) {
            if (sum[i] <= sessionTime) {
                dp[i] = 1;
            } else {
                for (int a = i, b = 0; a > b; a = (a-1)&i, b = a^i) {
                    dp[i] = min(dp[i], dp[a] + dp[b]);
                }
            }
        }
        return dp[m-1];
    }
};

1987. 不同的好子序列数目

思路:动态规划,滚动数组,去重

时间复杂度 O ( n ) O(n) O(n)

假设我们现在有两个集合 z e r o zero zero o n e one one,分别由 ‘0’ 开头的序列和 ‘1’ 开头的序列组成,且其中无重复序列。

现在我们要向所有序列的前面加 ‘1’,构成新的集合 o n e ′ one' one 包含:

  • ∣ z e r o ∣ |zero| zero 个以 ‘10’ 开头的序列
  • ∣ o n e ∣ |one| one 个以 ‘11’ 开头的序列

因为 o n e one one z e r o zero zero 本身无重复,所以 o n e ′ one' one 也无重复。另外, o n e ′ one' one 中的序列长度均大于一,所以将 ‘1’ 插入 o n e ′ one' one 中仍不会有重复。

除了证明 o n e ′ one' one 本身无重复外,还需证明 o n e ? o n e ′ one\subset one' one?one,考虑 o n e one one 中的三类序列:

  • 以 ‘10’ 开头,必然由 z e r o zero zero 的某个子集添加 ‘1’ 而来,这部分必然在 o n e ′ one' one 中。
  • 11 11 11 开头,必然由 o n e one one 的某个子集添加 ‘1’ 而来,这部分必然也在 o n e ′ one' one 中。
  • ‘1’ 本身,我们向 o n e ′ one' one 添加了 ‘1’,所以该序列也在 o n s ′ ons' ons 中。

所以, o n e ? o n e ′ one \subset one' one?one

所以有, ∣ o n e ′ ∣ = ∣ z e r o ∣ + ∣ o n e ∣ + 1 |one'| = |zero| + |one| + 1 one=zero+one+1

同理,向所有序列的前面加 ‘0’,构成的新集合 z e r o ′ zero' zero 包含:

  • ∣ z e r o ∣ |zero| zero 个以 ‘00’ 开头的序列
  • ∣ o n e ∣ |one| one 个以 ‘01’ 开头的序列

同样的,也可将 ‘0’ 插入 z e r o ′ zero' zero 中。

因此, ∣ z e r o ′ ∣ = ∣ z e r o ∣ + ∣ o n e ∣ + 1 |zero'| = |zero| + |one| + 1 zero=zero+one+1

class Solution {
public:
    int numberOfUniqueGoodSubsequences(string binary) {
        int zero = 0, one = 0; // 初始时均为空集合
        int mod = 1e9+7;
        int has_zero = 0; // 判断是否幽灵
        for (int i = binary.size()-1;i >= 0; i--) {
            if (binary[i] == '0') {
                has_zero = 1;
                zero = (zero + one + 1)%mod;
            } else {
                one = (one + zero + 1)%mod;
            }
        }
        return (one + has_zero) % mod;
    }
};
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-02 11:37:50  更:2021-09-02 11:39:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:55:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码