移动部分的题的实现

This commit is contained in:
游由 2022-02-21 11:30:32 +08:00
parent 1f5413830d
commit 375ffd2a40
17 changed files with 1146 additions and 611 deletions

View File

@ -88,29 +88,43 @@ mod q0289;
mod q0292;
mod q0299;
mod q0319;
mod q0326;
mod q0338;
mod q0342;
mod q0343;
mod q0344;
mod q0363;
mod q0367;
mod q0368;
mod q0371;
mod q0375;
mod q0377;
mod q0387;
mod q0392;
mod q0399;
mod q0403;
mod q0404;
mod q0405;
mod q0407;
mod q0412;
mod q0415;
mod q0421;
mod q0424;
mod q0435;
mod q0448;
mod q0461;
mod q0477;
mod q0486;
mod q0495;
mod q0509;
mod q0547;
mod q0554;
mod q0557;
mod q0575;
mod q0598;
mod q0605;
mod q0617;
mod q0628;
mod q0633;
mod q0690;
mod q0695;
@ -148,3 +162,4 @@ mod q1734;
mod q1791;
mod q1984;
mod q2006;
mod q0643;

View File

@ -0,0 +1,45 @@
use crate::Solution;
impl Solution {
/// [326.3 的幂](https://leetcode-cn.com/problems/power-of-three/)
///
/// 2022-02-18 17:41:24
///
/// 给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 `true` ;否则,返回 `false` 。
///
/// 整数 `n` 是 3 的幂次方需满足:存在整数 `x` 使得 `n == 3x`
///
/// + **示例 1**
/// + **输入:** n = 27
/// + **输出:** true
/// + **示例 2**
/// + **输入:** n = 0
/// + **输出:** false
/// + **示例 3**
/// + **输入:** n = 9
/// + **输出:** true
/// + **示例 4**
/// + **输入:** n = 45
/// + **输出:** false
/// + **提示:**
/// * `-231 <= n <= 231 - 1`
/// + **进阶:** 你能不使用循环或者递归来完成本题吗?
/// + Related Topics
/// * 递归
/// * 数学
/// * 👍 244
/// * 👎 0
pub fn is_power_of_three(n: i32) -> bool {
n > 0 && 0x4546B3DB % n == 0
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0326() {
assert_eq!(Solution::is_power_of_three(27), true);
}
}

View File

@ -0,0 +1,62 @@
use crate::Solution;
impl Solution {
/// [338.比特位计数](https://leetcode-cn.com/problems/counting-bits/)
///
/// 2022-02-21 10:03:17
///
/// 给你一个整数 `n` ,对于 `0 <= i <= n` 中的每个 `i` ,计算其二进制表示中 **`1` 的个数** ,返回一个长度为 `n + 1` 的数组 `ans` 作为答案。
///
/// + **示例 1**
/// + **输入:** n = 2
/// + **输出:** \[0,1,1\]
/// + **解释:**
/// 0 --> 0
/// 1 --> 1
/// 2 --> 10
/// + **示例 2**
/// + **输入:** n = 5
/// + **输出:** \[0,1,1,2,1,2\]
/// + **解释:**
/// 0 --> 0
/// 1 --> 1
/// 2 --> 10
/// 3 --> 11
/// 4 --> 100
/// 5 --> 101
/// + **提示:**
/// * `0 <= n <= 105`
/// + **进阶:**
/// * 很容易就能实现时间复杂度为 `O(n log n)` 的解决方案,你可以在线性时间复杂度 `O(n)` 内用一趟扫描解决此问题吗?
/// * 你能不使用任何内置函数解决此问题吗C++ 中的 `__builtin_popcount`
/// + Related Topics
/// * 位运算
/// * 动态规划
/// * 👍 894
/// * 👎 0
///
/// 动态规划 状态转移 `v[i] = v[i >> 1] + (i & 1) || v[i] = v[i & (i - 1)] + 1`
pub fn count_bits(n: i32) -> Vec<i32> {
/*let mut v = Vec::with_capacity((num + 1) as usize);
v.push(0);
for i in 1..=(num as usize) {
v.push(&v[i & (i - 1)] + 1)
}
v*/
let mut v = Vec::with_capacity((n + 1) as usize);
v.push(0);
(1..=(n as usize)).for_each(|i| { v.push(&v[i >> 1] + (i & 1) as i32) });
v
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0338() {
assert_eq!(Solution::count_bits(5), vec![0, 1, 1, 2, 1, 2]);
}
}

View File

@ -0,0 +1,57 @@
use crate::Solution;
impl Solution {
/// [343.整数拆分](https://leetcode-cn.com/problems/integer-break/)
///
/// 2022-02-21 10:12:14
///
/// 给定一个正整数 `n` ,将其拆分为 `k` 个 **正整数** 的和( `k >= 2` ),并使这些整数的乘积最大化。
///
/// 返回 _你可以获得的最大乘积_ 。
///
/// + **示例 1:**
/// + **输入:** n = 2
/// + **输出:** 1
/// + **解释:** 2 = 1 + 1, 1 × 1 = 1。
/// + **示例 2:**
/// + **输入:** n = 10
/// + **输出:** 36
/// + **解释:** 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
/// + **提示:**
/// * `2 <= n <= 58`
/// + Related Topics
/// * 数学
/// * 动态规划
/// * 👍 712
/// * 👎 0
pub fn integer_break(n: i32) -> i32 {
match n {
n if n <= 3 => n - 1,
_ => match n % 3 {
0 => 3i32.pow((n / 3) as u32),
1 => (3i32.pow((n / 3) as u32 - 1) * 4),
_ => (3i32.pow((n / 3) as u32) * 2)
}
}
/*if n <= 3 {
return n - 1;
}
let q = (n / 3) as u32;
match n % 3 {
0 => 3i32.pow(q),
1 => (3i32.pow(q - 1) * 4),
_ => (3i32.pow(q) * 2)
}*/
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0343() {
assert_eq!(Solution::integer_break(10), 36)
}
}

View File

@ -0,0 +1,52 @@
use crate::Solution;
impl Solution {
/// [371.两整数之和](https://leetcode-cn.com/problems/sum-of-two-integers/)
///
/// 2022-02-21 10:22:25
///
/// 给你两个整数 `a` 和 `b` **不使用** 运算符 `+` 和 `-` ,计算并返回两整数之和。
///
/// + **示例 1**
/// + **输入:** a = 1, b = 2
/// + **输出:** 3
/// + **示例 2**
/// + **输入:** a = 2, b = 3
/// + **输出:** 5
/// + **提示:**
/// * `-1000 <= a, b <= 1000`
/// + Related Topics
/// * 位运算
/// * 数学
/// * 👍 586
/// * 👎 0
///
/// 1. 加法器
/// ```rust
/// pub fn get_sum(mut a: i32, mut b: i32) -> i32 {
/// let mut sum = a;
/// while b != 0 {
/// sum = a ^ b;
/// b = (a & b) << 1;
/// a = sum;
/// }
/// sum
/// }
/// ```
/// 2. 内置接口
///
/// 实现见代码
pub fn get_sum(a: i32, b: i32) -> i32 {
std::ops::Add::<i32>::add(a, b)
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0371() {
assert_eq!(Solution::get_sum(12, 13), 25);
}
}

View File

@ -0,0 +1,64 @@
use crate::Solution;
impl Solution {
/// [387.字符串中的第一个唯一字符](https://leetcode-cn.com/problems/first-unique-character-in-a-string/)
///
/// 2022-02-21 10:29:57
///
/// 给定一个字符串 `s` ,找到 _它的第一个不重复的字符并返回它的索引_ 。如果不存在,则返回 `-1` 。
///
/// + **示例 1**
/// + **输入:** s = "leetcode"
/// + **输出:** 0
/// + **示例 2:**
/// + **输入:** s = "loveleetcode"
/// + **输出:** 2
/// + **示例 3:**
/// + **输入:** s = "aabb"
/// + **输出:** -1
/// + **提示:**
/// * `1 <= s.length <= 105`
/// * `s` 只包含小写字母
/// + Related Topics
/// * 队列
/// * 哈希表
/// * 字符串
/// * 计数
/// * 👍 505
/// * 👎 0
pub fn first_uniq_char(s: String) -> i32 {
let mut dup_lookup = vec![false; 26];
let mut idx_lookup = vec![s.len(); 26];
let s = s.into_bytes();
let mut idx = 0usize;
for i in 0..s.len() {
idx = (s[i] - 'a' as u8) as usize;
if idx_lookup[idx] == s.len() {
idx_lookup[idx] = i;
} else {
dup_lookup[idx] = true;
}
}
let mut ret = s.len();
for i in 0..dup_lookup.len() {
if !dup_lookup[i] && idx_lookup[i] != s.len() && idx_lookup[i] < ret {
ret = idx_lookup[i];
}
}
if ret == s.len() {
-1
} else {
ret as i32
}
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0387() {
assert_eq!(Solution::first_uniq_char( "leetcode".to_string()), 0);
}
}

View File

@ -0,0 +1,231 @@
use crate::Solution;
impl Solution {
/// [399.除法求值](https://leetcode-cn.com/problems/evaluate-division/)
///
/// 2022-02-21 10:35:22
///
/// 给你一个变量对数组 `equations` 和一个实数值数组 `values` 作为已知条件,其中 `equations[i] = [Ai, Bi]` 和 `values[i]` 共同表示等式 `Ai / Bi = values[i]` 。每个 `Ai` 或 `Bi` 是一个表示单个变量的字符串。
///
/// 另有一些以数组 `queries` 表示的问题,其中 `queries[j] = [Cj, Dj]` 表示第 `j` 个问题,请你根据已知条件找出 `Cj / Dj = ?` 的结果作为答案。
///
/// 返回 **所有问题的答案** 。如果存在某个无法确定的答案,则用 `-1.0` 替代这个答案。如果问题中出现了给定的已知条件中没有出现的字符串,也需要用 `-1.0` 替代这个答案。
///
/// **注意:** 输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况,且不存在任何矛盾的结果。
///
/// + **示例 1**
/// + **输入:** equations = \[\["a","b"\],\["b","c"\]\], values = \[2.0,3.0\], queries = \[\["a","c"\],\["b","a"\],\["a","e"\],\["a","a"\],\["x","x"\]\]
/// + **输出:** \[6.00000,0.50000,-1.00000,1.00000,-1.00000\]
/// + **解释:**
/// - 条件_a / b = 2.0_, _b / c = 3.0_
/// - 问题_a / c = ?_, _b / a = ?_, _a / e = ?_, _a / a = ?_, _x / x = ?_
/// - 结果:\[6.0, 0.5, -1.0, 1.0, -1.0 \]
/// + **示例 2**
/// + **输入:** equations = \[\["a","b"\],\["b","c"\],\["bc","cd"\]\], values = \[1.5,2.5,5.0\], queries = \[\["a","c"\],\["c","b"\],\["bc","cd"\],\["cd","bc"\]\]
/// + **输出:** \[3.75000,0.40000,5.00000,0.20000\]
/// + **示例 3**
/// + **输入:** equations = \[\["a","b"\]\], values = \[0.5\], queries = \[\["a","b"\],\["b","a"\],\["a","c"\],\["x","y"\]\]
/// + **输出:** \[0.50000,2.00000,-1.00000,-1.00000\]
/// + **提示:**
/// * `1 <= equations.length <= 20`
/// * `equations[i].length == 2`
/// * `1 <= Ai.length, Bi.length <= 5`
/// * `values.length == equations.length`
/// * `0.0 < values[i] <= 20.0`
/// * `1 <= queries.length <= 20`
/// * `queries[i].length == 2`
/// * `1 <= Cj.length, Dj.length <= 5`
/// * `Ai, Bi, Cj, Dj` 由小写英文字母与数字组成
/// + Related Topics
/// * 深度优先搜索
/// * 广度优先搜索
/// * 并查集
/// * 图
/// * 数组
/// * 最短路
/// * 👍 681
/// * 👎 0
///
/// 1. 广度优先搜索
/// 转为加权图,从起点开始通过广度优先搜索,不断更新起点与当前点之间的路径长度,直到搜索到终点为止。实现见源码。
/// 1. 复杂度分析
/// - 时间复杂度O(ML+Q(L+M)M为边的数量Q为询问的数量L为字符串的平均长度。构建图时需要处理M条边
/// 条边都涉及到O(L)的字符串比较处理查询时每次查询首先要进行一次O(L)的比较然后至多遍历O(M)条边。
/// - 空间复杂度O(NL+M)其中N为点的数量M为边的数量L为字符串的平均长度。为了将每个字符串映射到整数
/// 要开辟空间为O(NL)的哈希表随后需要花费O(M)的空间存储每条边的权重处理查询时还需要O(N)的空间维护访
/// 问队列。最终总的复杂度为O(NL+M+N)=O(NL+M)。
/// 2. 源码
/// ```rust
/// pub fn calc_equation(equations: Vec<Vec<String>>, values: Vec<f64>, queries: Vec<Vec<String>>) -> Vec<f64> {
/// let mut nvars = 0usize;
/// let mut variables = std::collections::HashMap::<String, usize>::new();
/// let n = equations.len();
/// for i in 0..n {
/// if !variables.contains_key(&*equations[i][0]) {
/// variables.insert(equations[i][0].clone(), nvars);
/// nvars += 1usize;
/// }
/// if !variables.contains_key(&*equations[i][1]) {
/// variables.insert(equations[i][1].clone(), nvars);
/// nvars += 1usize;
/// }
/// }
/// let mut edges = vec![Vec::<(usize, f64)>::new(); nvars];
/// for i in 0..n {
/// let (va, vb) = (variables[&*equations[i][0]], variables[&*equations[i][1]]);
/// edges[va].push((vb, values[i]));
/// edges[vb].push((va, 1.0f64 / values[i]));
/// }
/// let mut ret = Vec::<f64>::new();
/// for q in queries {
/// let mut result = -1.0;
/// if variables.contains_key(&*q[0]) && variables.contains_key(&*q[1]) {
/// let (ia, ib) = (variables[&*q[0]], variables[&*q[1]]);
/// if ia == ib {
/// result = 1.0;
/// } else {
/// let mut points = Vec::new();
/// points.push(ia);
/// let mut ratios = vec![-1.0; nvars];
/// ratios[ia] = 1.0;
/// while !points.is_empty() && ratios[ib] < 0f64 {
/// let x = points.remove(0);
/// for (y, val) in &edges[x] {
/// if ratios[*y] < 0f64 {
/// ratios[*y] = ratios[x] * *val;
/// points.push(*y);
/// }
/// }
/// }
/// result = ratios[ib];
/// }
/// }
/// ret.push(result)
/// }
/// ret
/// }
/// ```
/// 2. 弗洛伊德算法
/// ```rust
/// pub fn calc_equation(equations: Vec<Vec<String>>, values: Vec<f64>, queries: Vec<Vec<String>>) -> Vec<f64> {
/// let mut nvars = 0usize;
/// let mut variables = std::collections::HashMap::<String, usize>::new();
/// let n = equations.len();
/// for i in 0..n {
/// if !variables.contains_key(&*equations[i][0]) {
/// variables.insert(equations[i][0].clone(), nvars);
/// nvars += 1usize;
/// }
/// if !variables.contains_key(&*equations[i][1]) {
/// variables.insert(equations[i][1].clone(), nvars);
/// nvars += 1usize;
/// }
/// }
/// let mut graph = vec![vec![-1.0; nvars]; nvars];
/// for i in 0..n{
/// let (va, vb) = (variables[&*equations[i][0]], variables[&*equations[i][1]]);
/// graph[va][vb] = values[i];
/// graph[vb][va] = 1.0f64 / values[i];
/// }
/// for k in 0..nvars {
/// for i in 0..nvars {
/// for j in 0..nvars {
/// if graph[i][k] > 0.0 && graph[k][j] > 0.0 {
/// graph[i][j] = graph[i][k] * graph[k][j];
/// }
/// }
/// }
/// }
/// let mut ret = Vec::<f64>::new();
/// for q in queries {
/// let mut result = -1.0;
/// if variables.contains_key(&*q[0]) && variables.contains_key(&*q[1]) {
/// let (ia, ib) = (variables[&*q[0]], variables[&*q[1]]);
/// if graph[ia][ib] > 0.0 {
/// result = graph[ia][ib];
/// }
/// }
/// ret.push(result);
/// }
/// ret
/// }
/// ```
/// # 方法3 加权并查集
/// 源码见实现
pub fn calc_equation(equations: Vec<Vec<String>>, values: Vec<f64>, queries: Vec<Vec<String>>) -> Vec<f64> {
fn find(f: &mut Vec<usize>, w: &mut Vec<f64>, x: usize) -> usize {
if f[x] != x {
let father = find(f, w, f[x]);
w[x] = w[x] * w[f[x]];
f[x] = father;
}
f[x]
}
fn merge(f: &mut Vec<usize>, w: &mut Vec<f64>, x: usize, y: usize, val: f64) {
let fx = find(f, w, x);
let fy = find(f, w, y);
f[fx] = fy;
w[fx] = val * w[y] / w[x];
}
let mut nvars = 0usize;
let mut variables = std::collections::HashMap::<String, usize>::new();
let n = equations.len();
for i in 0..n {
if !variables.contains_key(&*equations[i][0]) {
variables.insert(equations[i][0].clone(), nvars);
nvars += 1usize;
}
if !variables.contains_key(&*equations[i][1]) {
variables.insert(equations[i][1].clone(), nvars);
nvars += 1usize;
}
}
let mut f = (0..nvars).collect::<Vec<usize>>();
let mut w = vec![1.0; nvars];
for i in 0..n {
let (va, vb) = (variables[&*equations[i][0]], variables[&*equations[i][1]]);
merge(&mut f, &mut w, va, vb, values[i]);
}
let mut ret = Vec::<f64>::new();
for q in queries {
let mut result = -1.0;
if variables.contains_key(&*q[0]) && variables.contains_key(&*q[1]) {
let (ia, ib) = (variables[&*q[0]], variables[&*q[1]]);
let (fa, fb) = (find(&mut f, &mut w, ia), find(&mut f, &mut w, ib));
if fa == fb {
result = w[ia] / w[ib];
}
}
ret.push(result);
}
ret
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0399() {
let eq = vec![vec!["a".to_string(), "b".to_string()], vec!["b".to_string(), "c".to_string()]];
let val = vec![2.0, 3.0];
let que = vec![
vec!["a".to_string(), "c".to_string()],
vec!["b".to_string(), "a".to_string()],
vec!["a".to_string(), "e".to_string()],
vec!["a".to_string(), "a".to_string()],
vec!["x".to_string(), "x".to_string()]
];
let vec1 = Solution::calc_equation(eq, val, que);
//println!("{:?}", vec1);
assert_eq!(vec1, vec![6.0, 0.5, -1.0, 1.0, -1.0])
}
}

View File

@ -0,0 +1,53 @@
use crate::Solution;
impl Solution {
/// [415.字符串相加](https://leetcode-cn.com/problems/add-strings/)
///
/// 2022-02-21 10:47:24
///
/// 给定两个字符串形式的非负整数 `num1` 和`num2` ,计算它们的和并同样以字符串形式返回。
///
/// 你不能使用任何內建的用于处理大整数的库(比如 `BigInteger` 也不能直接将输入的字符串转换为整数形式。
///
/// + **示例 1**
/// + **输入:** num1 = "11", num2 = "123"
/// + **输出:** "134"
/// + **示例 2**
/// + **输入:** num1 = "456", num2 = "77"
/// + **输出:** "533"
/// + **示例 3**
/// + **输入:** num1 = "0", num2 = "0"
/// + **输出:** "0"
/// + **提示:**
/// * `1 <= num1.length, num2.length <= 104`
/// * `num1` 和`num2` 都只包含数字 `0-9`
/// * `num1` 和`num2` 都不包含任何前导零
/// + Related Topics
/// * 数学
/// * 字符串
/// * 模拟
/// * 👍 507
/// * 👎 0
pub fn add_strings(mut num1: String, mut num2: String) -> String {
let mut res = String::new();
let mut carry = 0u8;
loop {
if num1.is_empty() && num2.is_empty() && carry == 0 { break; }
if let Some(n1) = num1.pop() { carry += n1 as u8 - b'0'; }
if let Some(n2) = num2.pop() { carry += n2 as u8 - b'0'; }
res.insert(0, ((carry % 10) + b'0') as char);
carry /= 10;
}
res
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0415() {
assert_eq!(Solution::add_strings("11".to_string(), "123".to_string()), "134".to_string());
}
}

View File

@ -0,0 +1,58 @@
use crate::Solution;
impl Solution {
/// [424.替换后的最长重复字符](https://leetcode-cn.com/problems/longest-repeating-character-replacement/)
///
/// 2022-02-21 10:52:05
///
/// 给你一个字符串 `s` 和一个整数 `k` 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 `k` 次。
///
/// 在执行上述操作后,返回包含相同字母的最长子字符串的长度。
///
/// + **示例 1**
/// + **输入:** s = "ABAB", k = 2
/// + **输出:** 4
/// + **解释:** 用两个'A'替换为两个'B',反之亦然。
/// + **示例 2**
/// + **输入:** s = "AABABBA", k = 1
/// + **输出:** 4
/// + **解释:**
/// - 将中间的一个'A'替换为'B',字符串变为 "AABBBBA"。
/// - 子串 "BBBB" 有最长重复字母, 答案为 4。
/// + **提示:**
/// * `1 <= s.length <= 105`
/// * `s` 仅由大写英文字母组成
/// * `0 <= k <= s.length`
/// + Related Topics
/// * 哈希表
/// * 字符串
/// * 滑动窗口
/// * 👍 553
/// * 👎 0
pub fn character_replacement(s: String, k: i32) -> i32 {
let mut num = vec![0; 26];
let s = s.into_bytes();
let n = s.len();
let (mut max_n, mut left, mut right, k) = (0usize, 0usize, 0usize, k as usize);
while right < n {
num[(s[right] - b'A') as usize] += 1;
max_n = max_n.max(num[(s[right] - b'A') as usize]);
if right - left + 1 - max_n > k {
num[(s[left] - b'A') as usize] -= 1;
left += 1;
}
right += 1;
}
(right - left) as i32
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0424() {
assert_eq!(Solution::character_replacement("AABABBA".to_string(), 1), 4);
}
}

View File

@ -0,0 +1,60 @@
use crate::Solution;
impl Solution {
/// [435.无重叠区间](https://leetcode-cn.com/problems/non-overlapping-intervals/)
///
/// 2022-02-21 10:56:06
///
/// 给定一个区间的集合 `intervals` ,其中 `intervals[i] = [starti, endi]` 。返回 _需要移除区间的最小数量使剩余区间互不重叠 _。
///
/// + **示例 1:**
/// + **输入:** intervals = \[\[1,2\],\[2,3\],\[3,4\],\[1,3\]\]
/// + **输出:** 1
/// + **解释:** 移除 \[1,3\] 后,剩下的区间没有重叠。
/// + **示例 2:**
/// + **输入:** intervals = \[ \[1,2\], \[1,2\], \[1,2\] \]
/// + **输出:** 2
/// + **解释:** 你需要移除两个 \[1,2\] 来使剩下的区间没有重叠。
/// + **示例 3:**
/// + **输入:** intervals = \[ \[1,2\], \[2,3\] \]
/// + **输出:** 0
/// + **解释:** 你不需要移除任何区间,因为它们已经是无重叠的了。
/// + **提示:**
/// * `1 <= intervals.length <= 105`
/// * `intervals[i].length == 2`
/// * `-5 * 104 <= starti < endi <= 5 * 104`
/// + Related Topics
/// * 贪心
/// * 数组
/// * 动态规划
/// * 排序
/// * 👍 605
/// * 👎 0
pub fn erase_overlap_intervals(mut intervals: Vec<Vec<i32>>) -> i32 {
if intervals.len() == 0 {
return 0;
}
intervals.sort_by(|a, b| a[1].cmp(&b[1]));
let mut last = &intervals[0];
let mut count = 0;
for i in 1..intervals.len() {
let cur = &intervals[i];
if cur[0] < last[1] {
count += 1;
} else {
last = &intervals[i];
}
}
count
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0435() {
assert_eq!(Solution::erase_overlap_intervals(vec![vec![0, 2], vec![1, 3], vec![2, 4], vec![3, 5], vec![4, 6]]), 2);
}
}

View File

@ -0,0 +1,57 @@
use crate::Solution;
impl Solution {
/// [448.找到所有数组中消失的数字](https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/)
///
/// 2022-02-21 11:00:15
///
/// 给你一个含 `n` 个整数的数组 `nums` ,其中 `nums[i]` 在区间 `[1, n]` 内。请你找出所有在 `[1, n]` 范围内但没有出现在 `nums` 中的数字,并以数组的形式返回结果。
///
/// + **示例 1**
/// + **输入:** nums = \[4,3,2,7,8,2,3,1\]
/// + **输出:** \[5,6\]
/// + **示例 2**
/// + **输入:** nums = \[1,1\]
/// + **输出:** \[2\]
/// + **提示:**
/// * `n == nums.length`
/// * `1 <= n <= 105`
/// * `1 <= nums[i] <= n`
/// + **进阶:**
/// 你能在不使用额外空间且时间复杂度为 `O(n)` 的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。
/// + Related Topics
/// * 数组
/// * 哈希表
/// * 👍 897
/// * 👎 0
///
/// 1. 哈希表
/// 2. 原地修改
/// 遍历数组,将数组元素中对应的索引位置的元素取反,二次遍历时大于零的元素没有被修改过,即缺少索引对应的元素。实现见源码。
pub fn find_disappeared_numbers(mut nums: Vec<i32>) -> Vec<i32> {
let mut ret = Vec::<i32>::new();
let mut idx = 0usize;
for i in 0..nums.len() {
idx = (nums[i].abs() - 1) as usize;
if nums[idx] > 0 {
nums[idx] *= -1;
}
}
for i in 0..nums.len() {
if nums[i] > 0 {
ret.push(i as i32 + 1);
}
}
ret
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0448() {
assert_eq!(Solution::find_disappeared_numbers(vec![4, 3, 2, 7, 8, 2, 3, 1]), vec![5, 6]);
}
}

View File

@ -0,0 +1,77 @@
use crate::Solution;
impl Solution {
/// [486.预测赢家](https://leetcode-cn.com/problems/predict-the-winner/)
///
/// 2022-02-21 11:05:01
///
/// 给你一个整数数组 `nums` 。玩家 1 和玩家 2 基于这个数组设计了一个游戏。
///
/// 玩家 1 和玩家 2 轮流进行自己的回合,玩家 1 先手。开始时,两个玩家的初始分值都是 `0` 。每一回合,玩家从数组的任意一端取一个数字(即,`nums[0]` 或 `nums[nums.length - 1]`),取到的数字将会从数组中移除(数组长度减 `1` )。玩家选中的数字将会加到他的得分上。当数组中没有剩余数字可取时,游戏结束。
///
/// 如果玩家 1 能成为赢家,返回 `true` 。如果两个玩家得分相等,同样认为玩家 1 是游戏的赢家,也返回 `true` 。你可以假设每个玩家的玩法都会使他的分数最大化。
///
/// + **示例 1**
/// + **输入:** nums = \[1,5,2\]
/// + **输出:** false
/// + **解释:**
/// - 一开始,玩家 1 可以从 1 和 2 中进行选择。
/// - 如果他选择 2或者 1 ),那么玩家 2 可以从 1或者 2 )和 5 中进行选择。如果玩家 2 选择了 5 ,那么玩家 1 则只剩下 1或者 2 )可选。
/// - 所以,玩家 1 的最终分数为 1 + 2 = 3而玩家 2 为 5 。
/// - 因此,玩家 1 永远不会成为赢家,返回 false 。
/// + **示例 2**
/// + **输入:** nums = \[1,5,233,7\]
/// + **输出:** true
/// + **解释:**
/// - 玩家 1 一开始选择 1 。然后玩家 2 必须从 5 和 7 中进行选择。无论玩家 2 选择了哪个,玩家 1 都可以选择 233 。
/// - 最终,玩家 1234 分)比玩家 212 分)获得更多的分数,所以返回 true表示玩家 1 可以成为赢家。
/// + **提示:**
/// * `1 <= nums.length <= 20`
/// * `0 <= nums[i] <= 107`
/// + Related Topics
/// * 递归
/// * 数组
/// * 数学
/// * 动态规划
/// * 博弈
/// * 👍 521
/// * 👎 0
///
/// 1. 递归
///
/// 实现见源码
///
/// 2. 动态规划
/// ```rust
/// pub fn predict_the_winner(nums: Vec<i32>) -> bool {
/// let mut dp = nums.clone();
/// for i in (0..nums.len() - 1).rev() {
/// for j in i + 1..nums.len() {
/// dp[j] = std::cmp::max(nums[i] - dp[j], nums[j] - dp[j - 1]);
/// }
/// }
/// dp[nums.len() - 1] >= 0
/// }
/// ```
pub fn predict_the_winner(nums: Vec<i32>) -> bool {
fn total(nums: &Vec<i32>, start: usize, end: usize, turn: i32) -> i32 {
if start == end {
return nums[start] * turn;
}
let score_start = nums[start] * turn + total(nums, start + 1, end, -turn);
let score_end = nums[end] * turn + total(nums, start, end - 1, -turn);
(score_start * turn).max(score_end * turn) * turn
}
total(&nums, 0, nums.len() - 1, 1) >= 0
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0486() {
assert_eq!(Solution::predict_the_winner(vec![1, 5, 233, 7]), true);
}
}

View File

@ -0,0 +1,135 @@
use crate::Solution;
impl Solution {
/// [547.省份数量](https://leetcode-cn.com/problems/number-of-provinces/)
///
/// 2022-02-21 11:09:51
///
/// 有 `n` 个城市,其中一些彼此相连,另一些没有相连。如果城市 `a` 与城市 `b` 直接相连,且城市 `b` 与城市 `c` 直接相连,那么城市 `a` 与城市 `c` 间接相连。
///
/// **省份** 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
///
/// 给你一个 `n x n` 的矩阵 `isConnected` ,其中 `isConnected[i][j] = 1` 表示第 `i` 个城市和第 `j` 个城市直接相连,而 `isConnected[i][j] = 0` 表示二者不直接相连。
///
/// 返回矩阵中 **省份** 的数量。
///
/// + **示例 1**
/// + ![](https://assets.leetcode.com/uploads/2020/12/24/graph1.jpg)
/// + **输入:** isConnected = \[\[1,1,0\],\[1,1,0\],\[0,0,1\]\]
/// + **输出:** 2
/// + **示例 2**
/// + ![](https://assets.leetcode.com/uploads/2020/12/24/graph2.jpg)
/// + **输入:** isConnected = \[\[1,0,0\],\[0,1,0\],\[0,0,1\]\]
/// + **输出:** 3
/// + **提示:**
/// * `1 <= n <= 200`
/// * `n == isConnected.length`
/// * `n == isConnected[i].length`
/// * `isConnected[i][j]` 为 `1` 或 `0`
/// * `isConnected[i][i] == 1`
/// * `isConnected[i][j] == isConnected[j][i]`
/// + Related Topics
/// * 深度优先搜索
/// * 广度优先搜索
/// * 并查集
/// * 图
/// * 👍 716
/// * 👎 0
///
/// 1. 深度优先搜索
/// ```rust
/// pub fn find_circle_num(is_connected: Vec<Vec<i32>>) -> i32 {
/// let provinces = is_connected.len();
/// let mut visited = vec![false; provinces];
/// let mut circles = 0;
/// fn dfs(is_connected: &Vec<Vec<i32>>, visited:&mut Vec<bool>, provinces: usize, i: usize) {
/// for j in 0..provinces {
/// if is_connected[i][j] == 1 && !visited[j] {
/// visited[j] = true;
/// dfs(is_connected, visited, provinces, j);
/// }
/// }
/// }
/// for i in 0..provinces {
/// if !visited[i] {
/// dfs(&is_connected, &mut visited, provinces, i);
/// circles += 1;
/// }
/// }
/// circles
/// }
/// ```
/// 2. 广度优先搜索
/// ```rust
/// pub fn find_circle_num(is_connected: Vec<Vec<i32>>) -> i32 {
/// let provinces = is_connected.len();
/// let mut visited = vec![false; provinces];
/// let mut circles = 0;
/// let mut queue = Vec::<usize>::new();
/// for i in 0..provinces {
/// if !visited[i] {
/// queue.push(i);
/// while !queue.is_empty() {
/// let j = queue.remove(0);
/// visited[j] = true;
/// for k in 0..provinces {
/// if is_connected[j][k] == 1 && !visited[k] {
/// queue.push(k);
/// }
/// }
/// }
/// circles += 1;
/// }
/// }
/// circles
/// }
/// ```
/// 3. 并查集
///
/// 实现方法见源码
pub fn find_circle_num(is_connected: Vec<Vec<i32>>) -> i32 {
let provinces = is_connected.len();
let mut parent = (0..provinces).collect::<Vec<usize>>();
fn find(parent: &mut Vec<usize>, idx: usize) -> usize {
if parent[idx] != idx {
parent[idx] = find(parent, parent[idx]);
}
parent[idx]
}
fn union(parent: &mut Vec<usize>, idx1: usize, idx2: usize) {
let a = find(parent, idx1);
let b = find(parent, idx2);
parent[a] = b;
}
for i in 0..provinces {
for j in i + 1..provinces {
if is_connected[i][j] == 1 {
union(&mut parent, i, j);
}
}
}
let mut circles = 0;
for i in 0..provinces {
if parent[i] == i {
circles += 1;
}
}
circles
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0547() {
let c = vec![vec![1, 1, 0], vec![1, 1, 0], vec![0, 0, 1]];
let n = Solution::find_circle_num(c);
assert_eq!(n, 2);
}
}

View File

@ -0,0 +1,62 @@
use crate::Solution;
impl Solution {
/// [605.种花问题](https://leetcode-cn.com/problems/can-place-flowers/)
///
/// 2022-02-21 11:16:45
///
/// 假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
///
/// 给你一个整数数组 `flowerbed` 表示花坛,由若干 `0` 和 `1` 组成,其中 `0` 表示没种植花,`1` 表示种植了花。另有一个数 `n` ,能否在不打破种植规则的情况下种入 `n` 朵花?能则返回 `true` ,不能则返回 `false`。
///
/// + **示例 1**
/// + **输入:** flowerbed = \[1,0,0,0,1\], n = 1
/// + **输出:** true
/// + **示例 2**
/// + **输入:** flowerbed = \[1,0,0,0,1\], n = 2
/// + **输出:** false
/// + **提示:**
/// * `1 <= flowerbed.length <= 2 * 104`
/// * `flowerbed[i]` 为 `0` 或 `1`
/// * `flowerbed` 中不存在相邻的两朵花
/// * `0 <= n <= flowerbed.length`
/// + Related Topics
/// * 贪心
/// * 数组
/// * 👍 429
/// * 👎 0
pub fn can_place_flowers(flowerbed: Vec<i32>, n: i32) -> bool {
let mut count = 0i32;
let m = flowerbed.len();
let mut prev = -1i32;
for i in 0..m {
if flowerbed[i] == 1 {
if prev < 0 {
count += (i / 2) as i32;
} else {
count += (i as i32 - prev - 2) / 2;
}
if count >= n {
return true;
}
prev = i as i32;
}
}
if prev < 0 {
count += (m as i32 + 1) / 2;
} else {
count += (m as i32 - prev - 1) / 2;
}
return count >= n;
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0605() {
assert_eq!(Solution::can_place_flowers(vec![1, 0, 0, 0, 1], 1), true);
}
}

View File

@ -0,0 +1,62 @@
use crate::Solution;
impl Solution {
/// [628.三个数的最大乘积](https://leetcode-cn.com/problems/maximum-product-of-three-numbers/)
///
/// 2022-02-21 11:21:05
///
/// 给你一个整型数组 `nums` ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
///
/// + **示例 1**
/// + **输入:** nums = \[1,2,3\]
/// + **输出:** 6
/// + **示例 2**
/// + **输入:** nums = \[1,2,3,4\]
/// + **输出:** 24
/// + **示例 3**
/// + **输入:** nums = \[-1,-2,-3\]
/// + **输出:** \-6
/// + **提示:**
/// * `3 <= nums.length <= 104`
/// * `-1000 <= nums[i] <= 1000`
/// + Related Topics
/// * 数组
/// * 数学
/// * 排序
/// * 👍 355
/// * 👎 0
pub fn maximum_product(nums: Vec<i32>) -> i32 {
let (mut min1, mut min2) = (i32::MAX, i32::MAX);
let (mut max1, mut max2, mut max3) = (i32::MIN, i32::MIN, i32::MIN);
for x in nums {
if x < min1 {
min2 = min1;
min1 = x;
} else if x < min2 {
min2 = x;
}
if x > max1 {
max3 = max2;
max2 = max1;
max1 = x;
} else if x > max2 {
max3 = max2;
max2 = x;
} else if x > max3 {
max3 = x;
}
}
(min1 * min2 * max1).max(max1 * max2 * max3)
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0628() {
assert_eq!(Solution::maximum_product(vec![1, 2, 3]), 6);
}
}

View File

@ -0,0 +1,56 @@
use crate::Solution;
impl Solution {
/// [643.子数组最大平均数 I](https://leetcode-cn.com/problems/maximum-average-subarray-i/)
///
/// 2022-02-21 11:24:27
///
/// 给你一个由 `n` 个元素组成的整数数组 `nums` 和一个整数 `k` 。
///
/// 请你找出平均数最大且 **长度为 `k`** 的连续子数组,并输出该最大平均数。
///
/// 任何误差小于 `10-5` 的答案都将被视为正确答案。
///
/// + **示例 1**
/// + **输入:** nums = \[1,12,-5,-6,50,3\], k = 4
/// + **输出:** 12.75
/// + **解释:** 最大平均数 (12-5-6+50)/4 = 51/4 = 12.75
/// + **示例 2**
/// + **输入:** nums = \[5\], k = 1
/// + **输出:** 5.00000
/// + **提示:**
/// * `n == nums.length`
/// * `1 <= k <= n <= 105`
/// * `-104 <= nums[i] <= 104`
/// + Related Topics
/// * 数组
/// * 滑动窗口
/// * 👍 223
/// * 👎 0
pub fn find_max_average(nums: Vec<i32>, k: i32) -> f64 {
let k = k as usize;
let mut sum = 0;
for i in 0..k {
sum += nums[i];
}
let mut max_sum = sum;
for i in k..nums.len() {
sum += nums[i];
sum -= nums[i - k];
if max_sum < sum {
max_sum = sum;
}
}
max_sum as f64 / k as f64
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0643() {
assert_eq!(Solution::find_max_average(vec![1, 12, -5, -6, 50, 3], 4), 12.75);
}
}

View File

@ -7,65 +7,6 @@ use std::rc::Rc;
use std::ops::Add;
impl Solution {
/// 486.预测赢家
///
/// [原题链接](https://leetcode-cn.com/problems/predict-the-winner/)
///
/// # 方法1 递归
/// 实现见源码
/// # 方法2 动态规划
/// ```rust
/// pub fn predict_the_winner(nums: Vec<i32>) -> bool {
/// let mut dp = nums.clone();
/// for i in (0..nums.len() - 1).rev() {
/// for j in i + 1..nums.len() {
/// dp[j] = std::cmp::max(nums[i] - dp[j], nums[j] - dp[j - 1]);
/// }
/// }
/// dp[nums.len() - 1] >= 0
/// }
/// ```
pub fn predict_the_winner(nums: Vec<i32>) -> bool {
fn total(nums: &Vec<i32>, start: usize, end: usize, turn: i32) -> i32 {
if start == end {
return nums[start] * turn;
}
let score_start = nums[start] * turn + total(nums, start + 1, end, -turn);
let score_end = nums[end] * turn + total(nums, start, end - 1, -turn);
(score_start * turn).max(score_end * turn) * turn
}
total(&nums, 0, nums.len() - 1, 1) >= 0
}
/// 338.比特位计数
///
/// [原题链接](https://leetcode-cn.com/problems/counting-bits/)
///
/// 动态规划 状态转移 v[i] = v[i >> 1] + (i & 1) || v[i] = v[i & (i - 1)] + 1
fn count_bits(num: i32) -> Vec<i32> {
// let mut v = Vec::with_capacity((num + 1) as usize);
// v.push(0);
// for i in 1..=(num as usize) {
// v.push(&v[i & (i - 1)] + 1)
// }
// v
let mut v = Vec::with_capacity((num + 1) as usize);
v.push(0);
(1..=(num as usize)).for_each(|i| { v.push(&v[i >> 1] + (i & 1) as i32) });
v
}
/// 326.3的幂
///
/// [原题链接](https://leetcode-cn.com/problems/power-of-three/)
///
/// 我佛了 n > 0 && 3^19 % n == 0
pub fn is_power_of_three(n: i32) -> bool {
//n > 0 && 1162261467 % n == 0
n > 0 && 0x4546B3DB % n == 0
//i64 4052555153018976267 0x383D_9170_B85F_F80B
}
/// 1502.判断能否形成等差数列
///
/// [原题链接](https://leetcode-cn.com/problems/can-make-arithmetic-progression-from-sequence/)
@ -104,29 +45,6 @@ impl Solution {
(n as i64 & (n as i64 + 1)) == 0
}
/// 371.两整数之和
///
/// [原题链接](https://leetcode-cn.com/problems/sum-of-two-integers/)
/// [原题链接](https://leetcode-cn.com/problems/add-without-plus-lcci/)
///
/// # 方法1 加法器
/// ```rust
/// pub fn get_sum(mut a: i32, mut b: i32) -> i32 {
/// let mut sum = a;
/// while b != 0 {
/// sum = a ^ b;
/// b = (a & b) << 1;
/// a = sum;
/// }
/// sum
/// }
/// ```
/// # 方法2 内置接口
/// 实现见代码
pub fn get_sum(a: i32, b: i32) -> i32 {
a.add(b)
}
/// 面试题 16.01.交换数字
///
/// [原题链接](https://leetcode-cn.com/problems/swap-numbers-lcci/)
@ -137,21 +55,6 @@ impl Solution {
numbers
}
/// 343.整数拆分
///
/// [原题链接](https://leetcode-cn.com/problems/integer-break/)
pub fn integer_break(n: i32) -> i32 {
if n <= 3 {
return n - 1;
}
let q = (n / 3) as u32;
match n % 3 {
0 => 3i32.pow(q),
1 => (3i32.pow(q - 1) * 4),
_ => (3i32.pow(q) * 2)
}
}
/// 1404.将二进制表示减到 1 的步骤数
///
/// [原题链接](https://leetcode-cn.com/problems/number-of-steps-to-reduce-a-number-in-binary-representation-to-one/)
@ -191,23 +94,6 @@ impl Solution {
idx
}
/// 415.字符串相加
///
/// [原题链接](https://leetcode-cn.com/problems/add-strings/)
/// # 十进制字符串相加
pub fn add_strings(mut num1: String, mut num2: String) -> String {
let mut res = String::new();
let mut carry = 0u8;
loop {
if num1.is_empty() && num2.is_empty() && carry == 0 { break; }
if let Some(n1) = num1.pop() { carry += n1 as u8 - b'0'; }
if let Some(n2) = num2.pop() { carry += n2 as u8 - b'0'; }
res.insert(0, ((carry % 10) + b'0') as char);
carry /= 10;
}
res
}
/// 面试题 16.07.最大数值
///
/// [原题链接](https://leetcode-cn.com/problems/maximum-lcci/)
@ -406,27 +292,6 @@ impl Solution {
sell2
}
/// 435.无重叠区间
///
/// [原题链接](https://leetcode-cn.com/problems/non-overlapping-intervals/)
pub fn erase_overlap_intervals(mut intervals: Vec<Vec<i32>>) -> i32 {
if intervals.len() == 0 {
return 0;
}
intervals.sort_by(|a, b| a[1].cmp(&b[1]));
let mut last = &intervals[0];
let mut count = 0;
for i in 1..intervals.len() {
let cur = &intervals[i];
if cur[0] < last[1] {
count += 1;
} else {
last = &intervals[i];
}
}
count
}
/// 1342.将数字变成 0 的操作次数
///
/// [原题链接](https://leetcode-cn.com/problems/number-of-steps-to-reduce-a-number-to-zero/)
@ -531,295 +396,6 @@ impl Solution {
s.replace(" ", "%20")
}
/// 399.除法求值
///
/// [原题链接](https://leetcode-cn.com/problems/evaluate-division/)
///
/// # 方法1 广度优先搜索
/// 转为加权图,从起点开始通过广度优先搜索,不断更新起点与当前点之间的路径长度,直到搜索到终点为止。实现见源码。
/// ## 复杂度分析
/// - 时间复杂度O(ML+Q(L+M)M为边的数量Q为询问的数量L为字符串的平均长度。构建图时需要处理M条边
/// 条边都涉及到O(L)的字符串比较处理查询时每次查询首先要进行一次O(L)的比较然后至多遍历O(M)条边。
/// - 空间复杂度O(NL+M)其中N为点的数量M为边的数量L为字符串的平均长度。为了将每个字符串映射到整数
/// 要开辟空间为O(NL)的哈希表随后需要花费O(M)的空间存储每条边的权重处理查询时还需要O(N)的空间维护访
/// 问队列。最终总的复杂度为O(NL+M+N)=O(NL+M)。
/// ## 源码
/// ```rust
/// pub fn calc_equation(equations: Vec<Vec<String>>, values: Vec<f64>, queries: Vec<Vec<String>>) -> Vec<f64> {
/// let mut nvars = 0usize;
/// let mut variables = std::collections::HashMap::<String, usize>::new();
/// let n = equations.len();
/// for i in 0..n {
/// if !variables.contains_key(&*equations[i][0]) {
/// variables.insert(equations[i][0].clone(), nvars);
/// nvars += 1usize;
/// }
/// if !variables.contains_key(&*equations[i][1]) {
/// variables.insert(equations[i][1].clone(), nvars);
/// nvars += 1usize;
/// }
/// }
/// let mut edges = vec![Vec::<(usize, f64)>::new(); nvars];
/// for i in 0..n {
/// let (va, vb) = (variables[&*equations[i][0]], variables[&*equations[i][1]]);
/// edges[va].push((vb, values[i]));
/// edges[vb].push((va, 1.0f64 / values[i]));
/// }
/// let mut ret = Vec::<f64>::new();
/// for q in queries {
/// let mut result = -1.0;
/// if variables.contains_key(&*q[0]) && variables.contains_key(&*q[1]) {
/// let (ia, ib) = (variables[&*q[0]], variables[&*q[1]]);
/// if ia == ib {
/// result = 1.0;
/// } else {
/// let mut points = Vec::new();
/// points.push(ia);
/// let mut ratios = vec![-1.0; nvars];
/// ratios[ia] = 1.0;
/// while !points.is_empty() && ratios[ib] < 0f64 {
/// let x = points.remove(0);
/// for (y, val) in &edges[x] {
/// if ratios[*y] < 0f64 {
/// ratios[*y] = ratios[x] * *val;
/// points.push(*y);
/// }
/// }
/// }
/// result = ratios[ib];
/// }
/// }
/// ret.push(result)
/// }
/// ret
/// }
/// ```
/// # 方法2 弗洛伊德算法
/// ## 源码
/// ```rust
/// pub fn calc_equation(equations: Vec<Vec<String>>, values: Vec<f64>, queries: Vec<Vec<String>>) -> Vec<f64> {
/// let mut nvars = 0usize;
/// let mut variables = std::collections::HashMap::<String, usize>::new();
/// let n = equations.len();
/// for i in 0..n {
/// if !variables.contains_key(&*equations[i][0]) {
/// variables.insert(equations[i][0].clone(), nvars);
/// nvars += 1usize;
/// }
/// if !variables.contains_key(&*equations[i][1]) {
/// variables.insert(equations[i][1].clone(), nvars);
/// nvars += 1usize;
/// }
/// }
/// let mut graph = vec![vec![-1.0; nvars]; nvars];
/// for i in 0..n{
/// let (va, vb) = (variables[&*equations[i][0]], variables[&*equations[i][1]]);
/// graph[va][vb] = values[i];
/// graph[vb][va] = 1.0f64 / values[i];
/// }
/// for k in 0..nvars {
/// for i in 0..nvars {
/// for j in 0..nvars {
/// if graph[i][k] > 0.0 && graph[k][j] > 0.0 {
/// graph[i][j] = graph[i][k] * graph[k][j];
/// }
/// }
/// }
/// }
/// let mut ret = Vec::<f64>::new();
/// for q in queries {
/// let mut result = -1.0;
/// if variables.contains_key(&*q[0]) && variables.contains_key(&*q[1]) {
/// let (ia, ib) = (variables[&*q[0]], variables[&*q[1]]);
/// if graph[ia][ib] > 0.0 {
/// result = graph[ia][ib];
/// }
/// }
/// ret.push(result);
/// }
/// ret
/// }
/// ```
/// # 方法3 加权并查集
/// ## 源码
/// 源码见实现
pub fn calc_equation(equations: Vec<Vec<String>>, values: Vec<f64>, queries: Vec<Vec<String>>) -> Vec<f64> {
fn find(f: &mut Vec<usize>, w: &mut Vec<f64>, x: usize) -> usize {
if f[x] != x {
let father = find(f, w, f[x]);
w[x] = w[x] * w[f[x]];
f[x] = father;
}
f[x]
}
fn merge(f: &mut Vec<usize>, w: &mut Vec<f64>, x: usize, y: usize, val: f64) {
let fx = find(f, w, x);
let fy = find(f, w, y);
f[fx] = fy;
w[fx] = val * w[y] / w[x];
}
let mut nvars = 0usize;
let mut variables = std::collections::HashMap::<String, usize>::new();
let n = equations.len();
for i in 0..n {
if !variables.contains_key(&*equations[i][0]) {
variables.insert(equations[i][0].clone(), nvars);
nvars += 1usize;
}
if !variables.contains_key(&*equations[i][1]) {
variables.insert(equations[i][1].clone(), nvars);
nvars += 1usize;
}
}
let mut f = (0..nvars).collect::<Vec<usize>>();
let mut w = vec![1.0; nvars];
for i in 0..n {
let (va, vb) = (variables[&*equations[i][0]], variables[&*equations[i][1]]);
merge(&mut f, &mut w, va, vb, values[i]);
}
let mut ret = Vec::<f64>::new();
for q in queries {
let mut result = -1.0;
if variables.contains_key(&*q[0]) && variables.contains_key(&*q[1]) {
let (ia, ib) = (variables[&*q[0]], variables[&*q[1]]);
let (fa, fb) = (find(&mut f, &mut w, ia), find(&mut f, &mut w, ib));
if fa == fb {
result = w[ia] / w[ib];
}
}
ret.push(result);
}
ret
}
/// 547.省份数量
///
/// [原题链接](https://leetcode-cn.com/problems/number-of-provinces/)
///
/// 求图的联通分量
///
/// # 方法1 深度优先搜索
/// ```rust
/// pub fn find_circle_num(is_connected: Vec<Vec<i32>>) -> i32 {
/// let provinces = is_connected.len();
/// let mut visited = vec![false; provinces];
/// let mut circles = 0;
/// fn dfs(is_connected: &Vec<Vec<i32>>, visited:&mut Vec<bool>, provinces: usize, i: usize) {
/// for j in 0..provinces {
/// if is_connected[i][j] == 1 && !visited[j] {
/// visited[j] = true;
/// dfs(is_connected, visited, provinces, j);
/// }
/// }
/// }
/// for i in 0..provinces {
/// if !visited[i] {
/// dfs(&is_connected, &mut visited, provinces, i);
/// circles += 1;
/// }
/// }
/// circles
/// }
/// ```
/// # 方法2 广度优先搜索
/// ```rust
/// pub fn find_circle_num(is_connected: Vec<Vec<i32>>) -> i32 {
/// let provinces = is_connected.len();
/// let mut visited = vec![false; provinces];
/// let mut circles = 0;
/// let mut queue = Vec::<usize>::new();
/// for i in 0..provinces {
/// if !visited[i] {
/// queue.push(i);
/// while !queue.is_empty() {
/// let j = queue.remove(0);
/// visited[j] = true;
/// for k in 0..provinces {
/// if is_connected[j][k] == 1 && !visited[k] {
/// queue.push(k);
/// }
/// }
/// }
/// circles += 1;
/// }
/// }
/// circles
/// }
/// ```
/// # 方法3 并查集
/// 实现方法见源码
pub fn find_circle_num(is_connected: Vec<Vec<i32>>) -> i32 {
let provinces = is_connected.len();
let mut parent = (0..provinces).collect::<Vec<usize>>();
fn find(parent: &mut Vec<usize>, idx: usize) -> usize {
if parent[idx] != idx {
parent[idx] = find(parent, parent[idx]);
}
parent[idx]
}
fn union(parent: &mut Vec<usize>, idx1: usize, idx2: usize) {
let a = find(parent, idx1);
let b = find(parent, idx2);
parent[a] = b;
}
for i in 0..provinces {
for j in i + 1..provinces {
if is_connected[i][j] == 1 {
union(&mut parent, i, j);
}
}
}
let mut circles = 0;
for i in 0..provinces {
if parent[i] == i {
circles += 1;
}
}
circles
}
/// 387.字符串中的第一个唯一字符
///
/// [原题链接](https://leetcode-cn.com/problems/first-unique-character-in-a-string/)
///
/// # 方法1 查表
pub fn first_uniq_char(s: String) -> i32 {
let mut dup_lookup = vec![false; 26];
let mut idx_lookup = vec![s.len(); 26];
let s = s.into_bytes();
let mut idx = 0usize;
for i in 0..s.len() {
idx = (s[i] - 'a' as u8) as usize;
if idx_lookup[idx] == s.len() {
idx_lookup[idx] = i;
} else {
dup_lookup[idx] = true;
}
}
let mut ret = s.len();
for i in 0..dup_lookup.len() {
if !dup_lookup[i] && idx_lookup[i] != s.len() && idx_lookup[i] < ret {
ret = idx_lookup[i];
}
}
if ret == s.len() {
-1
} else {
ret as i32
}
}
/// 239.滑动窗口最大值
///
/// [原题链接](https://leetcode-cn.com/problems/sliding-window-maximum/)
@ -856,34 +432,6 @@ impl Solution {
unimplemented!()
}
/// 605.种花问题
///
/// [原题链接](https://leetcode-cn.com/problems/can-place-flowers/)
pub fn can_place_flowers(flowerbed: Vec<i32>, n: i32) -> bool {
let mut count = 0i32;
let m = flowerbed.len();
let mut prev = -1i32;
for i in 0..m {
if flowerbed[i] == 1 {
if prev < 0 {
count += (i / 2) as i32;
} else {
count += (i as i32 - prev - 2) / 2;
}
if count >= n {
return true;
}
prev = i as i32;
}
}
if prev < 0 {
count += (m as i32 + 1) / 2;
} else {
count += (m as i32 - prev - 1) / 2;
}
return count >= n;
}
/// 1202.交换字符串中的元素
///
/// [原题链接](https://leetcode-cn.com/problems/smallest-string-with-swaps/)
@ -1117,29 +665,6 @@ impl Solution {
(stones.len() - count) as i32
}
/// 448.找到所有数组中消失的数字
///
/// [原题链接](https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/)
/// # 方法1 哈希表
/// # 方法2 原地修改
/// 遍历数组,将数组元素中对应的索引位置的元素取反,二次遍历时大于零的元素没有被修改过,即缺少索引对应的元素。实现见源码。
pub fn find_disappeared_numbers(mut nums: Vec<i32>) -> Vec<i32> {
let mut ret = Vec::<i32>::new();
let mut idx = 0usize;
for i in 0..nums.len() {
idx = (nums[i].abs() - 1) as usize;
if nums[idx] > 0 {
nums[idx] *= -1;
}
}
for i in 0..nums.len() {
if nums[i] > 0 {
ret.push(i as i32 + 1);
}
}
ret
}
/// 803.打砖块
///
/// [原题链接](https://leetcode-cn.com/problems/bricks-falling-when-hit/)
@ -1483,36 +1008,6 @@ impl Solution {
ret
}
/// 628.三个数的最大乘积
///
/// [原题链接](https://leetcode-cn.com/problems/maximum-product-of-three-numbers/xian)
/// # 方法1 线性遍历
/// 找到最大的三个值和最小的两个值。
pub fn maximum_product(nums: Vec<i32>) -> i32 {
let (mut min1, mut min2) = (i32::MAX, i32::MAX);
let (mut max1, mut max2, mut max3) = (i32::MIN, i32::MIN, i32::MIN);
for x in nums {
if x < min1 {
min2 = min1;
min1 = x;
} else if x < min2 {
min2 = x;
}
if x > max1 {
max3 = max2;
max2 = max1;
max1 = x;
} else if x > max2 {
max3 = max2;
max2 = x;
} else if x > max3 {
max3 = x;
}
}
(min1 * min2 * max1).max(max1 * max2 * max3)
}
/// 1489.找到最小生成树里的关键边和伪关键边
///
/// [原题链接](https://leetcode-cn.com/problems/find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree/)
@ -2186,46 +1681,6 @@ impl Solution {
}
ans
}
/// 424.替换后的最长重复字符
///
/// [原题链接](https://leetcode-cn.com/problems/longest-repeating-character-replacement/)
pub fn character_replacement(s: String, k: i32) -> i32 {
let mut num = vec![0; 26];
let s = s.into_bytes();
let n = s.len();
let (mut max_n, mut left, mut right, k) = (0usize, 0usize, 0usize, k as usize);
while right < n {
num[(s[right] - b'A') as usize] += 1;
max_n = max_n.max(num[(s[right] - b'A') as usize]);
if right - left + 1 - max_n > k {
num[(s[left] - b'A') as usize] -= 1;
left += 1;
}
right += 1;
}
(right - left) as i32
}
/// 643.子数组最大平均数 I
///
/// [原题链接](https://leetcode-cn.com/problems/maximum-average-subarray-i/)
pub fn find_max_average(nums: Vec<i32>, k: i32) -> f64 {
let k = k as usize;
let mut sum = 0;
for i in 0..k {
sum += nums[i];
}
let mut max_sum = sum;
for i in k..nums.len() {
sum += nums[i];
sum -= nums[i - k];
if max_sum < sum {
max_sum = sum;
}
}
max_sum as f64 / k as f64
}
}
// 单元测试
@ -2251,14 +1706,6 @@ mod tests {
println!("{}", t2.elapsed().as_millis());
}*/
#[test]
fn test_find_max_average() {
let nums = vec![1, 12, -5, -6, 50, 3];
let k = 4;
let max_average = Solution::find_max_average(nums, k);
println!("{}", max_average);
}
#[test]
fn test_minimum_effort_path() {
let h = vec![vec![1, 2, 2], vec![3, 8, 2], vec![5, 3, 5]];
@ -2302,14 +1749,6 @@ mod tests {
assert_eq!(vec1, vec![2]);
}
#[test]
fn test_erase_overlap_intervals() {
let intervals = vec![vec![0, 2], vec![1, 3], vec![2, 4], vec![3, 5], vec![4, 6]];
let re = Solution::erase_overlap_intervals(intervals);
//println!("{}", re);
assert_eq!(re, 2);
}
#[test]
fn test_large_group_positions() {
let s = "abcdddeeeeaabbbcd".to_string();
@ -2326,48 +1765,6 @@ mod tests {
assert_eq!(n, 2);
}
#[test]
fn test_calc_equation() {
let eq = vec![vec!["a".to_string(), "b".to_string()], vec!["b".to_string(), "c".to_string()]];
let val = vec![2.0, 3.0];
let que = vec![
vec!["a".to_string(), "c".to_string()],
vec!["b".to_string(), "a".to_string()],
vec!["a".to_string(), "e".to_string()],
vec!["a".to_string(), "a".to_string()],
vec!["x".to_string(), "x".to_string()]
];
let vec1 = Solution::calc_equation(eq, val, que);
//println!("{:?}", vec1);
assert_eq!(vec1, vec![6.0, 0.5, -1.0, 1.0, -1.0])
}
#[test]
fn test_find_circle_num() {
let c = vec![vec![1, 1, 0], vec![1, 1, 0], vec![0, 0, 1]];
let n = Solution::find_circle_num(c);
//println!("{}", n);
assert_eq!(n, 2);
}
#[test]
fn test_predict_the_winner() {
let nums = vec![1, 5, 233, 7];
let w = Solution::predict_the_winner(nums);
//println!("{}", w);
assert_eq!(w, true);
}
#[test]
fn test_first_uniq_char() {
let s = "leetcode".to_string();
let i = Solution::first_uniq_char(s);
//println!("{}", i);
assert_eq!(i, 0);
}
#[test]
fn test_find_redundant_connection() {
let edges = vec![vec![1, 2], vec![2, 3], vec![3, 4], vec![1, 4], vec![1, 5]];
@ -2391,12 +1788,4 @@ mod tests {
//println!("{}", i);
assert_eq!(i, 5);
}
#[test]
fn test_find_duplicate() {
let nums = vec![8, 7, 1, 10, 17, 15, 18, 11, 16, 9, 19, 12, 5, 14, 3, 4, 2, 13, 18, 18];
let i = Solution::find_duplicate(nums);
// println!("{}", i);
assert_eq!(i, 18);
}
}