56.合并区间、57.插入区间、636.函数的独占时间、761.特殊的二进制序列、986.区间列表的交集、1288.删除被覆盖区间、1413.逐步求和得到正数的最小值

This commit is contained in:
游由 2022-08-08 16:47:00 +08:00
parent a20d9cd7e4
commit cbc454169c
8 changed files with 454 additions and 0 deletions

View File

@ -24,6 +24,8 @@ mod q0046;
mod q0048;
mod q0053;
mod q0055;
mod q0056;
mod q0057;
mod q0058;
mod q0066;
mod q0067;
@ -128,6 +130,7 @@ mod q0617;
mod q0623;
mod q0628;
mod q0633;
mod q0636;
mod q0643;
mod q0674;
mod q0684;
@ -140,6 +143,7 @@ mod q0724;
mod q0733;
mod q0740;
mod q0746;
mod q0761;
mod q0778;
mod q0781;
mod q0783;
@ -159,6 +163,7 @@ mod q0947;
mod q0959;
mod q0965;
mod q0977;
mod q0986;
mod q0989;
mod q0995;
mod q1006;
@ -175,10 +180,12 @@ mod q1202;
mod q1203;
mod q1218;
mod q1269;
mod q1288;
mod q1310;
mod q1374;
mod q1403;
mod q1408;
mod q1413;
mod q1447;
mod q1473;
mod q1482;

View File

@ -0,0 +1,48 @@
use crate::Solution;
impl Solution {
/// [56.合并区间](https://leetcode.cn/problems/merge-intervals/)
///
/// 2022-08-08 14:19:46
///
/// 以数组 `intervals` 表示若干个区间的集合,其中单个区间为 `intervals[i] = [starti, endi]` 。请你合并所有重叠的区间,并返回 _一个不重叠的区间数组该数组需恰好覆盖输入中的所有区间_ 。
///
/// + **示例 1**
/// + **输入:** intervals = \[\[1,3\],\[2,6\],\[8,10\],\[15,18\]\]
/// + **输出:** \[\[1,6\],\[8,10\],\[15,18\]\]
/// + **解释:** 区间 \[1,3\] 和 \[2,6\] 重叠, 将它们合并为 \[1,6\].
/// + **示例 2**
/// + **输入:** intervals = \[\[1,4\],\[4,5\]\]
/// + **输出:** \[\[1,5\]\]
/// + **解释:** 区间 \[1,4\] 和 \[4,5\] 可被视为重叠区间。
/// + **提示:**
/// * `1 <= intervals.length <= 104`
/// * `intervals[i].length == 2`
/// * `0 <= starti <= endi <= 104`
/// + Related Topics
/// * 数组
/// * 排序
pub fn merge1(mut intervals: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
intervals.sort_unstable_by_key(|i| i[0]);
let mut merged = Vec::<Vec<i32>>::new();
for interval in intervals.into_iter() {
if merged.is_empty() || merged[merged.len() -1][1] < interval[0] {
merged.push(interval);
} else {
let last = merged.last_mut().unwrap();
last[1] = last[1].max(interval[1]);
}
}
merged
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0056() {
assert_eq!(Solution::merge1(vec![vec![1, 3], vec![2, 6], vec![8, 10], vec![15, 18]]), vec![vec![1, 6], vec![8, 10], vec![15, 18]]);
}
}

View File

@ -0,0 +1,70 @@
use crate::Solution;
impl Solution {
/// [57.插入区间](https://leetcode.cn/problems/insert-interval/)
///
/// 2022-08-08 15:01:19
///
/// 给你一个 **无重叠的** __按照区间起始端点排序的区间列表。
///
/// 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
///
/// + **示例 1**
/// + **输入:** intervals = \[\[1,3\],\[6,9\]\], newInterval = \[2,5\]
/// + **输出:** \[\[1,5\],\[6,9\]\]
/// + **示例 2**
/// + **输入:** intervals = \[\[1,2\],\[3,5\],\[6,7\],\[8,10\],\[12,16\]\], newInterval = \[4,8\]
/// + **输出:** \[\[1,2\],\[3,10\],\[12,16\]\]
/// + **解释:** 这是因为新的区间 `[4,8]` 与 `[3,5],[6,7],[8,10]` 重叠。
/// + **示例 3**
/// + **输入:** intervals = \[\], newInterval = \[5,7\]
/// + **输出:** \[\[5,7\]\]
/// + **示例 4**
/// + **输入:** intervals = \[\[1,5\]\], newInterval = \[2,3\]
/// + **输出:** \[\[1,5\]\]
/// + **示例 5**
/// + **输入:** intervals = \[\[1,5\]\], newInterval = \[2,7\]
/// + **输出:** \[\[1,7\]\]
/// + **提示:**
/// * `0 <= intervals.length <= 104`
/// * `intervals[i].length == 2`
/// * `0 <= intervals[i][0] <= intervals[i][1] <= 105`
/// * `intervals` 根据 `intervals[i][0]` 按 **升序** 排列
/// * `newInterval.length == 2`
/// * `0 <= newInterval[0] <= newInterval[1] <= 105`
/// + Related Topics
/// * 数组
pub fn insert(intervals: Vec<Vec<i32>>, new_interval: Vec<i32>) -> Vec<Vec<i32>> {
let (mut l, mut r): (i32, i32) = (new_interval[0], new_interval[1]);
let mut placed = false;
let mut ans = Vec::<Vec<i32>>::new();
for interval in intervals {
if interval[0] > r {
if !placed {
ans.push(vec![l, r]);
placed = true;
}
ans.push(interval);
} else if interval[1] < l {
ans.push(interval);
} else {
l = l.min(interval[0]);
r = r.max(interval[1]);
}
}
if !placed {
ans.push(vec![l, r]);
}
ans
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0057() {
assert_eq!(Solution::insert(vec![vec![1, 2], vec![3, 5], vec![6, 7], vec![8, 10], vec![12, 16]], vec![4, 8]), vec![vec![1, 2], vec![3, 10], vec![12, 16]]);
}
}

View File

@ -0,0 +1,97 @@
use std::collections::vec_deque::VecDeque;
use crate::Solution;
impl Solution {
/// [636.函数的独占时间](https://leetcode.cn/problems/exclusive-time-of-functions/)
///
/// 2022-08-08 10:25:21
///
/// 有一个 **单线程** CPU 正在运行一个含有 `n` 道函数的程序。每道函数都有一个位于 `0` 和 `n-1` 之间的唯一标识符。
///
/// 函数调用 **存储在一个 [调用栈](https://baike.baidu.com/item/%E8%B0%83%E7%94%A8%E6%A0%88/22718047?fr=aladdin) 上** :当一个函数调用开始时,它的标识符将会推入栈中。而当一个函数调用结束时,它的标识符将会从栈中弹出。标识符位于栈顶的函数是 **当前正在执行的函数** 。每当一个函数开始或者结束时,将会记录一条日志,包括函数标识符、是开始还是结束、以及相应的时间戳。
///
/// 给你一个由日志组成的列表 `logs` ,其中 `logs[i]` 表示第 `i` 条日志消息,该消息是一个按 `"{function_id}:{"start" | "end"}:{timestamp}"` 进行格式化的字符串。例如,`"0:start:3"` 意味着标识符为 `0` 的函数调用在时间戳 `3` 的 **起始开始执行** ;而 `"1:end:2"` 意味着标识符为 `1` 的函数调用在时间戳 `2` 的 **末尾结束执行**。注意,函数可以 **调用多次,可能存在递归调用** 。
///
/// 函数的 **独占时间** 定义是在这个函数在程序所有函数调用中执行时间的总和,调用其他函数花费的时间不算该函数的独占时间。例如,如果一个函数被调用两次,一次调用执行 `2` 单位时间,另一次调用执行 `1` 单位时间,那么该函数的 **独占时间** 为 `2 + 1 = 3` 。
///
/// 以数组形式返回每个函数的 **独占时间** ,其中第 `i` 个下标对应的值表示标识符 `i` 的函数的独占时间。
///
/// + **示例 1**
/// + ![](https://assets.leetcode.com/uploads/2019/04/05/diag1b.png)
/// + **输入:** n = 2, logs = \["0:start:0","1:start:2","1:end:5","0:end:6"\]
/// + **输出:** \[3,4\]
/// + **解释:**
/// + 函数 0 在时间戳 0 的起始开始执行,执行 2 个单位时间,于时间戳 1 的末尾结束执行。
/// + 函数 1 在时间戳 2 的起始开始执行,执行 4 个单位时间,于时间戳 5 的末尾结束执行。
/// + 函数 0 在时间戳 6 的开始恢复执行,执行 1 个单位时间。
/// + 所以函数 0 总共执行 2 + 1 = 3 个单位时间,函数 1 总共执行 4 个单位时间。
/// + **示例 2**
/// + **输入:** n = 1, logs = \["0:start:0","0:start:2","0:end:5","0:start:6","0:end:6","0:end:7"\]
/// + **输出:** \[8\]
/// + **解释:**
/// + 函数 0 在时间戳 0 的起始开始执行,执行 2 个单位时间,并递归调用它自身。
/// + 函数 0递归调用在时间戳 2 的起始开始执行,执行 4 个单位时间。
/// + 函数 0初始调用恢复执行并立刻再次调用它自身。
/// + 函数 0第二次递归调用在时间戳 6 的起始开始执行,执行 1 个单位时间。
/// + 函数 0初始调用在时间戳 7 的起始恢复执行,执行 1 个单位时间。
/// + 所以函数 0 总共执行 2 + 4 + 1 + 1 = 8 个单位时间。
/// + **示例 3**
/// + **输入:** n = 2, logs = \["0:start:0","0:start:2","0:end:5","1:start:6","1:end:6","0:end:7"\]
/// + **输出:** \[7,1\]
/// + **解释:**
/// + 函数 0 在时间戳 0 的起始开始执行,执行 2 个单位时间,并递归调用它自身。
/// + 函数 0递归调用在时间戳 2 的起始开始执行,执行 4 个单位时间。
/// + 函数 0初始调用恢复执行并立刻调用函数 1 。
/// + 函数 1在时间戳 6 的起始开始执行,执行 1 个单位时间,于时间戳 6 的末尾结束执行。
/// + 函数 0初始调用在时间戳 7 的起始恢复执行,执行 1 个单位时间,于时间戳 7 的末尾结束执行。
/// + 所以函数 0 总共执行 2 + 4 + 1 = 7 个单位时间,函数 1 总共执行 1 个单位时间。
/// + **示例 4**
/// + **输入:** n = 2, logs = \["0:start:0","0:start:2","0:end:5","1:start:7","1:end:7","0:end:8"\]
/// + **输出:** \[8,1\]
/// + **示例 5**
/// + **输入:** n = 1, logs = \["0:start:0","0:end:0"\]
/// + **输出:** \[1\]
/// + **提示:**
/// * `1 <= n <= 100`
/// * `1 <= logs.length <= 500`
/// * `0 <= function_id < n`
/// * `0 <= timestamp <= 109`
/// * 两个开始事件不会在同一时间戳发生
/// * 两个结束事件不会在同一时间戳发生
/// * 每道函数都有一个对应 `"start"` 日志的 `"end"` 日志
/// + Related Topics
/// * 栈
/// * 数组
pub fn exclusive_time(n: i32, logs: Vec<String>) -> Vec<i32> {
let mut stack = VecDeque::<(usize, i32)>::new();
let mut ans = vec![0; n as usize];
for log in logs {
let sp = log.split(':').collect::<Vec<&str>>();
let (i, b, t) = (sp[0].parse::<usize>().unwrap(), sp[1].starts_with('s'), sp[2].parse::<i32>().unwrap());
if b {
if !stack.is_empty() {
ans[stack.front().unwrap().0] += t - stack.front().unwrap().1;
stack.front_mut().unwrap().1 = t;
}
stack.push_front((i, t));
} else {
let top = stack.pop_front().unwrap();
ans[top.0] += t - top.1 + 1;
if !stack.is_empty() {
stack.front_mut().unwrap().1 = t + 1;
}
}
}
ans
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0636() {
assert_eq!(Solution::exclusive_time(2, vec!["0:start:0".to_owned(),"0:start:2".to_owned(),"0:end:5".to_owned(),"1:start:6".to_owned(),"1:end:6".to_owned(),"0:end:7".to_owned()]), vec![7, 1]);
}
}

View File

@ -0,0 +1,59 @@
use crate::Solution;
impl Solution {
/// [761.特殊的二进制序列](https://leetcode.cn/problems/special-binary-string/)
///
/// 2022-08-08 16:02:58
///
/// 特殊的二进制序列是具有以下两个性质的二进制序列:
///
/// * 0 的数量与 1 的数量相等。
/// * 二进制序列的每一个前缀码中 1 的数量要大于等于 0 的数量。
///
/// 给定一个特殊的二进制序列 `S`以字符串形式表示。定义一个_操作_ 为首先选择 `S` 的两个连续且非空的特殊的子串,然后将它们交换。(两个子串为连续的当且仅当第一个子串的最后一个字符恰好为第二个子串的第一个字符的前一个字符。)
///
/// 在任意次数的操作之后,交换后的字符串按照字典序排列的最大的结果是什么?
///
/// + **示例 1:**
/// + **输入:** S = "11011000"
/// + **输出:** "11100100"
/// + **解释:**
/// + 将子串 "10" 在S\[1\]出现) 和 "1100" 在S\[3\]出现)进行交换。
/// + 这是在进行若干次操作后按字典序排列最大的结果。
/// + **说明:**
/// 1. `S` 的长度不超过 `50`。
/// 2. `S` 保证为一个满足上述定义的_特殊_ 的二进制序列。
/// + Related Topics
/// * 递归
/// * 字符串
pub fn make_largest_special(s: String) -> String {
if s.len() <= 2 {
return s;
}
let (mut cnt, mut left) = (0, 0);
let mut subs = Vec::<String>::new();
for i in 0..s.len() {
if &s[i..i+1] == "1" {
cnt += 1;
} else {
cnt -= 1;
if cnt == 0 {
subs.push(format!("1{}0", Solution::make_largest_special((&s[left + 1..i]).to_owned())));
left = i + 1;
}
}
}
subs.sort_unstable_by(|a, b|b.cmp(a));
subs.into_iter().collect::<String>()
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0761() {
assert_eq!(Solution::make_largest_special("11011000".to_owned()), "11100100".to_owned());
}
}

View File

@ -0,0 +1,66 @@
use crate::Solution;
impl Solution {
/// [986.区间列表的交集](https://leetcode.cn/problems/interval-list-intersections/)
///
/// 2022-08-08 13:57:51
///
/// 给定两个由一些 **闭区间** 组成的列表,`firstList` 和 `secondList` ,其中 `firstList[i] = [starti, endi]` 而 `secondList[j] = [startj, endj]` 。每个区间列表都是成对 **不相交** 的,并且 **已经排序** 。
///
/// 返回这 **两个区间列表的交集** 。
///
/// 形式上,**闭区间** `[a, b]`(其中 `a <= b`)表示实数 `x` 的集合,而 `a <= x <= b` 。
///
/// 两个闭区间的 **交集** 是一组实数,要么为空集,要么为闭区间。例如,`[1, 3]` 和 `[2, 4]` 的交集为 `[2, 3]` 。
///
/// + **示例 1**
/// + ![](https://assets.leetcode.com/uploads/2019/01/30/interval1.png)
/// + **输入:** firstList = \[\[0,2\],\[5,10\],\[13,23\],\[24,25\]\], secondList = \[\[1,5\],\[8,12\],\[15,24\],\[25,26\]\]
/// + **输出:** \[\[1,2\],\[5,5\],\[8,10\],\[15,23\],\[24,24\],\[25,25\]\]
/// + **示例 2**
/// + **输入:** firstList = \[\[1,3\],\[5,9\]\], secondList = \[\]
/// + **输出:** \[\]
/// + **示例 3**
/// + **输入:** firstList = \[\], secondList = \[\[4,8\],\[10,12\]\]
/// + **输出:** \[\]
/// + **示例 4**
/// + **输入:** firstList = \[\[1,7\]\], secondList = \[\[3,10\]\]
/// + **输出:** \[\[3,7\]\]
/// + **提示:**
/// * `0 <= firstList.length, secondList.length <= 1000`
/// * `firstList.length + secondList.length >= 1`
/// * `0 <= starti < endi <= 109`
/// * `endi < starti+1`
/// * `0 <= startj < endj <= 109`
/// * `endj < startj+1`
/// + Related Topics
/// * 数组
/// * 双指针
pub fn interval_intersection(first_list: Vec<Vec<i32>>, second_list: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let mut ans = vec![];
let (mut i, mut j) = (0usize, 0usize);
while i < first_list.len() && j < second_list.len() {
let l = first_list[i][0].max(second_list[j][0]);
let h = first_list[i][1].min(second_list[j][1]);
if l <= h {
ans.push(vec![l, h]);
}
if first_list[i][1] < second_list[j][1] {
i += 1;
} else {
j += 1;
}
}
ans
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0986() {
assert_eq!(Solution::interval_intersection(vec![vec![0, 2], vec![5, 10], vec![13, 23], vec![24, 25]], vec![vec![1, 5], vec![8, 12], vec![15, 24], vec![25, 26]]), vec![vec![1, 2], vec![5, 5], vec![8, 10], vec![15, 23], vec![24, 24], vec![25, 25]]);
}
}

View File

@ -0,0 +1,46 @@
use crate::Solution;
impl Solution {
/// [1288.删除被覆盖区间](https://leetcode.cn/problems/remove-covered-intervals/)
///
/// 2022-08-08 15:13:53
///
/// 给你一个区间列表,请你删除列表中被其他区间所覆盖的区间。
///
/// 只有当 `c <= a` 且 `b <= d` 时,我们才认为区间 `[a,b)` 被区间 `[c,d)` 覆盖。
///
/// 在完成所有删除操作后,请你返回列表中剩余区间的数目。
///
/// + **示例:**
/// + **输入:** intervals = \[\[1,4\],\[3,6\],\[2,8\]\]
/// + **输出:** 2
/// + **解释:** 区间 \[3,6\] 被区间 \[2,8\] 覆盖,所以它被删除了。
/// + **提示:**
/// * `1 <= intervals.length <= 1000`
/// * `0 <= intervals[i][0] < intervals[i][1] <= 10^5`
/// * 对于所有的 `i != j``intervals[i] != intervals[j]`
/// + Related Topics
/// * 数组
/// * 排序
pub fn remove_covered_intervals(mut intervals: Vec<Vec<i32>>) -> i32 {
intervals.sort_unstable_by(|a, b| a[0].cmp(&b[0]).then(b[1].cmp(&a[1])));
let (mut ans, mut r_max) = (intervals.len(), intervals[0][1]);
for i in 1..intervals.len() {
match intervals[i][1] <= r_max {
true => ans -= 1,
_ => r_max = r_max.max(intervals[i][1])
}
}
ans as i32
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q1288() {
assert_eq!(Solution::remove_covered_intervals(vec![vec![1, 4], vec![3, 6], vec![2, 8]]), 2);
}
}

View File

@ -0,0 +1,61 @@
use crate::Solution;
impl Solution {
/// [1413.逐步求和得到正数的最小值](https://leetcode.cn/problems/minimum-value-to-get-positive-step-by-step-sum/)
///
/// 2022-08-08 16:32:11
///
/// 给你一个整数数组 `nums` 。你可以选定任意的 **正数** startValue 作为初始值。
///
/// 你需要从左到右遍历 `nums` 数组,并将 startValue 依次累加上 `nums` 数组中的值。
///
/// 请你在确保累加和始终大于等于 1 的前提下,选出一个最小的 **正数** 作为 startValue 。
///
/// + **示例 1**
/// + **输入:** nums = \[-3,2,-3,4,2\]
/// + **输出:** 5
/// + **解释:** 如果你选择 startValue = 4在第三次累加时和小于 1 。
/// ```txt
/// 累加求和 startValue = 4 | startValue = 5 | nums
/// (4 - 3) = 1 | (5 - 3) = 2 | -3
/// (1 + 2) = 3 | (2 + 2) = 4 | 2
/// (3 - 3) = 0 | (4 - 3) = 1 | -3
/// (0 + 4) = 4 | (1 + 4) = 5 | 4
/// (4 + 2) = 6 | (5 + 2) = 7 | 2
/// ```
///
/// + **示例 2**
/// + **输入:** nums = \[1,2\]
/// + **输出:** 1
/// + **解释:** 最小的 startValue 需要是正数。
/// + **示例 3**
/// + **输入:** nums = \[1,-2,-3\]
/// + **输出:** 5
/// + **提示:**
/// * `1 <= nums.length <= 100`
/// * `-100 <= nums[i] <= 100`
/// + Related Topics
/// * 数组
/// * 前缀和
pub fn min_start_value(nums: Vec<i32>) -> i32 {
let mut ans = 1;
let mut sum = 0;
for n in nums {
sum += n;
if sum.is_negative() {
ans = ans.max(-sum + 1);
}
}
ans
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q1413() {
assert_eq!(Solution::min_start_value(vec![-3, 2, -3, 4, 2]), 5);
}
}