4306 lines
139 KiB
Rust
4306 lines
139 KiB
Rust
//! 题库
|
||
|
||
use crate::structure::*;
|
||
use crate::*;
|
||
use std::cell::RefCell;
|
||
use std::rc::Rc;
|
||
use std::ops::Add;
|
||
|
||
impl Solution {
|
||
/// 1.两数之和
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/two-sum/)
|
||
fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
|
||
let mut m = std::collections::HashMap::new();
|
||
for (i, v) in nums.into_iter().enumerate() {
|
||
if m.contains_key(&v) {
|
||
return vec![m[&v], i as i32];
|
||
}
|
||
m.insert(target - v, i as i32);
|
||
}
|
||
vec![]
|
||
}
|
||
|
||
/// 2.两数相加
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/add-two-numbers/)
|
||
pub fn add_two_numbers(mut l1: Option<Box<ListNode>>, mut l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
|
||
let mut sum = 0;
|
||
let mut l = None;
|
||
let mut p = &mut l;
|
||
|
||
loop {
|
||
match (l1, l2) {
|
||
(Some(v1), Some(v2)) => {
|
||
sum += v1.val + v2.val;
|
||
l1 = v1.next;
|
||
l2 = v2.next;
|
||
}
|
||
(Some(v1), None) => {
|
||
sum += v1.val;
|
||
l1 = v1.next;
|
||
l2 = None;
|
||
}
|
||
(None, Some(v2)) => {
|
||
sum += v2.val;
|
||
l2 = v2.next;
|
||
l1 = None;
|
||
}
|
||
(None, None) => {
|
||
break;
|
||
}
|
||
}
|
||
*p = Some(Box::new(ListNode::new(sum % 10))); //不管sum是否大于10,都可以使用sum%10的值来构建新“节点“
|
||
sum /= 10; // 获取进位值,否则初始为0
|
||
if let Some(p_box_node) = p {
|
||
p = &mut p_box_node.next
|
||
}
|
||
}
|
||
if sum != 0 {
|
||
*p = Some(Box::new(ListNode::new(sum)));
|
||
}
|
||
l
|
||
}
|
||
|
||
/// 剑指 Offer 64.求1+2+…+n
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/qiu-12n-lcof/)
|
||
///
|
||
/// 位运算实现乘法
|
||
pub fn sum_nums(n: i32) -> i32 {
|
||
assert!(1 <= n && n <= 10000);
|
||
let x = n + 1;
|
||
let mut sum = 0;
|
||
(x & 0x0001 != 0) && (sum += n) == ();
|
||
(x & 0x0002 != 0) && (sum += n << 0x1) == ();
|
||
(x & 0x0004 != 0) && (sum += n << 0x2) == ();
|
||
(x & 0x0008 != 0) && (sum += n << 0x3) == ();
|
||
(x & 0x0010 != 0) && (sum += n << 0x4) == ();
|
||
(x & 0x0020 != 0) && (sum += n << 0x5) == ();
|
||
(x & 0x0040 != 0) && (sum += n << 0x6) == ();
|
||
(x & 0x0080 != 0) && (sum += n << 0x7) == ();
|
||
(x & 0x0100 != 0) && (sum += n << 0x8) == ();
|
||
(x & 0x0200 != 0) && (sum += n << 0x9) == ();
|
||
(x & 0x0400 != 0) && (sum += n << 0xA) == ();
|
||
(x & 0x0800 != 0) && (sum += n << 0xB) == ();
|
||
(x & 0x1000 != 0) && (sum += n << 0xC) == ();
|
||
(x & 0x2000 != 0) && (sum += n << 0xD) == ();
|
||
sum = sum >> 1;
|
||
return sum;
|
||
|
||
//(1..=n).sum()
|
||
}
|
||
|
||
/// 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
|
||
}
|
||
|
||
/// 218.天际线问题
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/the-skyline-problem/)
|
||
fn get_skyline(buildings: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 136.只出现一次的数字
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/single-number/)
|
||
///
|
||
/// 初始化0, 循环遍历异或运算
|
||
fn single_number(nums: Vec<i32>) -> i32 {
|
||
nums.iter().fold(0, |acc, &s| s ^ acc)
|
||
}
|
||
|
||
/// 260.只出现一次的数字 III
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/single-number-iii/)
|
||
pub fn single_number3(nums: Vec<i32>) -> Vec<i32> {
|
||
let mask = nums.iter().fold(0, |acc, &s| s ^ acc);
|
||
let diff = mask & (-mask);
|
||
let d = nums.iter().fold(0, |mut acc, &num| {
|
||
if (num & diff) != 0 { acc ^= num; }
|
||
acc
|
||
});
|
||
vec![d, mask ^ d]
|
||
}
|
||
|
||
/// 268.缺失数字
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/missing-number/)
|
||
pub fn missing_number(nums: Vec<i32>) -> i32 {
|
||
(nums.len() as i32 + 1) * (nums.len() as i32) / 2 - (nums.iter().sum::<i32>())
|
||
|
||
//(1..=(nums.len() as i32)).sum::<i32>() - (nums.iter().sum::<i32>())
|
||
|
||
// nums.iter().enumerate().fold(nums.len() as i32, |mut m, (i, &n)| {
|
||
// m ^= (i as i32) ^ n;
|
||
// m
|
||
// })
|
||
}
|
||
|
||
/// 405.数字转换为十六进制数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/convert-a-number-to-hexadecimal/)
|
||
pub fn num_to_hex(num: i32) -> String {
|
||
const LOOKUP: [char; 16] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
||
let mut num = num as usize & 0xffffffff;
|
||
let mut hex = String::new();
|
||
while num != 0 {
|
||
hex.insert(0, LOOKUP[num & 0xf]);
|
||
num >>= 4;
|
||
}
|
||
if hex.is_empty() {
|
||
hex.push('0');
|
||
}
|
||
hex
|
||
}
|
||
|
||
/// 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
|
||
}
|
||
|
||
/// 191.汉明权重
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/number-of-1-bits/)
|
||
///
|
||
/// 循环消去末尾1
|
||
pub fn hamming_weight(mut n: u32) -> i32 {
|
||
let mut x = 0;
|
||
while n != 0 {
|
||
x += 1;
|
||
n &= n - 1;
|
||
}
|
||
x
|
||
}
|
||
|
||
/// 190.颠倒二进制位
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/reverse-bits/)
|
||
///
|
||
/// 对应位掩码
|
||
pub fn reverse_bits(n: u32) -> u32 {
|
||
let mut n = n;
|
||
n = ((n & 0xffff0000u32) >> 16) | ((n & 0x0000ffffu32) << 16);
|
||
n = ((n & 0xff00ff00u32) >> 8) | ((n & 0x00ff00ffu32) << 8);
|
||
n = ((n & 0xf0f0f0f0u32) >> 4) | ((n & 0x0f0f0f0fu32) << 4);
|
||
n = ((n & 0xccccccccu32) >> 2) | ((n & 0x33333333u32) << 2);
|
||
n = ((n & 0xaaaaaaaau32) >> 1) | ((n & 0x55555555u32) << 1);
|
||
n
|
||
}
|
||
|
||
/// 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
|
||
}
|
||
|
||
/// 509.斐波那契数列
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/fibonacci-number/)
|
||
/// [原题链接](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/)
|
||
/// [原题链接](https://leetcode-cn.com/problems/climbing-stairs/)
|
||
///
|
||
/// # 方法1 动态规划
|
||
/// ```rust
|
||
/// pub fn fib(n: i32) -> i32 {
|
||
/// (0..n).fold((0u64, 1), |(p1, p2), _| (p2, p1 + p2)).0 as i32
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 通项公式
|
||
/// ```rust
|
||
/// pub fn fib(n: i32) -> i32 {
|
||
/// let t = 5.0f64.sqrt();
|
||
/// (((1.0f64 / t) * (((1.0f64 + t) / 2.0f64).powi(n) - ((1.0f64 - t) / 2.0f64).powi(n))) + 1e-10) as i32
|
||
/// }
|
||
/// ```
|
||
/// # 方法3 递归
|
||
/// ```rust
|
||
/// pub fn fib(n: i32) -> i32 {
|
||
/// if n == 0 {
|
||
/// 0
|
||
/// }else if n==1 {
|
||
/// 1
|
||
/// }else if n==2 {
|
||
/// 1
|
||
/// }else {
|
||
/// fib(n-1)+fib(n-2)
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
/// # 方法4 查表
|
||
/// ```rust
|
||
/// pub fn fib(n: i32) -> i32 {
|
||
/// let lookup = vec![0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040];
|
||
/// lookup[(n % 31) as usize]
|
||
/// }
|
||
/// ```
|
||
pub fn fib(n: i32) -> i32 {
|
||
let t = 5.0f64.sqrt();
|
||
(((1.0f64 / t) * (((1.0f64 + t) / 2.0f64).powi(n) - ((1.0f64 - t) / 2.0f64).powi(n))) + 1e-10) as i32
|
||
}
|
||
|
||
/// 1502.判断能否形成等差数列
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/can-make-arithmetic-progression-from-sequence/)
|
||
pub fn can_make_arithmetic_progression(mut arr: Vec<i32>) -> bool {
|
||
if arr.len() < 3 {
|
||
return true;
|
||
}
|
||
|
||
arr.sort();
|
||
|
||
let d = arr[1] - arr[0];
|
||
|
||
for i in 1..arr.len() {
|
||
if arr[i] != arr[i - 1] + d {
|
||
return false;
|
||
}
|
||
}
|
||
true
|
||
}
|
||
|
||
/// 1025.除数博弈
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/divisor-game/)
|
||
///
|
||
/// 偶赢奇输
|
||
pub fn divisor_game(n: i32) -> bool {
|
||
(n & 1) == 0
|
||
}
|
||
|
||
/// 693.交替位二进制数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/binary-number-with-alternating-bits/)
|
||
///
|
||
pub fn has_alternating_bits(n: i32) -> bool {
|
||
let n = (n ^ (n >> 1));
|
||
(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)
|
||
}
|
||
|
||
/// 292.Nim 游戏
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/nim-game/)
|
||
pub fn can_win_nim(n: i32) -> bool {
|
||
(n & 3) == 0
|
||
}
|
||
|
||
/// 224.基本计算器
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/basic-calculator/)
|
||
/// todo
|
||
pub fn calculate(s: String) -> i32 {
|
||
let mut stack = Vec::<i32>::new();
|
||
let mut operand = 0;
|
||
let mut result = 0;
|
||
let mut sign = 1;
|
||
|
||
let s = s.into_bytes();
|
||
|
||
for i in 0..s.len() {
|
||
let ch = s[i];
|
||
ch.is_ascii_digit();
|
||
match ch {
|
||
b'0'..=b'9' => operand = 10 * operand + (ch - b'0') as i32,
|
||
b'+' => {
|
||
result += sign * operand;
|
||
sign = 1;
|
||
operand = 0;
|
||
}
|
||
b'-' => {
|
||
result += sign * operand;
|
||
sign = -1;
|
||
operand = 0;
|
||
}
|
||
b'(' => {
|
||
stack.push(result);
|
||
stack.push(sign);
|
||
sign = 1;
|
||
result = 0;
|
||
}
|
||
b')' => {
|
||
result += sign * operand;
|
||
result *= stack.pop().unwrap();
|
||
result += stack.pop().unwrap();
|
||
operand = 0;
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
|
||
result + (sign * operand)
|
||
}
|
||
|
||
/// 412.Fizz Buzz
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/fizz-buzz/)
|
||
pub fn fizz_buzz(n: i32) -> Vec<String> {
|
||
(1..=n).fold(vec![], |mut acc, i| {
|
||
acc.push(String::from(if i % 3 == 0 { if i % 5 == 0 { "FizzBuzz".to_string() } else { "Fizz".to_string() } } else { if i % 5 == 0 { "Buzz".to_string() } else { format!("{}", i) } }));
|
||
acc
|
||
})
|
||
}
|
||
|
||
/// 46.全排列
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/permutations/)
|
||
pub fn permute(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
|
||
/*fn dfs(ret: &mut Vec<Vec<i32>>, nums: &Vec<i32>, path: &mut Vec<i32>, vis: &mut Vec<bool>) {
|
||
if nums.len() == path.len() {
|
||
ret.push(path.clone());
|
||
}
|
||
for i in 0..nums.len() {
|
||
if !vis[i] {
|
||
path.push(nums[i]);
|
||
vis[i] = true;
|
||
dfs(ret, nums, path, vis);
|
||
vis[i] = false;
|
||
path.pop();
|
||
}
|
||
}
|
||
}
|
||
let mut ret = Vec::<Vec<i32>>::new();
|
||
dfs(&mut ret, &nums, &mut vec![], &mut vec![false; nums.len()]);
|
||
ret*/
|
||
fn dfs(ret: &mut Vec<Vec<i32>>, nums: &mut Vec<i32>, path: &mut Vec<i32>) {
|
||
if nums.is_empty() {
|
||
ret.push(path.clone());
|
||
}
|
||
for i in 0..nums.len() {
|
||
path.push(nums[i]);
|
||
let mut new_nums = nums.clone();
|
||
new_nums.remove(i);
|
||
dfs(ret, &mut new_nums, path);
|
||
path.pop();
|
||
}
|
||
}
|
||
let mut ret = Vec::<Vec<i32>>::new();
|
||
dfs(&mut ret, &mut nums, &mut Vec::new());
|
||
ret
|
||
}
|
||
|
||
/// 面试题 16.01.交换数字
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/swap-numbers-lcci/)
|
||
pub fn swap_numbers(mut numbers: Vec<i32>) -> Vec<i32> {
|
||
numbers[0] ^= numbers[1];
|
||
numbers[1] ^= numbers[0];
|
||
numbers[0] ^= numbers[1];
|
||
numbers
|
||
}
|
||
|
||
/// 20.有效的括号
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/valid-parentheses/)
|
||
pub fn is_valid(s: String) -> bool {
|
||
let mut v = vec![];
|
||
for c in s.chars() {
|
||
match c as char {
|
||
'(' | '[' | '{' => v.push(c),
|
||
')' => {
|
||
match v.last() {
|
||
None => return false,
|
||
Some(s) => {
|
||
if *s == '(' {
|
||
v.pop();
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
']' => {
|
||
match v.last() {
|
||
None => return false,
|
||
Some(s) => {
|
||
if *s == '[' {
|
||
v.pop();
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
'}' => {
|
||
match v.last() {
|
||
None => return false,
|
||
Some(s) => {
|
||
if *s == '{' {
|
||
v.pop();
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_ => (),
|
||
}
|
||
}
|
||
v.is_empty()
|
||
}
|
||
|
||
/// 104.二叉树的最大深度
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/)
|
||
pub fn max_depth(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
|
||
if let Some(node) = root {
|
||
1 + std::cmp::max(Self::max_depth(node.borrow().left.clone()), Self::max_depth(node.borrow().right.clone()))
|
||
} else {
|
||
0
|
||
}
|
||
}
|
||
|
||
/// 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)
|
||
}
|
||
}
|
||
|
||
/// 169.多数元素
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/majority-element/)
|
||
pub fn majority_element(nums: Vec<i32>) -> i32 {
|
||
nums.iter().fold((0, -1), |mut acc, &num| {
|
||
if acc.0 == 0 { acc.1 = num }
|
||
acc.0 += if acc.1 == num { 1 } else { -1 };
|
||
acc
|
||
}).1
|
||
}
|
||
|
||
/// 1404.将二进制表示减到 1 的步骤数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/number-of-steps-to-reduce-a-number-in-binary-representation-to-one/)
|
||
pub fn num_steps(s: String) -> i32 {
|
||
let mut result = 0;
|
||
let mut meet1 = false;
|
||
|
||
for t in s.chars().rev().enumerate() {
|
||
if t.1 == '0' {
|
||
result += if meet1 { 2 } else { 1 }
|
||
} else {
|
||
if !meet1 {
|
||
if t.0 != (s.len() - 1) {
|
||
result += 2;
|
||
}
|
||
meet1 = true;
|
||
} else {
|
||
result += 1;
|
||
}
|
||
}
|
||
}
|
||
result
|
||
}
|
||
|
||
/// 201.数字范围按位与
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/bitwise-and-of-numbers-range/)
|
||
pub fn range_bitwise_and(m: i32, n: i32) -> i32 {
|
||
//! # 方法1
|
||
//! 每次循环得到前缀掩码左移一位,直到前缀相同。
|
||
//! ```rust
|
||
//! let mut mask = -1i32;
|
||
//! while ((m ^ n) & mask) != 0 {
|
||
//! mask <<= 1;
|
||
//! }
|
||
//! m & mask
|
||
//! ```
|
||
//! # 方法2
|
||
//! 循环消去较大值的末尾1,直到前缀相同。
|
||
//! ```rust
|
||
//! while n > m {
|
||
//! n = n & (n - 1);
|
||
//! }
|
||
//! n
|
||
//! ```
|
||
//! # 方法3
|
||
//! 两数异或后将其最高位1后的位全部置为1,再取反码得到前缀掩码。
|
||
//!
|
||
//! 时间复杂度近似O(1)。空间复杂度O(1),只用到了一个掩码。
|
||
//! ```rust
|
||
//! if m == n {
|
||
//! return m;
|
||
//! }
|
||
//! let mut mask = m ^ n;
|
||
//! mask |= (mask >> 1);
|
||
//! mask |= (mask >> 2);
|
||
//! mask |= (mask >> 4);
|
||
//! mask |= (mask >> 8);
|
||
//! mask |= (mask >> 16);
|
||
//!
|
||
//! m & (!mask)
|
||
//! ```
|
||
|
||
if m == n {
|
||
return m;
|
||
}
|
||
|
||
let mut mask = m ^ n;
|
||
|
||
mask |= (mask >> 1);
|
||
mask |= (mask >> 2);
|
||
mask |= (mask >> 4);
|
||
mask |= (mask >> 8);
|
||
mask |= (mask >> 16);
|
||
|
||
m & (!mask)
|
||
}
|
||
|
||
/// 面试题 08.03.魔术索引
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/magic-index-lcci/)
|
||
///
|
||
/// 循环遍历
|
||
/// todo:二分查找加DFS
|
||
pub fn find_magic_index(nums: Vec<i32>) -> i32 {
|
||
let mut idx = -1;
|
||
for i in nums.iter().enumerate() {
|
||
if *i.1 as usize == i.0 {
|
||
return i.0 as i32;
|
||
}
|
||
}
|
||
idx
|
||
}
|
||
|
||
/// 171.Excel表列序号
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/excel-sheet-column-number/)
|
||
pub fn title_to_number(s: String) -> i32 {
|
||
s.chars().fold(0, |col, c| col * 26 + c as i32 - 64)
|
||
}
|
||
|
||
/// 168.Excel表列名称
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/excel-sheet-column-title/)
|
||
pub fn convert_to_title(n: i32) -> String {
|
||
let mut s = String::with_capacity(8);
|
||
let mut n = n;
|
||
while n != 0 {
|
||
let c = (((n - 1) % 26) as u8 + b'A') as char;
|
||
s.insert(0, c);
|
||
n = (n - 1) / 26;
|
||
}
|
||
|
||
s
|
||
}
|
||
|
||
/// 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
|
||
}
|
||
|
||
/// 78.子集
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/subsets/)
|
||
pub fn subsets(nums: Vec<i32>) -> Vec<Vec<i32>> {
|
||
let mut ret = vec![vec![]];
|
||
|
||
for num in nums {
|
||
let mut temp = ret.clone();
|
||
temp.iter_mut().for_each(|x| x.push(num));
|
||
ret.append(&mut temp);
|
||
}
|
||
|
||
ret
|
||
}
|
||
|
||
/// 面试题 16.07.最大数值
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/maximum-lcci/)
|
||
///
|
||
/// # 方法1
|
||
/// 内置函数
|
||
/// ```rust
|
||
/// pub fn maximum(a: i32, b: i32) -> i32 {
|
||
/// std::cmp::max(a, b)
|
||
/// }
|
||
/// ```
|
||
/// # 方法2
|
||
/// 数学公式 max(a, b) = (|a - b| + a + b) / 2。使用64位计算,避免溢出。实现见源码。
|
||
pub fn maximum(a: i32, b: i32) -> i32 {
|
||
((a as i64 - b as i64).abs() + a as i64 + b as i64 >> 1) as i32
|
||
}
|
||
|
||
/// 面试题 05.01.插入
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/insert-into-bits-lcci/)
|
||
///
|
||
/// i到j位置0,或运算设置位
|
||
pub fn insert_bits(n: i32, m: i32, i: i32, j: i32) -> i32 {
|
||
n & !(((1 << (j - i + 1)) - 1) << i) | (m << i)
|
||
}
|
||
|
||
/// 1480.一维数组的动态和
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/running-sum-of-1d-array/)
|
||
pub fn running_sum(mut nums: Vec<i32>) -> Vec<i32> {
|
||
nums.iter().scan(0, |s, i| {
|
||
*s += *i;
|
||
Some(*s)
|
||
}).collect()
|
||
}
|
||
|
||
/// 1108.IP 地址无效化
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/defanging-an-ip-address/)
|
||
pub fn defang_i_paddr(address: String) -> String {
|
||
address.replace(".", "[.]")
|
||
}
|
||
|
||
/// 1281.整数的各位积和之差
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/subtract-the-product-and-sum-of-digits-of-an-integer/)
|
||
pub fn subtract_product_and_sum(mut n: i32) -> i32 {
|
||
let mut add = 0;
|
||
let mut mul = 1;
|
||
while n > 0 {
|
||
let digit = n % 10;
|
||
n /= 10;
|
||
add += digit;
|
||
mul *= digit;
|
||
}
|
||
mul - add
|
||
}
|
||
|
||
/// 1295.统计位数为偶数的数字
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/find-numbers-with-even-number-of-digits/)
|
||
///
|
||
/// # 方法1 字符串长度
|
||
/// ```rust
|
||
/// pub fn find_numbers(nums: Vec<i32>) -> i32 {
|
||
/// nums.iter().fold(0, |mut acc, x| {
|
||
/// acc += (1usize - (x.to_string().len() & 1usize)) as i32;
|
||
/// acc
|
||
/// })
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 取以10为底的对数
|
||
/// ```rust
|
||
/// pub fn find_numbers(nums: Vec<i32>) -> i32 {
|
||
/// nums.iter().map(|&x| { ((x as f32).log10()) as i32 & 1 }).sum()
|
||
/// }
|
||
/// ```
|
||
/// # 方法3 除10
|
||
/// ```rust
|
||
/// pub fn find_numbers(nums: Vec<i32>) -> i32 {
|
||
/// let mut res = 0;
|
||
/// for mut num in nums {
|
||
/// let mut b = 0;
|
||
/// while num > 9 {
|
||
/// num /= 10;
|
||
/// b += 1;
|
||
/// }
|
||
/// res += b & 1;
|
||
/// }
|
||
/// res
|
||
/// }
|
||
/// ```
|
||
/// # 方法4 暴力
|
||
pub fn find_numbers(nums: Vec<i32>) -> i32 {
|
||
let mut ret = 0i32;
|
||
for n in nums {
|
||
ret += match n {
|
||
10..=99 | 1000..=9999 | 100000 => 1,
|
||
_ => 0
|
||
}
|
||
}
|
||
ret
|
||
/*nums.iter().fold(0i32, |acc, &x| acc + match x {
|
||
10..=99 | 1000..=9999 | 100000 => 1,
|
||
_ => 0
|
||
})*/
|
||
//nums.iter().filter(|&&num| (10 <= num && num < 100) || (1000 <= num && num < 10000) || num == 100000).count() as i32
|
||
}
|
||
|
||
/// 51.N皇后
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/n-queens/)
|
||
/// todo
|
||
pub fn solve_n_queens(n: i32) -> Vec<Vec<String>> {
|
||
fn generate_board(queens: &Vec<usize>, n: usize) -> Vec<String> {
|
||
let mut board = Vec::<String>::with_capacity(n);
|
||
for i in 0..n {
|
||
let mut row = vec![b'.'; n];
|
||
row[queens[i]] = b'Q';
|
||
board.push(String::from_utf8(row).unwrap());
|
||
}
|
||
board
|
||
}
|
||
fn solve(solutions: &mut Vec<Vec<String>>, queens: &mut Vec<usize>, n: usize, row: usize, columns: usize, diagonals1: usize, diagonals2: usize) {
|
||
if row == n {
|
||
solutions.push(generate_board(queens, n));
|
||
} else {
|
||
let mut available_positions = ((1 << n) - 1) & (!(columns | diagonals1 | diagonals2));
|
||
while available_positions != 0 {
|
||
let position = available_positions & ((!available_positions) + 1);
|
||
available_positions = available_positions & (available_positions - 1);
|
||
let column = position.trailing_zeros() as usize;
|
||
queens[row] = column;
|
||
solve(solutions, queens, n, row + 1, columns | position, (diagonals1 | position) >> 1, (diagonals2 | position) << 1);
|
||
queens[row] = usize::MAX;
|
||
}
|
||
}
|
||
}
|
||
let mut solutions = Vec::<Vec<String>>::new();
|
||
solve(&mut solutions, &mut vec![usize::MAX; n as usize], n as usize, 0, 0, 0, 0);
|
||
solutions
|
||
}
|
||
|
||
/// 100.相同的树
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/same-tree/)
|
||
/// todo
|
||
pub fn is_same_tree(p: Option<Rc<RefCell<TreeNode>>>, q: Option<Rc<RefCell<TreeNode>>>) -> bool {
|
||
match (p, q) {
|
||
(Some(r), Some(e)) => {
|
||
r.borrow().val == e.borrow().val
|
||
&& Solution::is_same_tree(r.borrow().left.clone(), e.borrow().left.clone())
|
||
&& Solution::is_same_tree(r.borrow().right.clone(), e.borrow().right.clone())
|
||
},
|
||
(Some(_r), None) => false,
|
||
(None, Some(_e)) => false,
|
||
(None, None) => true,
|
||
}
|
||
}
|
||
|
||
/// 6.Z 字形变换
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/zigzag-conversion/)
|
||
/// todo
|
||
pub fn convert(s: String, num_rows: i32) -> String {
|
||
if num_rows <= 1 {
|
||
return s;
|
||
}
|
||
let n = s.len();
|
||
let num_rows = num_rows as usize;
|
||
let cycle_len = 2 * num_rows - 2;
|
||
let s = s.into_bytes();
|
||
let mut ret = String::with_capacity(n);
|
||
for i in 0..num_rows {
|
||
let mut j = 0;
|
||
while j + i < n {
|
||
ret.push(s[i + j] as char);
|
||
if i != 0 && i != num_rows - 1 && j + cycle_len - i < n {
|
||
ret.push(s[j + cycle_len - i] as char);
|
||
}
|
||
j += cycle_len;
|
||
}
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 37.解数独
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/sudoku-solver/)
|
||
pub fn solve_sudoku(board: &mut Vec<Vec<char>>) {
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 36.有效的数独
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/valid-sudoku/)
|
||
pub fn is_valid_sudoku(board: Vec<Vec<char>>) -> bool {
|
||
let mut row_lookup = [[false; 9]; 9];
|
||
let mut col_lookup = [[false; 9]; 9];
|
||
let mut sub_lookup = [[false; 9]; 9];
|
||
for row in 0..9 {
|
||
for col in 0..9 {
|
||
if board[row][col] == '.' { continue; }
|
||
let idx = board[row][col] as usize - '1' as usize;
|
||
let sub_idx = ((row / 3) * 3 + col / 3) as usize;
|
||
if row_lookup[row][idx] || col_lookup[col][idx] || sub_lookup[sub_idx][idx] {
|
||
return false;
|
||
} else {
|
||
row_lookup[row][idx] = true;
|
||
col_lookup[col][idx] = true;
|
||
sub_lookup[sub_idx][idx] = true;
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/// 10.正则表达式匹配
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/regular-expression-matching/)
|
||
pub fn is_match(s: String, p: String) -> bool {
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 188.买卖股票的最佳时机 IV
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/)
|
||
/// todo
|
||
pub fn max_profit_iv(mut k: i32, prices: Vec<i32>) -> i32 {
|
||
/*if prices.is_empty() || k < 1 {
|
||
return 0;
|
||
}
|
||
let n = prices.len();
|
||
let k = std::cmp::min(k as usize, n / 2);
|
||
let mut buy = vec![i32::MIN / 2; k + 1];
|
||
let mut sell = vec![i32::MIN / 2; k + 1];
|
||
buy[0] = -prices[0];
|
||
sell[0] = 0;
|
||
for i in 1..n {
|
||
buy[0] = std::cmp::max(buy[0], sell[0] - prices[i]);
|
||
for j in 1..=k {
|
||
buy[j] = std::cmp::max(buy[j], sell[j] - prices[i]);
|
||
sell[j] = std::cmp::max(sell[j], buy[j - 1] + prices[i]);
|
||
}
|
||
}
|
||
*sell.iter().max().unwrap()*/
|
||
if prices.len() < 2 || k < 1 {
|
||
return 0;
|
||
}
|
||
let k = std::cmp::min(k as usize, prices.len() / 2);
|
||
let mut buy = vec![i32::MIN; k + 1];
|
||
let mut sell = vec![0; k + 1];
|
||
for p in prices {
|
||
for j in 1..=k {
|
||
buy[j] = buy[j].max(sell[j - 1] - p);
|
||
sell[j] = sell[j].max(buy[j] + p);
|
||
}
|
||
}
|
||
sell[k]
|
||
}
|
||
|
||
/// 123.买卖股票的最佳时机 III
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/)
|
||
/// todo
|
||
pub fn max_profit_iii(prices: Vec<i32>) -> i32 {
|
||
if prices.is_empty() {
|
||
return 0;
|
||
}
|
||
use std::cmp::max;
|
||
let (mut buy1, mut sell1) = (-prices[0], 0);
|
||
let (mut buy2, mut sell2) = (-prices[0], 0);
|
||
|
||
for i in 1..prices.len() {
|
||
buy1 = max(buy1, -prices[i]);
|
||
sell1 = max(sell1, buy1 + prices[i]);
|
||
buy2 = max(buy2, sell1 - prices[i]);
|
||
sell2 = max(sell2, buy2 + prices[i]);
|
||
}
|
||
sell2
|
||
}
|
||
|
||
/// 217.存在重复元素
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/contains-duplicate/)
|
||
pub fn contains_duplicate(nums: Vec<i32>) -> bool {
|
||
let mut set = std::collections::HashSet::<i32>::new();
|
||
for n in nums {
|
||
if !set.insert(n) {
|
||
return true;
|
||
}
|
||
}
|
||
false
|
||
}
|
||
|
||
/// 48.旋转图像
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/rotate-image/)
|
||
/// # 方法1 新矩阵旋转行
|
||
/// ```rust
|
||
/// pub fn rotate1(matrix: &mut Vec<Vec<i32>>) {
|
||
/// let n = matrix.len();
|
||
/// let mut matrix_new = matrix.clone();
|
||
/// for i in 0..n {
|
||
/// for j in 0..n {
|
||
/// matrix_new[j][n - i - 1] = matrix[i][j];
|
||
/// }
|
||
/// }
|
||
/// *matrix = matrix_new;
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 原地旋转 分块
|
||
/// ```rust
|
||
/// pub fn rotate1(matrix: &mut Vec<Vec<i32>>) {
|
||
/// let n = matrix.len();
|
||
/// for i in 0..n / 2 {
|
||
/// for j in 0..(n + 1) / 2 {
|
||
/// let temp = matrix[i][j];
|
||
/// matrix[i][j] = matrix[n - j - 1][i];
|
||
/// matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
|
||
/// matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
|
||
/// matrix[j][n - i - 1] = temp;
|
||
/// }
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
/// # 方法3 翻转代替旋转
|
||
///
|
||
pub fn rotate1(matrix: &mut Vec<Vec<i32>>) {
|
||
let n = matrix.len();
|
||
for i in 0..n / 2 {
|
||
for j in 0..n {
|
||
matrix[i][j] ^= matrix[n - i - 1][j];
|
||
matrix[n - i - 1][j] ^= matrix[i][j];
|
||
matrix[i][j] ^= matrix[n - i - 1][j];
|
||
}
|
||
}
|
||
for i in 0..n {
|
||
for j in 0..i {
|
||
matrix[i][j] ^= matrix[j][i];
|
||
matrix[j][i] ^= matrix[i][j];
|
||
matrix[i][j] ^= matrix[j][i];
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 125.验证回文串
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/valid-palindrome/)
|
||
/// # 方法1 双指针
|
||
/// 头尾双指针遍历
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn is_palindrome1(s: String) -> bool {
|
||
/// if s.len() <= 1 {
|
||
/// return true;
|
||
/// }
|
||
/// let s = s.into_bytes();
|
||
/// let (mut i, mut j) = (0usize, s.len() - 1);
|
||
/// while i < j {
|
||
/// while i < j && !s[i].is_ascii_alphanumeric() {
|
||
/// i += 1;
|
||
/// }
|
||
/// while i < j && !s[j].is_ascii_alphanumeric() {
|
||
/// j -= 1;
|
||
/// }
|
||
/// if i < j {
|
||
/// if s[i].to_ascii_lowercase() != s[j].to_ascii_lowercase() {
|
||
/// return false;
|
||
/// }
|
||
/// i += 1;
|
||
/// j -= 1;
|
||
/// }
|
||
/// }
|
||
/// true
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 筛选
|
||
/// 实现见源码
|
||
pub fn is_palindrome1(s: String) -> bool {
|
||
let a = s.to_ascii_lowercase().into_bytes().into_iter().filter(|c| c.is_ascii_alphanumeric()).collect::<Vec<u8>>();
|
||
let mut b = a.clone();
|
||
b.reverse();
|
||
a == b
|
||
}
|
||
|
||
/// 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
|
||
}
|
||
|
||
/// 67.二进制求和
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/add-binary/)
|
||
pub fn add_binary(mut a: String, mut b: String) -> String {
|
||
let mut carry = 0;
|
||
let mut res = String::new();
|
||
loop {
|
||
let (n1, n2) = (a.pop(), b.pop());
|
||
|
||
if n1 == None && n2 == None { break; }
|
||
|
||
let mut sum = carry;
|
||
if let Some(x) = n1 {
|
||
sum += x.to_digit(2).unwrap();
|
||
}
|
||
if let Some(x) = n2 {
|
||
sum += x.to_digit(2).unwrap();
|
||
}
|
||
|
||
carry = sum / 2;
|
||
res.insert_str(0, &(sum % 2).to_string());
|
||
}
|
||
if carry > 0 { res.insert_str(0, &carry.to_string()); }
|
||
res
|
||
}
|
||
|
||
/// 1342.将数字变成 0 的操作次数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/number-of-steps-to-reduce-a-number-to-zero/)
|
||
///
|
||
/// # 方法1 递归
|
||
/// ```rust
|
||
/// pub fn number_of_steps (num: i32) -> i32 {
|
||
/// if num > 1 {
|
||
/// 1 + (num & 1) + number_of_steps(num >> 1)
|
||
/// } else {
|
||
/// num
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 循环
|
||
pub fn number_of_steps(mut num: i32) -> i32 {
|
||
let mut res = 0;
|
||
while num > 1 {
|
||
res += 1 + (num & 1);
|
||
num >>= 1;
|
||
}
|
||
res + num
|
||
}
|
||
|
||
/// 830.较大分组的位置
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/positions-of-large-groups/)
|
||
pub fn large_group_positions(s: String) -> Vec<Vec<i32>> {
|
||
let c = s.into_bytes();
|
||
let mut start = 0i32;
|
||
let mut res = vec![];
|
||
for i in 1..=c.len() {
|
||
if i == c.len() || c[i - 1] != c[i] {
|
||
if i as i32 - start >= 3 {
|
||
res.push(vec![start, (i - 1) as i32]);
|
||
}
|
||
start = i as i32;
|
||
}
|
||
}
|
||
res
|
||
}
|
||
|
||
/// 1678.设计 Goal 解析器
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/goal-parser-interpretation/)
|
||
///
|
||
/// # 方法1 replase
|
||
/// ```rust
|
||
/// pub fn interpret(command: String) -> String {
|
||
/// command.replace("(al)", "al").replace("()", "o")
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 遍历
|
||
pub fn interpret(command: String) -> String {
|
||
let mut answer = String::new();
|
||
let mut pre = '\0';
|
||
for ch in command.chars() {
|
||
if ch == 'G' {
|
||
answer.push(ch);
|
||
} else if ch == ')' {
|
||
if pre == '(' {
|
||
answer.push('o');
|
||
} else {
|
||
answer.push_str("al");
|
||
}
|
||
}
|
||
pre = ch;
|
||
}
|
||
answer
|
||
}
|
||
|
||
/// LCP 06.拿硬币
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/na-ying-bi/)
|
||
pub fn min_count(coins: Vec<i32>) -> i32 {
|
||
coins.iter().map(|x| (x + 1) >> 1).sum()
|
||
}
|
||
|
||
/// LCP 17.速算机器人
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/nGK0Fy/)
|
||
///
|
||
/// # 方法1 遍历
|
||
/// ```rust
|
||
/// pub fn calculate2(s: String) -> i32 {
|
||
/// let t = s.chars().into_iter().fold((1, 0), |mut acc, ch| {
|
||
/// if ch == 'A' { acc.0 = 2 * acc.0 + acc.1 } else { acc.1 = 2 * acc.1 + acc.0 }
|
||
/// acc
|
||
/// });
|
||
/// t.0 + t.1
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 数学
|
||
pub fn calculate2(s: String) -> i32 {
|
||
1 << s.len() as i32
|
||
}
|
||
|
||
/// 剑指 Offer 05.替换空格
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/)
|
||
pub fn replace_space(s: String) -> String {
|
||
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 弗洛伊德算法
|
||
/// todo 解析
|
||
/// ## 复杂度分析
|
||
/// todo
|
||
/// ## 源码
|
||
/// ```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 加权并查集
|
||
/// todo
|
||
/// ## 复杂度分析
|
||
/// todo
|
||
/// ## 源码
|
||
/// 源码见实现
|
||
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
|
||
}
|
||
|
||
/// 189.旋转数组
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/rotate-array/)
|
||
///
|
||
/// # 方法1 暴力模拟法
|
||
/// ```rust
|
||
/// pub fn rotate(nums: &mut Vec<i32>, k: i32) {
|
||
/// for _ in 0..(k as usize % nums.len()) {
|
||
/// let n = nums.pop().unwrap();
|
||
/// nums.insert(0, n);
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 环状替换
|
||
/// ```rust
|
||
/// pub fn rotate(nums: &mut Vec<i32>, k: i32) {
|
||
/// let k = k as usize % nums.len();
|
||
/// if nums.len() <= 1 || k == 0 {
|
||
/// return;
|
||
/// }
|
||
/// let mut start_idx = 0usize;
|
||
/// let mut idx = start_idx;
|
||
/// let mut tmp = nums[idx];
|
||
/// for _ in 0..nums.len() {
|
||
/// idx = (idx + k) % nums.len();
|
||
/// let new_tmp = nums[idx];
|
||
/// nums[idx] = tmp;
|
||
/// tmp = new_tmp;
|
||
/// if idx == start_idx {
|
||
/// start_idx += 1;
|
||
/// idx = start_idx;
|
||
/// tmp = nums[idx];
|
||
/// }
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
/// # 方法3 数组翻转
|
||
/// ```rust
|
||
/// pub fn rotate(nums: &mut Vec<i32>, k: i32) {
|
||
/// let k = k as usize % nums.len();
|
||
/// let n = nums.len();
|
||
/// nums.reverse();
|
||
/// nums[0..k].reverse();
|
||
/// nums[k..n].reverse();
|
||
/// }
|
||
/// ```
|
||
/// # 方法4 内置方法
|
||
/// ```rust
|
||
/// pub fn rotate(nums: &mut Vec<i32>, k: i32) {
|
||
/// let k = k as usize % nums.len();
|
||
/// nums.rotate_right(k);
|
||
/// }
|
||
/// ```
|
||
pub fn rotate(nums: &mut Vec<i32>, k: i32) {
|
||
let k = k as usize % nums.len();
|
||
nums.rotate_right(k);
|
||
}
|
||
|
||
/// 135.分发糖果
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/candy/)
|
||
pub fn candy(ratings: Vec<i32>) -> i32 {
|
||
unimplemented!();
|
||
}
|
||
|
||
/// 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
|
||
}
|
||
}
|
||
|
||
/// 86.分隔链表
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/partition-list/)
|
||
/// todo
|
||
pub fn partition(mut head: Option<Box<ListNode>>, x: i32) -> Option<Box<ListNode>> {
|
||
let mut less_than_x_head = None;
|
||
let mut less_than_x = &mut less_than_x_head;
|
||
let mut greater_than_x_head = None;
|
||
let mut greater_than_x = &mut greater_than_x_head;
|
||
while let Some(mut box_node) = head {
|
||
head = box_node.next.take();
|
||
if box_node.val < x {
|
||
*less_than_x = Some(box_node);
|
||
less_than_x = &mut less_than_x.as_mut()?.next;
|
||
} else {
|
||
*greater_than_x = Some(box_node);
|
||
greater_than_x = &mut greater_than_x.as_mut()?.next;
|
||
}
|
||
}
|
||
*less_than_x = greater_than_x_head;
|
||
less_than_x_head
|
||
}
|
||
|
||
/// 239.滑动窗口最大值
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/sliding-window-maximum/)
|
||
/// [原题链接](https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/)
|
||
/// # 方法2 单调队列
|
||
/// ```rust
|
||
/// pub fn max_sliding_window(nums: Vec<i32>, k: i32) -> Vec<i32> {
|
||
/// if nums.is_empty() {
|
||
/// return vec![];
|
||
/// }
|
||
/// let k = k as usize;
|
||
/// let mut q = std::collections::VecDeque::<usize>::new();
|
||
/// for i in 0..k as usize {
|
||
/// while !q.is_empty() && nums[i] >= nums[*q.back().unwrap()] {
|
||
/// q.pop_back();
|
||
/// }
|
||
/// q.push_back(i);
|
||
/// }
|
||
/// let mut ans: Vec<i32> = vec![nums[*q.front().unwrap()]];
|
||
/// for i in k..nums.len() {
|
||
/// while !q.is_empty() && nums[i] >= nums[*q.back().unwrap()] {
|
||
/// q.pop_back();
|
||
/// }
|
||
/// q.push_back(i);
|
||
/// while *q.front().unwrap() <= i - k {
|
||
/// q.pop_front();
|
||
/// }
|
||
/// ans.push(nums[*q.front().unwrap()]);
|
||
/// }
|
||
/// ans
|
||
/// }
|
||
/// ```
|
||
/// todo
|
||
pub fn max_sliding_window(nums: Vec<i32>, k: i32) -> Vec<i32> {
|
||
if nums.is_empty() { return vec![]; }
|
||
#[derive(PartialEq, Eq)]
|
||
struct Item(i32, usize);
|
||
impl PartialOrd for Item {
|
||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||
self.0.partial_cmp(&other.0)
|
||
}
|
||
}
|
||
impl Ord for Item {
|
||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||
self.0.cmp(&other.0)
|
||
}
|
||
}
|
||
let n = nums.len();
|
||
let k = k as usize;
|
||
let mut q = std::collections::binary_heap::BinaryHeap::<Item>::new();
|
||
for i in 0..k {
|
||
q.push(Item(nums[i], i));
|
||
}
|
||
for i in k..n {
|
||
q.push(Item(nums[i], i));
|
||
/*while {
|
||
|
||
}*/
|
||
}
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 605.种花问题
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/can-place-flowers/)
|
||
/// todo
|
||
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;
|
||
}
|
||
|
||
/// 228.汇总区间
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/summary-ranges/)
|
||
pub fn summary_ranges(nums: Vec<i32>) -> Vec<String> {
|
||
if nums.is_empty() {
|
||
return Vec::new();
|
||
}
|
||
let mut ret = Vec::<String>::new();
|
||
let mut s = nums[0];
|
||
for i in 1..=nums.len() {
|
||
if i == nums.len() || nums[i] - nums[i - 1] != 1 {
|
||
if nums[i - 1] - s > 0 {
|
||
ret.push(format!("{}->{}", s, nums[i - 1]));
|
||
} else {
|
||
ret.push(format!("{}", s));
|
||
}
|
||
if i < nums.len() {
|
||
s = nums[i];
|
||
}
|
||
}
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 1202.交换字符串中的元素
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/smallest-string-with-swaps/)
|
||
/// # 方法1 并查集 优先队列
|
||
/// todo
|
||
///
|
||
/// # 方法2 DFS
|
||
///
|
||
/// ## 源码
|
||
/// todo
|
||
pub fn smallest_string_with_swaps(s: String, pairs: Vec<Vec<i32>>) -> String {
|
||
if pairs.is_empty() {
|
||
return s;
|
||
}
|
||
|
||
use std::collections::HashMap;
|
||
use std::collections::binary_heap::BinaryHeap;
|
||
use std::cmp::Reverse;
|
||
let len = s.len();
|
||
|
||
let mut parent = (0..len).collect::<Vec<usize>>();
|
||
let mut rank = vec![1usize; len];
|
||
|
||
fn find(parent: &mut Vec<usize>, x: usize) -> usize {
|
||
if x != parent[x] {
|
||
parent[x] = find(parent, parent[x]);
|
||
}
|
||
return parent[x];
|
||
}
|
||
|
||
fn union(parent: &mut Vec<usize>, rank: &mut Vec<usize>, x: usize, y: usize) {
|
||
let root_x = find(parent, x);
|
||
let root_y = find(parent, y);
|
||
if root_x == root_y {
|
||
return;
|
||
}
|
||
if rank[root_x] == rank[root_y] {
|
||
parent[root_x] = root_y;
|
||
rank[root_y] += 1;
|
||
} else if rank[root_x] < rank[root_y] {
|
||
parent[root_x] = parent[root_y];
|
||
} else {
|
||
parent[root_y] = parent[root_x];
|
||
}
|
||
}
|
||
|
||
for pair in pairs {
|
||
union(&mut parent, &mut rank, pair[0] as usize, pair[1] as usize);
|
||
}
|
||
|
||
let s = s.into_bytes();
|
||
let mut map = HashMap::<usize, BinaryHeap<Reverse<u8>>>::new();
|
||
for i in 0..len {
|
||
let root = find(&mut parent, i);
|
||
if map.contains_key(&root) {
|
||
map.get_mut(&root).unwrap().push(Reverse(s[i]));
|
||
} else {
|
||
let mut min_heap = BinaryHeap::<Reverse<u8>>::new();
|
||
min_heap.push(Reverse(s[i]));
|
||
map.insert(root, min_heap);
|
||
}
|
||
}
|
||
|
||
let mut ret = String::with_capacity(len);
|
||
for i in 0..len {
|
||
let root = find(&mut parent, i);
|
||
let c = map.get_mut(&root).unwrap().pop().unwrap().0;
|
||
ret.push(c as char);
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 1203.项目管理
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/sort-items-by-groups-respecting-dependencies/)
|
||
/// # 方法1 拓扑排序
|
||
/// todo
|
||
pub fn sort_items(n: i32, m: i32, group: Vec<i32>, before_items: Vec<Vec<i32>>) -> Vec<i32> {
|
||
fn top_sort(deg: &mut Vec<usize>, graph: &mut Vec<Vec<usize>>, items: &mut Vec<usize>) -> Vec<usize> {
|
||
let mut q = std::collections::VecDeque::<usize>::new();
|
||
let n = items.len();
|
||
for item in items {
|
||
if deg[*item] == 0 {
|
||
q.push_back(*item);
|
||
}
|
||
}
|
||
let mut res = Vec::<usize>::new();
|
||
while !q.is_empty() {
|
||
let u = q.pop_front().unwrap();
|
||
res.push(u);
|
||
for &v in &graph[u] {
|
||
deg[v] -= 1;
|
||
if deg[v] == 0 {
|
||
q.push_back(v);
|
||
}
|
||
}
|
||
}
|
||
if res.len() == n {
|
||
res
|
||
} else {
|
||
Vec::new()
|
||
}
|
||
}
|
||
let mut group_item = vec![Vec::<usize>::new(); (n + m) as usize];
|
||
let mut group_graph = vec![Vec::<usize>::new(); (n + m) as usize];
|
||
let mut item_graph = vec![Vec::<usize>::new(); n as usize];
|
||
|
||
let mut group_degree = vec![0usize; (n + m) as usize];
|
||
let mut item_degree = vec![0usize; n as usize];
|
||
|
||
let mut id = (0..((n + m) as usize)).collect::<Vec<usize>>();
|
||
let mut left_id = m as usize;
|
||
let mut group = group.into_iter().map(|x| x as usize).collect::<Vec<usize>>();
|
||
for i in 0..(n as usize) {
|
||
if group[i] == -1i32 as usize {
|
||
group[i] = left_id;
|
||
left_id += 1;
|
||
}
|
||
group_item[group[i]].push(i);
|
||
}
|
||
|
||
for i in 0..(n as usize) {
|
||
let curr_group_id = group[i];
|
||
for &item in &before_items[i] {
|
||
let before_group_id = group[item as usize];
|
||
if before_group_id == curr_group_id {
|
||
item_degree[i] += 1;
|
||
item_graph[item as usize].push(i);
|
||
} else {
|
||
group_degree[curr_group_id] += 1;
|
||
group_graph[before_group_id].push(curr_group_id);
|
||
}
|
||
}
|
||
}
|
||
|
||
let group_top_sort = top_sort(&mut group_degree, &mut group_graph, &mut id);
|
||
if group_top_sort.is_empty() {
|
||
return Vec::new();
|
||
}
|
||
let mut ans = Vec::<i32>::new();
|
||
|
||
for curr_group_id in group_top_sort {
|
||
//let size = group_item[curr_group_id].len();
|
||
if group_item[curr_group_id].len() == 0 {
|
||
continue;
|
||
}
|
||
let res = top_sort(&mut item_degree, &mut item_graph, &mut group_item[curr_group_id]);
|
||
if res.is_empty() {
|
||
return Vec::<i32>::new();
|
||
}
|
||
for item in res {
|
||
ans.push(item as i32);
|
||
}
|
||
}
|
||
ans
|
||
}
|
||
|
||
/// 9.回文数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/palindrome-number/)
|
||
/// # 方法1 字符串
|
||
/// ```rust
|
||
/// pub fn is_palindrome(x: i32) -> bool {
|
||
/// let xs = x.to_string().into_bytes();
|
||
/// let mut xsc = xs.clone();
|
||
/// xsc.reverse();
|
||
/// xs == xsc
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 对数 双指针
|
||
/// ```rust
|
||
/// pub fn is_palindrome(mut x: i32) -> bool {
|
||
/// if x < 0 {
|
||
/// return false;
|
||
/// }
|
||
/// let exp = (x as f64).log10() as u32;
|
||
/// let mut n = 10i32.pow(exp);
|
||
/// while x > 0 {
|
||
/// let top = x / n;
|
||
/// if top != x % 10 {
|
||
/// return false;
|
||
/// }
|
||
/// x -= n * top;
|
||
/// x /= 10;
|
||
/// n /= 100;
|
||
/// }
|
||
/// true
|
||
/// }
|
||
/// ```
|
||
/// # 方法3 求一半逆序数
|
||
pub fn is_palindrome(mut x: i32) -> bool {
|
||
if x < 0 || (x % 10 == 0 && x != 0) {
|
||
return false;
|
||
}
|
||
let mut r = 0;
|
||
while x > r {
|
||
r = r * 10 + x % 10;
|
||
x /= 10;
|
||
}
|
||
x == r || x == r / 10
|
||
}
|
||
|
||
/// 14.最长公共前缀
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/longest-common-prefix/)
|
||
/// # 方法1 排序
|
||
/// 排序后,返回第一个和最后一个的公共前缀
|
||
/// ##源码
|
||
/// ```rust
|
||
/// pub fn longest_common_prefix(mut strs: Vec<String>) -> String {
|
||
/// if strs.is_empty() {
|
||
/// return "".to_string();
|
||
/// }
|
||
/// strs.sort();
|
||
/// let first = strs.first().unwrap().as_bytes();
|
||
/// let last = strs.last().unwrap().as_bytes();
|
||
/// let n = std::cmp::min(first.len(), last.len());
|
||
/// let mut ret = String::with_capacity(n);
|
||
/// for i in 0..n {
|
||
/// if first[i] != last[i] {
|
||
/// break;
|
||
/// }
|
||
/// ret.push(first[i] as char);
|
||
/// }
|
||
/// ret
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 横向扫描
|
||
/// 每两个之间的公共前缀。
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn longest_common_prefix(mut strs: Vec<String>) -> String {
|
||
/// fn lcp(str1: &String, str2: &String) -> String {
|
||
/// let n = std::cmp::min(str1.len(), str2.len());
|
||
/// let b1 = str1.as_bytes();
|
||
/// let b2 = str2.as_bytes();
|
||
/// let mut ret = String::new();
|
||
/// for i in 0..n {
|
||
/// if b1[i] != b2[i] {
|
||
/// break;
|
||
/// }
|
||
/// ret.push(b1[i] as char);
|
||
/// }
|
||
/// ret
|
||
/// }
|
||
/// if strs.is_empty() {
|
||
/// return "".to_string();
|
||
/// }
|
||
/// let mut prefix = strs[0].clone();
|
||
/// for i in 1..strs.len() {
|
||
/// prefix = lcp(&prefix, &strs[i]);
|
||
/// if prefix.is_empty() {
|
||
/// break;
|
||
/// }
|
||
/// }
|
||
/// prefix
|
||
/// }
|
||
/// ```
|
||
/// # 方法3 纵向扫描
|
||
/// 从0开始每个字符是否相等。
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn longest_common_prefix(strs: Vec<String>) -> String {
|
||
/// if strs.is_empty() {
|
||
/// return "".to_string();
|
||
/// }
|
||
/// let length = strs[0].len();
|
||
/// let count = strs.len();
|
||
/// for i in 0..length {
|
||
/// let b = strs[0].as_bytes()[i];
|
||
/// for j in 1..count {
|
||
/// if i == strs[j].len() || strs[j].as_bytes()[i] != b {
|
||
/// return strs[0].split_at(i).0.clone().to_string();
|
||
/// }
|
||
/// }
|
||
/// }
|
||
/// return strs[0].clone();
|
||
/// }
|
||
/// ```
|
||
/// # 方法4 分治
|
||
/// 两两之间的公共前缀。
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn longest_common_prefix(strs: Vec<String>) -> String {
|
||
/// fn lcp(str1: &String, str2: &String) -> String {
|
||
/// let n = std::cmp::min(str1.len(), str2.len());
|
||
/// let b1 = str1.as_bytes();
|
||
/// let b2 = str2.as_bytes();
|
||
/// let mut ret = String::new();
|
||
/// for i in 0..n {
|
||
/// if b1[i] != b2[i] {
|
||
/// break;
|
||
/// }
|
||
/// ret.push(b1[i] as char);
|
||
/// }
|
||
/// ret
|
||
/// }
|
||
/// fn lcp_r(strs: &Vec<String>, start: usize, end: usize) -> String {
|
||
/// if start == end {
|
||
/// strs[start].clone()
|
||
/// } else {
|
||
/// let mid = (end - start) / 2 + start;
|
||
/// let lcp_left = lcp_r(strs, start, mid);
|
||
/// let lcp_right = lcp_r(strs, mid + 1, end);
|
||
/// lcp(&lcp_left, &lcp_right)
|
||
/// }
|
||
/// }
|
||
/// if strs.is_empty() {
|
||
/// "".to_string()
|
||
/// } else {
|
||
/// lcp_r(&strs, 0, strs.len() - 1).to_owned()
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
/// # 方法5 二分查找
|
||
/// # 方法6 字典树
|
||
pub fn longest_common_prefix(strs: Vec<String>) -> String {
|
||
if strs.is_empty() {
|
||
return "".to_string();
|
||
}
|
||
let length = strs[0].len();
|
||
let count = strs.len();
|
||
for i in 0..length {
|
||
let b = strs[0].as_bytes()[i];
|
||
for j in 1..count {
|
||
if i == strs[j].len() || strs[j].as_bytes()[i] != b {
|
||
return strs[0].split_at(i).0.clone().to_string();
|
||
}
|
||
}
|
||
}
|
||
return strs[0].clone();
|
||
}
|
||
|
||
/// 66.加一
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/plus-one/)
|
||
pub fn plus_one(mut digits: Vec<i32>) -> Vec<i32> {
|
||
for i in (0..digits.len()).rev() {
|
||
digits[i] += 1;
|
||
digits[i] = digits[i] % 10;
|
||
if digits[i] != 0 {
|
||
return digits;
|
||
}
|
||
}
|
||
let mut ret = vec![1];
|
||
ret.extend(digits);
|
||
ret
|
||
}
|
||
|
||
/// 69.x的平方根
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/sqrtx/)
|
||
/// # 方法1 内置函数
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// (x as f32).sqrt() as i32
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 牛顿迭代法
|
||
/// f(x) = x^2 - c 的零点,令x0=c,取f(x)在点(x0, f(x0))处切线的与x轴交点的坐标x1,迭代上一步。
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// if x == 0 {
|
||
/// return 0;
|
||
/// }
|
||
/// let c = x as f64;
|
||
/// let mut x0 = x as f64;
|
||
/// loop {
|
||
/// let xi = 0.5 * (x0 + c / x0);
|
||
/// if (x0 - xi).abs() < 1e-7 {
|
||
/// break;
|
||
/// }
|
||
/// x0 = xi;
|
||
/// }
|
||
/// x0 as i32
|
||
/// }
|
||
/// ```
|
||
/// # 方法3 二分查找法
|
||
/// 实现见源码
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// let (mut l, mut r, mut ans) = (0, x, -1);
|
||
/// while l <= r {
|
||
/// let mid = l + (r - l) / 2;
|
||
/// if mid as i64 * mid as i64 <= x as i64 {
|
||
/// ans = mid;
|
||
/// l = mid + 1;
|
||
/// } else {
|
||
/// r = mid - 1;
|
||
/// }
|
||
/// }
|
||
/// ans
|
||
/// }
|
||
/// ```
|
||
/// # 方法4 袖珍计算器算法
|
||
/// 使用指数函数和对数函数替换平方根函数的方法
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// let ans = (0.5f64 * (x as f64).ln()).exp() as i32;
|
||
/// if (ans + 1) as i64 * (ans + 1) as i64 <= x as i64 {
|
||
/// ans + 1
|
||
/// } else {
|
||
/// ans
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
/// # 方法5 卡马克快速平方根倒数
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// unsafe {
|
||
/// union X2f {
|
||
/// i: i64,
|
||
/// f: f64,
|
||
/// }
|
||
/// let x_half = 0.5f64 * x as f64;
|
||
/// let mut u = X2f { f: x as f64 };
|
||
/// u.i = 0x5FE6EC85E7DE30DA_i64 - (u.i >> 1);
|
||
/// u.f = u.f * (1.5f64 - x_half * u.f * u.f); // 牛顿迭代法
|
||
/// u.f = u.f * (1.5f64 - x_half * u.f * u.f);
|
||
/// u.f = u.f * (1.5f64 - x_half * u.f * u.f); // 三次迭代
|
||
/// return (1.0f64 / u.f) as i32;
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
pub fn my_sqrt(x: i32) -> i32 {
|
||
let x_half = 0.5f64 * x as f64;
|
||
let mut i = (x as f64).to_bits();
|
||
i = 0x5FE6EC85E7DE30DA_u64 - (i >> 1);
|
||
let mut f = f64::from_bits(i);
|
||
f = f * (1.5 - x_half * f * f);
|
||
f = f * (1.5 - x_half * f * f);
|
||
f = f * (1.5 - x_half * f * f);
|
||
(1.0f64 / f) as i32
|
||
}
|
||
|
||
/// 367.有效的完全平方数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/valid-perfect-square/)
|
||
/// 解题思路和求平方根一样,就不写了
|
||
pub fn is_perfect_square(num: i32) -> bool {
|
||
let q = (num as f64).sqrt() as i32;
|
||
num == q * q
|
||
}
|
||
|
||
/// 279.完全平方数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/perfect-squares/)
|
||
/// # 方法2 四平方定理
|
||
pub fn num_squares(mut n: i32) -> i32 {
|
||
/*let mut ret = 0;
|
||
while n > 0 {
|
||
let q = (n as f32).sqrt() as i32;
|
||
n -= q * q;
|
||
ret += 1;
|
||
}
|
||
ret*/
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 50.Pow(x, n)
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/powx-n/)
|
||
pub fn my_pow(mut x: f64, mut n: i32) -> f64 {
|
||
/*if n < 0 {
|
||
n = -n;
|
||
x = 1.0f64 / x;
|
||
}
|
||
let mut ret = 1.0f64;
|
||
for _ in 0..n {
|
||
ret *= x;
|
||
}
|
||
ret*/
|
||
//x.powi(n)
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 172.阶乘后的零
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/factorial-trailing-zeroes/)
|
||
/// todo
|
||
pub fn trailing_zeroes(mut n: i32) -> i32 {
|
||
let mut zero_count = 0;
|
||
while n > 0 {
|
||
n /= 5;
|
||
zero_count += n;
|
||
}
|
||
zero_count
|
||
}
|
||
|
||
/// 684.冗余连接
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/redundant-connection/)
|
||
///
|
||
/// # 方法1 并查集
|
||
/// todo
|
||
pub fn find_redundant_connection(edges: Vec<Vec<i32>>) -> Vec<i32> {
|
||
fn find(parent: &mut Vec<usize>, index: usize) -> usize {
|
||
if parent[index] != index {
|
||
parent[index] = find(parent, parent[index]);
|
||
}
|
||
parent[index]
|
||
}
|
||
fn union(parent: &mut Vec<usize>, index1: usize, index2: usize) {
|
||
let idx1 = find(parent, index1);
|
||
let idx2 = find(parent, index2);
|
||
parent[idx1] = idx2;
|
||
}
|
||
|
||
let nodes_count = edges.len();
|
||
let mut parent = (0..nodes_count + 1).collect::<Vec<usize>>();
|
||
for edge in edges {
|
||
let (node1, node2) = (edge[0] as usize, edge[1] as usize);
|
||
if find(&mut parent, node1) != find(&mut parent, node2) {
|
||
union(&mut parent, node1, node2);
|
||
} else {
|
||
return edge;
|
||
}
|
||
}
|
||
Vec::<i32>::new()
|
||
}
|
||
|
||
/// 58.最后一个单词的长度
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/length-of-last-word/)
|
||
/// # 方法1 反向遍历
|
||
/// 实现见源码
|
||
/// # 方法2 分割字符串
|
||
/// 先删除尾部的无效字符,按空格分割字符串,去最后一个,返回其长度。
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn length_of_last_word(s: String) -> i32 {
|
||
/// s.trim_end().split_whitespace().last().unwrap_or("").len() as i32
|
||
/// }
|
||
/// ```
|
||
pub fn length_of_last_word(s: String) -> i32 {
|
||
let mut ret = 0;
|
||
let s = s.into_bytes();
|
||
let mut is_last_word = false;
|
||
for &c in s.iter().rev() {
|
||
if c != b' ' {
|
||
is_last_word = true;
|
||
}
|
||
if is_last_word {
|
||
if c == b' ' {
|
||
is_last_word = false;
|
||
break;
|
||
}
|
||
ret += 1;
|
||
}
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 83.删除排序链表中的重复元素
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/)
|
||
pub fn delete_duplicates(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
|
||
unimplemented!();
|
||
}
|
||
|
||
/// 88.合并两个有序数组
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/merge-sorted-array/)
|
||
pub fn merge(nums1: &mut Vec<i32>, m: i32, nums2: &mut Vec<i32>, n: i32) {
|
||
/*nums1.resize(m as usize, 0);
|
||
nums1.extend(nums2.clone());
|
||
nums1.sort();*/
|
||
let mut p1 = m - 1;
|
||
let mut p2 = n - 1;
|
||
let mut p = m + n - 1;
|
||
while p1 >= 0 && p2 >= 0 {
|
||
if nums1[p1 as usize] < nums2[p2 as usize] {
|
||
nums1[p as usize] = nums2[p2 as usize];
|
||
p2 -= 1;
|
||
} else {
|
||
nums1[p as usize] = nums1[p1 as usize];
|
||
p1 -= 1;
|
||
}
|
||
p -= 1;
|
||
}
|
||
for i in 0..((p2 + 1) as usize) {
|
||
nums1[i] = nums2[i];
|
||
}
|
||
}
|
||
|
||
/// 1018.可被5整除的二进制前缀
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/binary-prefix-divisible-by-5/)
|
||
pub fn prefixes_div_by5(a: Vec<i32>) -> Vec<bool> {
|
||
let mut ret = Vec::<bool>::with_capacity(a.len());
|
||
let mut s = 0;
|
||
for n in a {
|
||
s = ((s << 1) + n) % 5;
|
||
ret.push(s == 0);
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 3.无重复字符的最长子串
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/)
|
||
/// # 方法1 HashMap
|
||
/// ```rust
|
||
/// pub fn length_of_longest_substring(s: String) -> i32 {
|
||
/// let s = s.into_bytes();
|
||
/// //存储每个字符最后的索引
|
||
/// let mut map = std::collections::HashMap::<u8, i32>::new();
|
||
/// //上一个重复值的索引 没有重复值的话返回 最后一个元素的索引减-1,为字符串的长度。
|
||
/// let mut k = -1i32;
|
||
/// //返回值
|
||
/// let mut ret = 0i32;
|
||
/// for (i, c) in s.iter().enumerate() {
|
||
/// let o = map.get(c).unwrap_or(&-1i32);
|
||
/// if k < *o {
|
||
/// k = *o;
|
||
/// } else {
|
||
/// ret = std::cmp::max(ret, i as i32 - k);
|
||
/// }
|
||
/// map.insert(*c, i as i32);
|
||
/// }
|
||
/// ret
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 查表
|
||
/// 使用带索引的迭代好像效率差一点。。。实现见源码。
|
||
pub fn length_of_longest_substring(s: String) -> i32 {
|
||
let (s, mut map, mut k, mut ret) = (s.into_bytes(), [-1; 128], -1i32, 0i32);
|
||
for i in 0..s.len() {
|
||
let o = map[s[i] as usize];
|
||
if k < o {
|
||
k = o;
|
||
} else {
|
||
ret = std::cmp::max(ret, i as i32 - k);
|
||
}
|
||
map[s[i] as usize] = i as i32;
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 8.字符串转换整数 (atoi)
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/string-to-integer-atoi/)
|
||
/// # 方法1 常规解法
|
||
/// if...else...逻辑结构 注意溢出
|
||
/// 实现见源码
|
||
/// # 方法2 有限状态机
|
||
/// todo
|
||
pub fn my_atoi(mut s: String) -> i32 {
|
||
let mut negative = false;
|
||
let mut res = 0i64;
|
||
for (i, ch) in s.trim().chars().enumerate() {
|
||
if ch == '+' && i == 0 { continue; }
|
||
if ch == '-' && i == 0 {
|
||
negative = true;
|
||
continue;
|
||
}
|
||
if !ch.is_digit(10) { break; }
|
||
res = 10i64 * res + ch.to_digit(10).unwrap() as i64;
|
||
if negative { if -res < i32::MIN as i64 { return i32::MIN; } } else { if res > i32::MAX as i64 { return i32::MAX; } }
|
||
}
|
||
|
||
if negative { -res as i32 } else { res as i32 }
|
||
}
|
||
|
||
/// 29.两数相除
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/divide-two-integers/)
|
||
/// # 方法1 内置API
|
||
/// ```rust
|
||
/// pub fn divide(dividend: i32, divisor: i32) -> i32 {
|
||
/// use std::ops::Div;
|
||
/// if divisor == 0 {
|
||
/// return 0;
|
||
/// } else if divisor == -1 && dividend == i32::MIN {
|
||
/// return i32::MAX;
|
||
/// }
|
||
/// dividend.div(divisor)
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 位运算除法
|
||
/// todo
|
||
pub fn divide(dividend: i32, divisor: i32) -> i32 {
|
||
if divisor == 0 {
|
||
return 0;
|
||
} else if divisor == -1 && dividend == i32::MIN {
|
||
return i32::MAX;
|
||
}
|
||
let negative = (dividend ^ divisor) < 0;
|
||
let mut t = (dividend as i64).abs();
|
||
let mut d = (divisor as i64).abs();
|
||
let mut ret = 0;
|
||
for i in (0..32).rev() {
|
||
if (t >> i) >= d {
|
||
ret |= 1 << i;
|
||
t -= d << i;
|
||
}
|
||
}
|
||
if negative {
|
||
-ret
|
||
} else {
|
||
ret
|
||
}
|
||
}
|
||
|
||
/// 947.移除最多的同行或同列石头
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/most-stones-removed-with-same-row-or-column/)
|
||
/// # 方法1 并查集
|
||
/// todo
|
||
/// 实现见源码
|
||
/// # 方法2 dfs
|
||
/// todo
|
||
pub fn remove_stones(stones: Vec<Vec<i32>>) -> i32 {
|
||
use std::collections::HashMap;
|
||
let mut parent = HashMap::<usize, usize>::new();
|
||
let mut count = 0usize;
|
||
fn find(parent: &mut HashMap<usize, usize>, count: &mut usize, x: usize) -> usize {
|
||
if !parent.contains_key(&x) {
|
||
parent.insert(x, x);
|
||
*count += 1;
|
||
}
|
||
if x != parent[&x] {
|
||
let v = find(parent, count, parent[&x]);
|
||
parent.insert(x, v);
|
||
}
|
||
parent[&x]
|
||
}
|
||
|
||
for stone in &stones {
|
||
let root_x = find(&mut parent, &mut count, !stone[0] as usize);
|
||
let root_y = find(&mut parent, &mut count, stone[1] as usize);
|
||
if root_x == root_y {
|
||
continue;
|
||
}
|
||
parent.insert(root_x, root_y);
|
||
count -= 1;
|
||
}
|
||
|
||
(stones.len() - count) as i32
|
||
}
|
||
|
||
/// 4.寻找两个正序数组的中位数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/median-of-two-sorted-arrays/)
|
||
/// # 方法1 暴力模拟法
|
||
/// ```rust
|
||
/// pub fn find_median_sorted_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
|
||
/// let mut ret = 0.0;
|
||
/// let mut nums = Vec::new();
|
||
/// nums.extend(nums1);
|
||
/// nums.extend(nums2);
|
||
/// if nums.is_empty() {
|
||
/// return ret;
|
||
/// }
|
||
/// nums.sort();
|
||
/// if nums.len() & 1 == 0 {
|
||
/// ret = (nums[nums.len() / 2 - 1] as f64 + nums[nums.len() / 2] as f64) / 2.0;
|
||
/// } else {
|
||
/// ret = nums[nums.len() / 2] as f64;
|
||
/// }
|
||
/// ret
|
||
/// }
|
||
/// ```
|
||
pub fn find_median_sorted_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
|
||
/*let t = nums1.len() + nums2.len();
|
||
let (mut i,mut j, k) = (0usize, 0usize, 0usize);
|
||
while i < nums1.len() || j < nums2.len() {
|
||
|
||
}*/
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 5.最长回文子串
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/longest-palindromic-substring/)
|
||
pub fn longest_palindrome(s: String) -> String {
|
||
/*if s.is_empty() {
|
||
return "".to_string();
|
||
}
|
||
use std::collections::VecDeque;
|
||
let s = s.into_bytes();
|
||
let q = VecDeque::<u8>::new();
|
||
for i in 1..s.len() {
|
||
|
||
}*/
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 11.盛最多水的容器
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/container-with-most-water/)
|
||
/// # 方法1 暴力模拟
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn max_area(height: Vec<i32>) -> i32 {
|
||
/// let mut area = 0;
|
||
/// for i in 0..height.len() {
|
||
/// for j in (i + 1)..height.len() {
|
||
/// area = area.max((j - i) as i32 * height[i].min(height[j]));
|
||
/// }
|
||
/// }
|
||
/// area
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 双指针
|
||
/// 每次淘汰掉双指针最小的那个数。实现见源码
|
||
pub fn max_area(height: Vec<i32>) -> i32 {
|
||
let (mut l, mut r) = (0, height.len() - 1);
|
||
let mut area = 0;
|
||
while l < r {
|
||
area = area.max((r - l) as i32 * height[l].min(height[r]));
|
||
if height[l] <= height[r] {
|
||
l += 1;
|
||
} else {
|
||
r -= 1;
|
||
}
|
||
}
|
||
area
|
||
}
|
||
|
||
/// 15.三数之和
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/3sum/)
|
||
pub fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 287.寻找重复数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/find-the-duplicate-number/)
|
||
/// # 方法1 排序
|
||
/// ```rust
|
||
/// pub fn find_duplicate(mut nums: Vec<i32>) -> i32 {
|
||
/// nums.sort();
|
||
/// for (idx, &n) in nums.iter().enumerate() {
|
||
/// if n == nums[idx + 1] {
|
||
/// return n;
|
||
/// }
|
||
/// }
|
||
/// 0
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 查表
|
||
/// ```rust
|
||
/// pub fn find_duplicate(nums: Vec<i32>) -> i32 {
|
||
/// let mut num_look = vec![0; nums.len()];
|
||
/// let mut idx = 0usize;
|
||
/// for n in nums {
|
||
/// idx = (n - 1) as usize;
|
||
/// if n == num_look[idx] {
|
||
/// return n;
|
||
/// }
|
||
/// num_look[idx] = n;
|
||
/// }
|
||
/// 0
|
||
/// }
|
||
/// ```
|
||
/// # 方法3 二分查找
|
||
/// # 方法4 二进制
|
||
/// # 方法5 快慢指针
|
||
/// todo
|
||
pub fn find_duplicate(nums: Vec<i32>) -> i32 {
|
||
let mut num_look = vec![0; nums.len()];
|
||
let mut idx = 0usize;
|
||
for n in nums {
|
||
idx = (n - 1) as usize;
|
||
if n == num_look[idx] {
|
||
return n;
|
||
}
|
||
num_look[idx] = n;
|
||
}
|
||
0
|
||
}
|
||
|
||
/// 448.找到所有数组中消失的数字
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/)
|
||
/// # 方法1 哈希表
|
||
/// todo 略
|
||
/// # 方法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/)
|
||
/// # 方法1 并查集
|
||
/// todo
|
||
pub fn hit_bricks(grid: Vec<Vec<i32>>, hits: Vec<Vec<i32>>) -> Vec<i32> {
|
||
const DIRECTIONS: [[i32; 2]; 4] = [[0, 1], [1, 0], [-1, 0], [0, -1]];
|
||
let rows = grid.len();
|
||
let cols = grid[0].len();
|
||
let mut copy = grid.clone();
|
||
for hit in &hits {
|
||
copy[hit[0] as usize][hit[1] as usize] = 0;
|
||
}
|
||
let grid_len = rows * cols;
|
||
|
||
let mut parent = (0..(grid_len + 1)).collect::<Vec<usize>>();
|
||
let mut size = vec![1usize; grid_len + 1];
|
||
|
||
fn in_area(x: usize, y: usize, rows: usize, cols: usize) -> bool {
|
||
x < rows && y < cols
|
||
}
|
||
fn get_idx(x: usize, y: usize, cols: usize) -> usize {
|
||
x * cols + y
|
||
}
|
||
fn find(parent: &mut Vec<usize>, x: usize) -> usize {
|
||
if x != parent[x] {
|
||
parent[x] = find(parent, parent[x]);
|
||
}
|
||
parent[x]
|
||
}
|
||
fn union(parent: &mut Vec<usize>, size: &mut Vec<usize>, x: usize, y: usize) {
|
||
let root_x = find(parent, x);
|
||
let root_y = find(parent, y);
|
||
if root_x == root_y {
|
||
return;
|
||
}
|
||
parent[root_x] = root_y;
|
||
size[root_y] += size[root_x];
|
||
}
|
||
fn get_size(parent: &mut Vec<usize>, size: &mut Vec<usize>, x: usize) -> usize {
|
||
return size[find(parent, x)];
|
||
}
|
||
|
||
for j in 0..cols {
|
||
if copy[0][j] == 1 {
|
||
union(&mut parent, &mut size, j, grid_len);
|
||
}
|
||
}
|
||
|
||
for i in 1..rows {
|
||
for j in 0..cols {
|
||
if copy[i][j] == 1 {
|
||
if copy[i - 1][j] == 1 {
|
||
union(&mut parent, &mut size, get_idx(i - 1, j, cols), get_idx(i, j, cols));
|
||
}
|
||
if j > 0 && copy[i][j - 1] == 1 {
|
||
union(&mut parent, &mut size, get_idx(i, j - 1, cols), get_idx(i, j, cols));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
let mut res = vec![0i32; hits.len()];
|
||
for i in (0..res.len()).rev() {
|
||
let x = hits[i][0] as usize;
|
||
let y = hits[i][1] as usize;
|
||
if grid[x][y] == 0 {
|
||
continue;
|
||
}
|
||
let origin = get_size(&mut parent, &mut size, grid_len);
|
||
|
||
if x == 0 {
|
||
union(&mut parent, &mut size, y, grid_len);
|
||
}
|
||
|
||
for direction in &DIRECTIONS {
|
||
let new_x = (x as i32 + direction[0]) as usize;
|
||
let new_y = (y as i32 + direction[1]) as usize;
|
||
if in_area(new_x, new_y, rows, cols) && copy[new_x][new_y] == 1 {
|
||
union(&mut parent, &mut size, get_idx(x, y, cols), get_idx(new_x, new_y, cols));
|
||
}
|
||
}
|
||
|
||
let current = get_size(&mut parent, &mut size, grid_len);
|
||
res[i] = if current < origin + 1 {
|
||
0
|
||
} else {
|
||
(current - origin - 1) as i32
|
||
};
|
||
copy[x][y] = 1;
|
||
}
|
||
res
|
||
}
|
||
|
||
/// 1232.缀点成线
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/check-if-it-is-a-straight-line/)
|
||
pub fn check_straight_line(mut coordinates: Vec<Vec<i32>>) -> bool {
|
||
if coordinates.len() <= 2 {
|
||
return true;
|
||
}
|
||
let mut delta_x = coordinates[0][0];
|
||
let mut delta_y = coordinates[0][1];
|
||
|
||
for i in 0..coordinates.len() {
|
||
coordinates[i][0] -= delta_x;
|
||
coordinates[i][1] -= delta_y;
|
||
}
|
||
let (a, b) = (coordinates[1][1], -coordinates[1][0]);
|
||
for i in 2..coordinates.len() {
|
||
let (x, y) = (coordinates[i][0], coordinates[i][1]);
|
||
if a * x + b * y != 0 {
|
||
return false;
|
||
}
|
||
}
|
||
true
|
||
}
|
||
|
||
/// 721.账户合并
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/accounts-merge/)
|
||
/// # 方法1 并查集
|
||
/// todo
|
||
pub fn accounts_merge(accounts: Vec<Vec<String>>) -> Vec<Vec<String>> {
|
||
fn find(parent: &mut Vec<usize>, index: usize) -> usize {
|
||
if parent[index] != index {
|
||
parent[index] = find(parent, parent[index]);
|
||
}
|
||
parent[index]
|
||
}
|
||
fn union(parent: &mut Vec<usize>, index1: usize, index2: usize) {
|
||
let idx1 = find(parent, index1);
|
||
let idx2 = find(parent, index2);
|
||
parent[idx2] = idx1;
|
||
}
|
||
use std::collections::HashMap;
|
||
let mut email_to_idx = HashMap::<String, usize>::new();
|
||
let mut email_to_name = HashMap::<String, String>::new();
|
||
let mut emails_count = 0usize;
|
||
for account in &accounts {
|
||
let name = &account[0];
|
||
for i in 1..account.len() {
|
||
let email = &account[i];
|
||
if !email_to_idx.contains_key(email) {
|
||
email_to_idx.insert(email.clone(), emails_count);
|
||
email_to_name.insert(email.clone(), name.clone());
|
||
emails_count += 1;
|
||
}
|
||
}
|
||
}
|
||
let mut parent = (0..emails_count).collect::<Vec<usize>>();
|
||
for account in &accounts {
|
||
let first_email = &account[1];
|
||
let first_idx = email_to_idx[first_email];
|
||
for i in 2..account.len() {
|
||
let next_email = &account[i];
|
||
let next_idx = email_to_idx[next_email];
|
||
union(&mut parent, first_idx, next_idx);
|
||
}
|
||
}
|
||
let mut idx_to_emails = HashMap::<usize, Vec<String>>::new();
|
||
for email in email_to_idx.keys() {
|
||
let idx = find(&mut parent, email_to_idx[email]);
|
||
if !idx_to_emails.contains_key(&idx) {
|
||
idx_to_emails.insert(idx, Vec::<String>::new());
|
||
}
|
||
idx_to_emails.get_mut(&idx).unwrap().push(email.clone());
|
||
}
|
||
let mut merged = Vec::<Vec<String>>::new();
|
||
for emails in idx_to_emails.values_mut() {
|
||
emails.sort();
|
||
let name = &email_to_name[&emails[0]];
|
||
let mut account = Vec::<String>::with_capacity(1usize + emails.len());
|
||
account.push(name.clone());
|
||
account.extend(emails.clone());
|
||
merged.push(account);
|
||
}
|
||
merged
|
||
}
|
||
|
||
/// 1584.连接所有点的最小费用
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/min-cost-to-connect-all-points/)
|
||
/// # 方法1 Kruskal算法
|
||
/// todo
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn min_cost_connect_points(points: Vec<Vec<i32>>) -> i32 {
|
||
/// let dist = |x: usize, y: usize| -> i32 { (points[x][0] - points[y][0]).abs() + (points[x][1] - points[y][1]).abs() };
|
||
/// let n = points.len();
|
||
/// let mut edges = Vec::<(i32, usize, usize)>::new();
|
||
/// for i in 0..n {
|
||
/// for j in (i + 1)..n {
|
||
/// edges.push((dist(i, j), i, j));
|
||
/// }
|
||
/// }
|
||
/// edges.sort_by(|a, b| a.0.cmp(&b.0));
|
||
/// let mut f = (0..n).collect::<Vec<usize>>();
|
||
/// let mut rank = vec![1usize; n];
|
||
/// fn find(f: &mut Vec<usize>, x: usize) -> usize {
|
||
/// if f[x] != x {
|
||
/// f[x] = find(f, f[x]);
|
||
/// }
|
||
/// f[x]
|
||
/// }
|
||
/// fn union_set(f: &mut Vec<usize>, rank: &mut Vec<usize>, x: usize, y: usize) -> bool {
|
||
/// let (mut fx, mut fy) = (find(f, x), find(f, y));
|
||
/// if fx == fy {
|
||
/// return false;
|
||
/// }
|
||
/// if rank[fx] < rank[fy] {
|
||
/// fx ^= fy;
|
||
/// fy ^= fx;
|
||
/// fx ^= fy;
|
||
/// }
|
||
/// rank[fx] += rank[fy];
|
||
/// f[fy] = fx;
|
||
/// return true;
|
||
/// }
|
||
/// let (mut ret, mut num) = (0, 1);
|
||
/// for &(len, x, y) in &edges {
|
||
/// if union_set(&mut f, &mut rank, x, y) {
|
||
/// ret += len;
|
||
/// num += 1;
|
||
/// if num == n {
|
||
/// break;
|
||
/// }
|
||
/// }
|
||
/// }
|
||
/// ret
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 建图优化Kruskal算法
|
||
/// 实现见源码
|
||
/// # 方法3 prim算法
|
||
/// todo
|
||
pub fn min_cost_connect_points(points: Vec<Vec<i32>>) -> i32 {
|
||
use std::collections::HashSet;
|
||
|
||
fn low_bit(k: usize) -> usize {
|
||
k & ((!k) + 1)
|
||
}
|
||
fn update(tree: &mut Vec<i32>, id_rec: &mut Vec<i32>, mut pos: usize, val: i32, id: usize) {
|
||
while pos > 0 {
|
||
if tree[pos] > val {
|
||
tree[pos] = val;
|
||
id_rec[pos] = id as i32;
|
||
}
|
||
pos -= low_bit(pos);
|
||
}
|
||
}
|
||
fn query(tree: &mut Vec<i32>, id_res: &mut Vec<i32>, mut pos: usize) -> i32 {
|
||
let mut min_val = i32::MAX;
|
||
let mut j = -1;
|
||
while pos < tree.len() {
|
||
if min_val > tree[pos] {
|
||
min_val = tree[pos];
|
||
j = id_res[pos];
|
||
}
|
||
pos += low_bit(pos);
|
||
}
|
||
j
|
||
}
|
||
fn build(pos: &mut Vec<(i32, i32, usize)>, edges: &mut Vec<(i32, usize, usize)>, n: usize) {
|
||
pos.sort_by(|a, b| if a.0 == b.0 { a.1.cmp(&b.1) } else { a.0.cmp(&b.0) });
|
||
let mut a = Vec::<i32>::with_capacity(n);
|
||
let mut set = HashSet::<i32>::new();
|
||
for i in 0..n {
|
||
a.push(pos[i].1 - pos[i].0);
|
||
set.insert(pos[i].1 - pos[i].0);
|
||
}
|
||
let mut b = set.into_iter().collect::<Vec<i32>>();
|
||
b.sort();
|
||
let num = b.len() + 1;
|
||
let mut tree = vec![i32::MAX; num];
|
||
let mut id_rec = vec![-1i32; num];
|
||
for i in (0..n).rev() {
|
||
let poss = b.binary_search(&a[i]).unwrap() + 1;
|
||
let j = query(&mut tree, &mut id_rec, poss);
|
||
if j != -1 {
|
||
let dis = (pos[i].0 - pos[j as usize].0).abs() + (pos[i].1 - pos[j as usize].1).abs();
|
||
edges.push((dis, pos[i].2, pos[j as usize].2));
|
||
}
|
||
update(&mut tree, &mut id_rec, poss, pos[i].0 + pos[i].1, i);
|
||
}
|
||
}
|
||
|
||
let mut pos = Vec::<(i32, i32, usize)>::with_capacity(points.len());
|
||
let mut edges = Vec::<(i32, usize, usize)>::new();
|
||
let n = points.len();
|
||
for i in 0..n {
|
||
pos.push((points[i][0], points[i][1], i));
|
||
}
|
||
build(&mut pos, &mut edges, n);
|
||
for i in 0..n {
|
||
pos[i].0 ^= pos[i].1;
|
||
pos[i].1 ^= pos[i].0;
|
||
pos[i].0 ^= pos[i].1;
|
||
//swap(&mut pos[i].0, &mut pos[i].1);
|
||
}
|
||
build(&mut pos, &mut edges, n);
|
||
for i in 0..n {
|
||
pos[i].0 = -pos[i].0;
|
||
}
|
||
build(&mut pos, &mut edges, n);
|
||
for i in 0..n {
|
||
pos[i].0 ^= pos[i].1;
|
||
pos[i].1 ^= pos[i].0;
|
||
pos[i].0 ^= pos[i].1;
|
||
}
|
||
build(&mut pos, &mut edges, n);
|
||
|
||
edges.sort_by(|a, b| a.0.cmp(&b.0));
|
||
let mut f = (0..n).collect::<Vec<usize>>();
|
||
let mut rank = vec![1usize; n];
|
||
fn find(f: &mut Vec<usize>, x: usize) -> usize {
|
||
if f[x] != x {
|
||
f[x] = find(f, f[x]);
|
||
}
|
||
f[x]
|
||
}
|
||
fn union_set(f: &mut Vec<usize>, rank: &mut Vec<usize>, x: usize, y: usize) -> bool {
|
||
let (mut fx, mut fy) = (find(f, x), find(f, y));
|
||
if fx == fy {
|
||
return false;
|
||
}
|
||
if rank[fx] < rank[fy] {
|
||
fx ^= fy;
|
||
fy ^= fx;
|
||
fx ^= fy;
|
||
}
|
||
rank[fx] += rank[fy];
|
||
f[fy] = fx;
|
||
return true;
|
||
}
|
||
let (mut ret, mut num) = (0i32, 1usize);
|
||
for &(len, x, y) in &edges {
|
||
if union_set(&mut f, &mut rank, x, y) {
|
||
ret += len;
|
||
num += 1usize;
|
||
if num == n {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
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/)
|
||
/// # 方法1 枚举+最小生成树判定
|
||
/// todo
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn find_critical_and_pseudo_critical_edges(n: i32, mut edges: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
|
||
/// fn find_set(parent: &mut Vec<usize>, x: usize) -> usize {
|
||
/// if parent[x] == x {
|
||
/// x
|
||
/// } else {
|
||
/// parent[x] = find_set(parent, parent[x]);
|
||
/// parent[x]
|
||
/// }
|
||
/// }
|
||
/// fn unite(parent:&mut Vec<usize>, size:&mut Vec<usize>, x:usize, y:usize, set_count: &mut usize) -> bool {
|
||
/// let mut x_root = find_set(parent, x);
|
||
/// let mut y_root = find_set(parent, y);
|
||
/// if x_root == y_root {
|
||
/// return false;
|
||
/// }
|
||
/// if size[x_root] < size[y_root] {
|
||
/// x_root ^= y_root;
|
||
/// y_root ^= x_root;
|
||
/// x_root ^= y_root;
|
||
/// }
|
||
/// parent[y_root] = x_root;
|
||
/// size[x_root] += size[y_root];
|
||
/// *set_count -= 1;
|
||
/// true
|
||
/// }
|
||
/// let m = edges.len();
|
||
/// for i in 0..m {
|
||
/// edges[i].push(i as i32);
|
||
/// }
|
||
/// edges.sort_by(|u, v| u[2].cmp(&v[2]));
|
||
/// let n = n as usize;
|
||
/// let mut parent = (0..n).collect::<Vec<usize>>();
|
||
/// let mut size = vec![1usize; n];
|
||
/// let mut set_count = n;
|
||
/// let mut value = 0;
|
||
/// for i in 0..m {
|
||
/// if unite(&mut parent, &mut size, edges[i][0] as usize, edges[i][1] as usize, &mut set_count) {
|
||
/// value += edges[i][2];
|
||
/// }
|
||
/// }
|
||
/// let mut ans = vec![Vec::<i32>::new(); 2];
|
||
/// for i in 0..m {
|
||
/// let mut parent0 = (0..n).collect::<Vec<usize>>();
|
||
/// let mut size0 = vec![1usize; n];
|
||
/// let mut set_count0 = n;
|
||
/// let mut value0 = 0;
|
||
/// for j in 0..m {
|
||
/// if i != j && unite(&mut parent0, &mut size0, edges[j][0] as usize, edges[j][1] as usize, &mut set_count0) {
|
||
/// value0 += edges[j][2];
|
||
/// }
|
||
/// }
|
||
/// if set_count0 != 1 || value0 > value {
|
||
/// ans[0].push(edges[i][3]);
|
||
/// continue;
|
||
/// }
|
||
/// let mut parent1 = (0..n).collect::<Vec<usize>>();
|
||
/// let mut size1 = vec![1usize; n];
|
||
/// let mut set_count1 = n;
|
||
/// unite(&mut parent1, &mut size1, edges[i][0] as usize, edges[i][1] as usize, &mut set_count1);
|
||
/// let mut value1 = edges[i][2];
|
||
/// for j in 0..m {
|
||
/// if i != j && unite(&mut parent1, &mut size1, edges[j][0] as usize, edges[j][1] as usize, &mut set_count1) {
|
||
/// value1 += edges[j][2];
|
||
/// }
|
||
/// }
|
||
/// if value1 == value {
|
||
/// ans[1].push(edges[i][3]);
|
||
/// }
|
||
/// }
|
||
/// ans
|
||
/// }
|
||
/// ```
|
||
pub fn find_critical_and_pseudo_critical_edges(n: i32, mut edges: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
|
||
fn find_set(parent: &mut Vec<usize>, x: usize) -> usize {
|
||
if parent[x] == x {
|
||
x
|
||
} else {
|
||
parent[x] = find_set(parent, parent[x]);
|
||
parent[x]
|
||
}
|
||
}
|
||
fn unite(parent: &mut Vec<usize>, size: &mut Vec<usize>, x: usize, y: usize, set_count: &mut usize) -> bool {
|
||
let mut x_root = find_set(parent, x);
|
||
let mut y_root = find_set(parent, y);
|
||
if x_root == y_root {
|
||
return false;
|
||
}
|
||
if size[x_root] < size[y_root] {
|
||
std::mem::swap(&mut x_root, &mut y_root);
|
||
}
|
||
parent[y_root] = x_root;
|
||
size[x_root] += size[y_root];
|
||
*set_count -= 1;
|
||
true
|
||
}
|
||
|
||
fn get_cutting_edge_(edges: &mut Vec<Vec<usize>>, edges_id: &mut Vec<Vec<usize>>, low: &mut Vec<usize>, dfn: &mut Vec<usize>, ans: &mut Vec<usize>, ts: &mut i32, u: usize, parent_edge_id: usize) {
|
||
*ts += 1;
|
||
dfn[u] = *ts as usize;
|
||
low[u] = *ts as usize;
|
||
for i in 0..edges[u].len() {
|
||
let v = edges[u][i];
|
||
let id = edges_id[u][i];
|
||
if dfn[v] == dfn.len() {
|
||
get_cutting_edge_(edges, edges_id, low, dfn, ans, ts, v, id);
|
||
low[u] = low[u].min(low[v]);
|
||
if low[v] > dfn[u] {
|
||
ans.push(id);
|
||
}
|
||
} else if id != parent_edge_id {
|
||
low[u] = low[u].min(dfn[v]);
|
||
}
|
||
}
|
||
}
|
||
|
||
fn get_cutting_edge(n: usize, mut edges: Vec<Vec<usize>>, mut edges_id: Vec<Vec<usize>>) -> Vec<usize> {
|
||
let mut low = vec![n; n];
|
||
let mut dfn = vec![n; n];
|
||
let mut ts = -1;
|
||
let mut ans = Vec::<usize>::new();
|
||
for i in 0..n {
|
||
if dfn[i] == n {
|
||
get_cutting_edge_(&mut edges, &mut edges_id, &mut low, &mut dfn, &mut ans, &mut ts, i, n);
|
||
}
|
||
}
|
||
ans
|
||
}
|
||
|
||
let m = edges.len();
|
||
for i in 0..m {
|
||
edges[i].push(i as i32);
|
||
}
|
||
edges.sort_by(|u, v| u[2].cmp(&v[2]));
|
||
let n = n as usize;
|
||
let mut parent = (0..n).collect::<Vec<usize>>();
|
||
let mut size = vec![1usize; n];
|
||
let mut set_count = n;
|
||
let mut ans = vec![Vec::<i32>::new(); 2];
|
||
let mut label = vec![0; m];
|
||
let mut i = 0;
|
||
while i < m {
|
||
//let w = edges[i][2];
|
||
let mut j = i;
|
||
while j < m && edges[j][2] == edges[i][2] {
|
||
j += 1;
|
||
}
|
||
let mut comp_to_id = std::collections::HashMap::<usize, usize>::new();
|
||
let mut gn = 0usize;
|
||
for k in i..j {
|
||
let x = find_set(&mut parent, edges[k][0] as usize);
|
||
let y = find_set(&mut parent, edges[k][1] as usize);
|
||
if x != y {
|
||
if !comp_to_id.contains_key(&x) {
|
||
comp_to_id.insert(x, gn);
|
||
gn += 1;
|
||
}
|
||
if !comp_to_id.contains_key(&y) {
|
||
comp_to_id.insert(y, gn);
|
||
gn += 1;
|
||
}
|
||
} else {
|
||
label[edges[k][3] as usize] = -1;
|
||
}
|
||
}
|
||
let mut gm = vec![Vec::<usize>::new(); gn];
|
||
let mut gm_id = vec![Vec::<usize>::new(); gn];
|
||
for k in i..j {
|
||
let x = find_set(&mut parent, edges[k][0] as usize);
|
||
let y = find_set(&mut parent, edges[k][1] as usize);
|
||
if x != y {
|
||
let idx = comp_to_id[&x];
|
||
let idy = comp_to_id[&y];
|
||
gm[idx].push(idy);
|
||
gm_id[idx].push(edges[k][3] as usize);
|
||
gm[idy].push(idx);
|
||
gm_id[idy].push(edges[k][3] as usize);
|
||
}
|
||
}
|
||
let bridges = get_cutting_edge(gn, gm, gm_id);
|
||
|
||
for id in bridges {
|
||
ans[0].push(id as i32);
|
||
label[id] = 1;
|
||
}
|
||
for k in i..j {
|
||
unite(&mut parent, &mut size, edges[k][0] as usize, edges[k][1] as usize, &mut set_count);
|
||
}
|
||
i = j;
|
||
}
|
||
for i in 0..m {
|
||
if label[i] == 0 {
|
||
ans[1].push(i as i32);
|
||
}
|
||
}
|
||
ans
|
||
}
|
||
|
||
/// 989.数组形式的整数加法
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/add-to-array-form-of-integer/)
|
||
pub fn add_to_array_form(mut a: Vec<i32>, mut k: i32) -> Vec<i32> {
|
||
let mut carry = 0;
|
||
for n in a.iter_mut().rev() {
|
||
*n = *n + k % 10 + carry;
|
||
carry = *n / 10;
|
||
k /= 10;
|
||
*n %= 10;
|
||
}
|
||
while k != 0 || carry != 0 {
|
||
carry = k % 10 + carry;
|
||
a.insert(0, carry % 10);
|
||
k /= 10;
|
||
carry /= 10;
|
||
}
|
||
a
|
||
}
|
||
|
||
/// 1319.连通网络的操作次数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/number-of-operations-to-make-network-connected/)
|
||
pub fn make_connected(n: i32, connections: Vec<Vec<i32>>) -> i32 {
|
||
if connections.len() + 1 < n as usize {
|
||
return -1;
|
||
}
|
||
let n = n as usize;
|
||
let mut parent = (0..n).collect::<Vec<usize>>();
|
||
let mut size = vec![1usize; n];
|
||
let mut set_count = n;
|
||
fn find_set(parent: &mut Vec<usize>, x: usize) -> usize {
|
||
if parent[x] == x {
|
||
x
|
||
} else {
|
||
parent[x] = find_set(parent, parent[x]);
|
||
parent[x]
|
||
}
|
||
}
|
||
fn unite(parent: &mut Vec<usize>, size: &mut Vec<usize>, x: usize, y: usize, set_count: &mut usize) -> bool {
|
||
let mut x_root = find_set(parent, x);
|
||
let mut y_root = find_set(parent, y);
|
||
if x_root == y_root {
|
||
return false;
|
||
}
|
||
if size[x_root] < size[y_root] {
|
||
x_root ^= y_root;
|
||
y_root ^= x_root;
|
||
x_root ^= y_root;
|
||
}
|
||
parent[y_root] = x_root;
|
||
size[x_root] += size[y_root];
|
||
*set_count -= 1;
|
||
true
|
||
}
|
||
for c in connections {
|
||
unite(&mut parent, &mut size, c[0] as usize, c[1] as usize, &mut set_count);
|
||
}
|
||
set_count as i32 - 1
|
||
}
|
||
|
||
/// 674.最长连续递增序列
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence/)
|
||
pub fn find_length_of_lcis(nums: Vec<i32>) -> i32 {
|
||
let mut ans = 0;
|
||
let mut start = 0;
|
||
for i in 0..nums.len() {
|
||
if i > 0 && nums[i] <= nums[i - 1] {
|
||
start = i;
|
||
}
|
||
ans = ans.max(i - start + 1);
|
||
}
|
||
ans as i32
|
||
}
|
||
|
||
/// 959.由斜杠划分区域
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/regions-cut-by-slashes/)
|
||
pub fn regions_by_slashes(grid: Vec<String>) -> i32 {
|
||
fn find(parent: &mut Vec<usize>, x: usize) -> usize {
|
||
if parent[x] == x {
|
||
x
|
||
} else {
|
||
parent[x] = find(parent, parent[x]);
|
||
parent[x]
|
||
}
|
||
}
|
||
fn union(parent: &mut Vec<usize>, x: usize, y: usize) {
|
||
let x_root = find(parent, x);
|
||
let y_root = find(parent, y);
|
||
parent[x_root] = y_root;
|
||
}
|
||
let n = grid.len();
|
||
let mut parent = (0..(n * n * 4)).collect::<Vec<usize>>();
|
||
for (i, s) in grid.into_iter().enumerate() {
|
||
let s = s.into_bytes();
|
||
for j in 0..n {
|
||
let idx = i * n + j;
|
||
if i < n - 1 {
|
||
let bottom = idx + n;
|
||
union(&mut parent, idx * 4 + 2, bottom * 4);
|
||
}
|
||
if j < n - 1 {
|
||
let right = idx + 1;
|
||
union(&mut parent, idx * 4 + 1, right * 4 + 3);
|
||
}
|
||
if s[j] == b'/' {
|
||
union(&mut parent, idx * 4, idx * 4 + 3);
|
||
union(&mut parent, idx * 4 + 1, idx * 4 + 2);
|
||
} else if s[j] == b'\\' {
|
||
union(&mut parent, idx * 4, idx * 4 + 1);
|
||
union(&mut parent, idx * 4 + 2, idx * 4 + 3);
|
||
} else {
|
||
union(&mut parent, idx * 4, idx * 4 + 1);
|
||
union(&mut parent, idx * 4 + 1, idx * 4 + 2);
|
||
union(&mut parent, idx * 4 + 2, idx * 4 + 3);
|
||
}
|
||
}
|
||
}
|
||
let mut fathers = std::collections::HashSet::<usize>::new();
|
||
for i in 0..(n * n * 4) {
|
||
let fa = find(&mut parent, i);
|
||
fathers.insert(fa);
|
||
}
|
||
fathers.len() as i32
|
||
}
|
||
|
||
/// 1128.等价多米诺骨牌对的数量
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/number-of-equivalent-domino-pairs/)
|
||
pub fn num_equiv_domino_pairs(dominoes: Vec<Vec<i32>>) -> i32 {
|
||
let mut m = std::collections::HashMap::<i32, i32>::new();
|
||
let mut ret = 0;
|
||
for d in dominoes {
|
||
let key = if d[0] < d[1] {
|
||
d[0] * 10 + d[1]
|
||
} else {
|
||
d[1] * 10 + d[0]
|
||
};
|
||
ret += m.get(&key).unwrap_or(&0);
|
||
*m.entry(key).or_default() += 1;
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 206.反转链表
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/reverse-linked-list/)
|
||
pub fn reverse_list(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 101.对称二叉树
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/symmetric-tree/)
|
||
/// # 方法1 递归
|
||
/// # 方法2 队列迭代
|
||
/// todo
|
||
pub fn is_symmetric(root: Option<Rc<RefCell<TreeNode>>>) -> bool {
|
||
fn symmetric(t1: &Option<Rc<RefCell<TreeNode>>>, t2: &Option<Rc<RefCell<TreeNode>>>) -> bool {
|
||
return match (t1, t2) {
|
||
(None, None) => true,
|
||
(Some(n1), Some(n2)) => {
|
||
n1.borrow().val == n2.borrow().val
|
||
&& symmetric(&n1.borrow().left, &n2.borrow().right)
|
||
&& symmetric(&n1.borrow().right, &n2.borrow().left)
|
||
}
|
||
_ => false
|
||
}
|
||
}
|
||
symmetric(&root, &root)
|
||
}
|
||
|
||
/// 112.路径总和
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/path-sum/)
|
||
pub fn has_path_sum(root: Option<Rc<RefCell<TreeNode>>>, target_sum: i32) -> bool {
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 21.合并两个有序链表
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/merge-two-sorted-lists/)
|
||
pub fn merge_two_lists(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
|
||
unimplemented!();
|
||
}
|
||
|
||
/// 543.二叉树的直径
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/diameter-of-binary-tree/)
|
||
pub fn diameter_of_binary_tree(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
|
||
unimplemented!();
|
||
}
|
||
|
||
/// 234.回文链表
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/palindrome-linked-list/)
|
||
pub fn is_palindrome2(head: Option<Box<ListNode>>) -> bool {
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 144.二叉树的前序遍历
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/binary-tree-preorder-traversal/)
|
||
/// # 方法1 递归
|
||
/// # 方法2 栈
|
||
/// # 方法3 Morris遍历
|
||
/// todo
|
||
pub fn preorder_traversal(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
|
||
/*fn preorder(ret:&mut Vec<i32>, root: & Option<Rc<RefCell<TreeNode>>>) {
|
||
match root {
|
||
Some(r) => {
|
||
ret.push(r.borrow().val);
|
||
preorder(ret, &r.borrow().left);
|
||
preorder(ret, &r.borrow().right);
|
||
}
|
||
None => {}
|
||
}
|
||
}
|
||
let mut ret = Vec::<i32>::new();
|
||
preorder(&mut ret, &root);
|
||
ret*/
|
||
let mut stack = vec![root];
|
||
let mut ret = vec![];
|
||
while let Some(n) = stack.pop() {
|
||
if let Some(n) = n {
|
||
ret.push(n.borrow().val);
|
||
stack.push(n.borrow_mut().right.take());
|
||
stack.push(n.borrow_mut().left.take());
|
||
}
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 94.二叉树的中序遍历
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/binary-tree-inorder-traversal/)
|
||
/// # 方法1 递归
|
||
/// # 方法2 栈
|
||
/// # 方法3 Morris遍历
|
||
/// todo
|
||
pub fn inorder_traversal(mut root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
|
||
fn inorder(ret:&mut Vec<i32>, root: & Option<Rc<RefCell<TreeNode>>>) {
|
||
if let Some(r) = root {
|
||
inorder(ret, &r.borrow().left);
|
||
ret.push(r.borrow().val);
|
||
inorder(ret, &r.borrow().right);
|
||
}
|
||
}
|
||
let mut ret = Vec::<i32>::new();
|
||
inorder(&mut ret, &root);
|
||
ret
|
||
/*let mut ret = vec![];
|
||
let mut stack = vec![];
|
||
while root.is_some() || !stack.is_empty() {
|
||
while let Some(r) = root {
|
||
stack.push(r.clone());
|
||
root = r.borrow().left.clone();
|
||
}
|
||
root = stack.pop();
|
||
if let Some(n) = root {
|
||
ret.push(n.borrow().val);
|
||
root = n.borrow().right.clone();
|
||
}
|
||
}
|
||
ret*/
|
||
/*let ret = vec![];
|
||
let mut predecessor;
|
||
while root.is_some() {
|
||
if root.unwrap().borrow().left.is_some() {
|
||
predecessor = root.unwrap().borrow().left.unwrap().clone();
|
||
while predecessor.borrow().right.is_some() {
|
||
|
||
}
|
||
}
|
||
}*/
|
||
//unimplemented!()
|
||
}
|
||
|
||
/// 145.二叉树的后序遍历
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/binary-tree-postorder-traversal/)
|
||
/// # 方法1 递归
|
||
/// # 方法2 栈
|
||
/// # 方法3 Morris遍历
|
||
/// todo
|
||
pub fn postorder_traversal(mut root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
|
||
/*fn postorder(ret:&mut Vec<i32>, root: & Option<Rc<RefCell<TreeNode>>>) {
|
||
match root {
|
||
Some(r) => {
|
||
postorder(ret, &r.borrow().left);
|
||
postorder(ret, &r.borrow().right);
|
||
ret.push(r.borrow().val);
|
||
}
|
||
None => {}
|
||
}
|
||
}
|
||
let mut ret = Vec::<i32>::new();
|
||
postorder(&mut ret, &root);
|
||
ret*/
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 102.二叉树的层序遍历
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/binary-tree-level-order-traversal/)
|
||
/// # 方法1
|
||
pub fn level_order(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<Vec<i32>> {
|
||
let mut ret = vec![];
|
||
if root.is_none() {
|
||
return ret;
|
||
}
|
||
let mut q = vec![root.unwrap()];
|
||
while !q.is_empty() {
|
||
let mut level = vec![];
|
||
let n = q.len();
|
||
for _ in 0..n {
|
||
let node = q.remove(0);
|
||
level.push(node.borrow().val);
|
||
if node.borrow().left.is_some() {
|
||
q.push(node.borrow_mut().left.take().unwrap());
|
||
}
|
||
if node.borrow().right.is_some() {
|
||
q.push(node.borrow_mut().right.take().unwrap());
|
||
}
|
||
}
|
||
ret.push(level);
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 1579.保证图可完全遍历
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/)
|
||
/// # 并查集
|
||
pub fn max_num_edges_to_remove(n: i32, mut edges: Vec<Vec<i32>>) -> i32 {
|
||
fn find_set(parent: &mut Vec<usize>, x: usize) -> usize {
|
||
if parent[x] == x {
|
||
x
|
||
} else {
|
||
parent[x] = find_set(parent, parent[x]);
|
||
parent[x]
|
||
}
|
||
}
|
||
fn unite(parent: &mut Vec<usize>, size: &mut Vec<usize>, x: usize, y: usize, set_count: &mut usize) -> bool {
|
||
let mut x_root = find_set(parent, x);
|
||
let mut y_root = find_set(parent, y);
|
||
if x_root == y_root {
|
||
return false;
|
||
}
|
||
if size[x_root] < size[y_root] {
|
||
x_root ^= y_root;
|
||
y_root ^= x_root;
|
||
x_root ^= y_root;
|
||
}
|
||
parent[y_root] = x_root;
|
||
size[x_root] += size[y_root];
|
||
*set_count -= 1;
|
||
true
|
||
}
|
||
let n = n as usize;
|
||
let mut parent1 = (0..n).collect::<Vec<usize>>();
|
||
let mut parent2 = (0..n).collect::<Vec<usize>>();
|
||
let mut size1 = vec![1usize; n];
|
||
let mut size2 = vec![1usize; n];
|
||
let mut set_count1 = n;
|
||
let mut set_count2 = n;
|
||
let mut ans = 0;
|
||
for edge in edges.iter_mut() {
|
||
edge[1] -= 1;
|
||
edge[2] -= 1;
|
||
}
|
||
for edge in &edges {
|
||
if edge[0] == 3 {
|
||
if !unite(&mut parent1, &mut size1, edge[1] as usize, edge[2] as usize, &mut set_count1) {
|
||
ans += 1;
|
||
} else {
|
||
unite(&mut parent2, &mut size2, edge[1] as usize, edge[2] as usize, &mut set_count2);
|
||
}
|
||
}
|
||
}
|
||
for edge in &edges {
|
||
if edge[0] == 1 {
|
||
if !unite(&mut parent1, &mut size1, edge[1] as usize, edge[2] as usize, &mut set_count1) {
|
||
ans += 1;
|
||
}
|
||
} else if edge[0] == 2 {
|
||
if !unite(&mut parent2, &mut size2, edge[1] as usize, edge[2] as usize, &mut set_count2) {
|
||
ans += 1;
|
||
}
|
||
}
|
||
}
|
||
if set_count1 != 1 || set_count2 != 1 {
|
||
return -1;
|
||
}
|
||
ans
|
||
}
|
||
|
||
/// 106.从中序与后序遍历序列构造二叉树
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/)
|
||
pub fn build_tree2(inorder: Vec<i32>, postorder: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> {
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 105.从前序与中序遍历序列构造二叉树
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
|
||
pub fn build_tree1(preorder: Vec<i32>, inorder: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> {
|
||
unimplemented!()
|
||
}
|
||
/// 236.二叉树的最近公共祖先
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/)
|
||
pub fn lowest_common_ancestor(root: Option<Rc<RefCell<TreeNode>>>, p: Option<Rc<RefCell<TreeNode>>>, q: Option<Rc<RefCell<TreeNode>>>) -> Option<Rc<RefCell<TreeNode>>> {
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 724.寻找数组的中心索引
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/find-pivot-index/)
|
||
pub fn pivot_index(nums: Vec<i32>) -> i32 {
|
||
let mut sum_right = nums.iter().sum::<i32>();
|
||
let mut sum_left = 0;
|
||
for i in 0..nums.len() {
|
||
sum_right -= nums[i];
|
||
if sum_left == sum_right {
|
||
return i as i32;
|
||
}
|
||
sum_left += nums[i];
|
||
}
|
||
-1
|
||
}
|
||
|
||
/// 56.合并区间
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/merge-intervals/)
|
||
pub fn merge1(mut intervals: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
|
||
/*let mut ans = Vec::<Vec<i32>>::new();
|
||
if intervals.is_empty() {
|
||
return ans;
|
||
}
|
||
intervals.sort_by(|a, b| a[0].cmp(&b[0]));
|
||
let mut item = intervals.get(0).unwrap().clone();
|
||
for t in intervals {
|
||
if item[1] < t[0] {
|
||
ans.push(item);
|
||
} else {
|
||
item[1] =
|
||
}
|
||
}*/
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 面试题 01.08.零矩阵
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/zero-matrix-lcci/)
|
||
pub fn set_zeroes(matrix: &mut Vec<Vec<i32>>) {
|
||
let n = matrix.len();
|
||
let m = matrix[0].len();
|
||
let mut row_lookup = vec![false; n];
|
||
let mut col_lookup = vec![false; m];
|
||
for i in 0..n {
|
||
for j in 0..m {
|
||
if matrix[i][j] == 0 {
|
||
row_lookup[i] = true;
|
||
col_lookup[j] = true;
|
||
}
|
||
}
|
||
}
|
||
for i in 0..n {
|
||
if row_lookup[i] {
|
||
for j in 0..m {
|
||
matrix[i][j] = 0;
|
||
}
|
||
}
|
||
}
|
||
for j in 0..m {
|
||
if col_lookup[j] {
|
||
for i in 0..n {
|
||
matrix[i][j] = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 498.对角线遍历
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/diagonal-traverse/)
|
||
/// # 方法1 模拟
|
||
/// # 方法2 计算坐标
|
||
/// todo
|
||
pub fn find_diagonal_order(matrix: Vec<Vec<i32>>) -> Vec<i32> {
|
||
/*if matrix.is_empty() {
|
||
return vec![];
|
||
}
|
||
let s = matrix.len() * matrix[0].len();
|
||
// 1 2 3 ... min(m, n) ... 3 2 1
|
||
// max(m, n) - min(m, n) + 1
|
||
let mut ret = Vec::<i32>::with_capacity(s);
|
||
let (mut i, mut j) = (0usize, 0usize);
|
||
while i * j < s {
|
||
ret.push(matrix[i][j]);
|
||
}*/
|
||
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 151.翻转字符串里的单词
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/reverse-words-in-a-string/)
|
||
pub fn reverse_words(mut s: String) -> String {
|
||
/*s.trim();
|
||
s.split(' ');*/
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 1631.最小体力消耗路径
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/path-with-minimum-effort/)
|
||
/// # 方法1 Dijkstra 算法
|
||
/// # 方法2 并查集
|
||
///
|
||
pub fn minimum_effort_path(heights: Vec<Vec<i32>>) -> i32 {
|
||
struct UnionFind {
|
||
parent: Vec<usize>,
|
||
size: Vec<usize>,
|
||
n: usize,
|
||
set_count: usize,
|
||
}
|
||
impl UnionFind {
|
||
fn new(n: usize) -> UnionFind {
|
||
UnionFind {
|
||
parent: (0..n).collect::<Vec<usize>>(),
|
||
size: vec![1; n],
|
||
n,
|
||
set_count: n,
|
||
}
|
||
}
|
||
fn find_set(&mut self, x: usize) -> usize {
|
||
if self.parent[x] == x {
|
||
x
|
||
} else {
|
||
self.parent[x] = self.find_set(self.parent[x]);
|
||
self.parent[x]
|
||
}
|
||
}
|
||
fn unite(&mut self, x: usize, y: usize) -> bool {
|
||
let mut root_x = self.find_set(x);
|
||
let mut root_y = self.find_set(y);
|
||
if root_x == root_y {
|
||
return false;
|
||
}
|
||
if self.size[root_x] < self.size[root_y] {
|
||
std::mem::swap(&mut root_x, &mut root_y);
|
||
}
|
||
self.parent[root_y] = root_x;
|
||
self.size[root_x] += self.size[root_y];
|
||
self.set_count -= 1;
|
||
true
|
||
}
|
||
fn connected(&mut self, x: usize, y: usize) -> bool {
|
||
let root_x = self.find_set(x);
|
||
let root_y = self.find_set(y);
|
||
root_x == root_y
|
||
}
|
||
}
|
||
let (m, n) = (heights.len(), heights[0].len());
|
||
let mut edges = Vec::<(usize, usize, i32)>::new();
|
||
for i in 0..m {
|
||
for j in 0..n {
|
||
let id = i * n + j;
|
||
if i > 0 {
|
||
edges.push((id - n, id, (heights[i][j] - heights[i - 1][j]).abs()));
|
||
}
|
||
if j > 0 {
|
||
edges.push((id - 1, id, (heights[i][j] - heights[i][j - 1]).abs()));
|
||
}
|
||
}
|
||
}
|
||
edges.sort_unstable_by_key(|x| x.2);
|
||
let mut uf = UnionFind::new(m * n);
|
||
let mut ans = 0;
|
||
for (x, y, v) in edges {
|
||
uf.unite(x, y);
|
||
if uf.connected(0, m * n - 1) {
|
||
ans = v;
|
||
break;
|
||
}
|
||
}
|
||
ans
|
||
//unimplemented!();
|
||
}
|
||
/*pub fn minimum_effort_path(heights: Vec<Vec<i32>>) -> i32 {
|
||
const DIRS: [(i32, i32); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
|
||
#[derive(PartialEq, Eq)]
|
||
struct Item(usize, usize, i32);
|
||
impl PartialOrd for Item {
|
||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||
other.2.partial_cmp(&self.2)
|
||
}
|
||
}
|
||
impl Ord for Item {
|
||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||
other.2.cmp(&self.2)
|
||
}
|
||
}
|
||
let (m, n) = (heights.len(), heights[0].len());
|
||
let mut queue = std::collections::binary_heap::BinaryHeap::<Item>::new();
|
||
queue.push(Item(0, 0, 0));
|
||
let mut dist = vec![i32::MAX; m * n];
|
||
dist[0] = 0;
|
||
let mut visited = vec![false; m * n];
|
||
while !queue.is_empty() {
|
||
let Item(x, y, d) = queue.pop().unwrap();
|
||
let id = x * n + y;
|
||
if visited[id] { continue; }
|
||
if x == m - 1 && y == n - 1 { break; }
|
||
visited[id] = true;
|
||
for (dx, dy) in DIRS.iter() {
|
||
let (nx, ny) = ((x as i32 + dx) as usize, (y as i32 + dy) as usize);
|
||
if nx < m && ny < n && d.max((heights[x][y] - heights[nx][ny]).abs()) < dist[nx * n + ny] {
|
||
dist[nx * n + ny] = d.max((heights[x][y] - heights[nx][ny]).abs());
|
||
queue.push(Item(nx, ny, dist[nx * n + ny]));
|
||
}
|
||
}
|
||
}
|
||
dist[m * n - 1]
|
||
}*/
|
||
|
||
/// 778.水位上升的泳池中游泳
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/swim-in-rising-water/)
|
||
/// # 方法1 二分查找
|
||
/// # 方法2 并查集
|
||
/// # 方法3 Dijkstra 算法
|
||
/// todo
|
||
pub fn swim_in_water(grid: Vec<Vec<i32>>) -> i32 {
|
||
const DIRS: [(i32, i32); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
|
||
#[derive(PartialEq, Eq)]
|
||
struct Item(usize, usize, i32);
|
||
impl PartialOrd for Item {
|
||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||
other.2.partial_cmp(&self.2)
|
||
}
|
||
}
|
||
impl Ord for Item {
|
||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||
other.2.cmp(&self.2)
|
||
}
|
||
}
|
||
let n = grid.len();
|
||
let mut queue = std::collections::binary_heap::BinaryHeap::<Item>::new();
|
||
queue.push(Item(0, 0, grid[0][0]));
|
||
let mut dist = vec![vec![(n * n) as i32; n]; n];
|
||
dist[0][0] = grid[0][0];
|
||
let mut visited = vec![vec![false; n]; n];
|
||
while !queue.is_empty() {
|
||
let Item(x, y, _) = queue.pop().unwrap();
|
||
if visited[x][y] { continue; }
|
||
if x == n - 1 && y == n - 1 { return dist[n - 1][n - 1]; }
|
||
visited[x][y] = true;
|
||
for (dx, dy) in DIRS.iter() {
|
||
let (nx, ny) = ((x as i32 + dx) as usize, (y as i32 + dy) as usize);
|
||
if nx < n && ny < n && !visited[nx][ny] && grid[nx][ny].max(dist[x][y]) < dist[nx][ny] {
|
||
dist[nx][ny] = grid[nx][ny].max(dist[x][y]);
|
||
queue.push(Item(nx, ny, grid[nx][ny]));
|
||
}
|
||
}
|
||
}
|
||
-1
|
||
}
|
||
|
||
/// 839.相似字符串组
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/similar-string-groups/)
|
||
/// # 方法1 并查集
|
||
pub fn num_similar_groups(strs: Vec<String>) -> i32 {
|
||
fn find(parent: &mut Vec<usize>, x: usize) -> usize {
|
||
if parent[x] == x {
|
||
x
|
||
} else {
|
||
parent[x] = find(parent, parent[x]);
|
||
parent[x]
|
||
}
|
||
}
|
||
fn check(a: &Vec<u8>, b: &Vec<u8>, len: usize) -> bool {
|
||
let mut num = 0;
|
||
for i in 0..len {
|
||
if a[i] != b[i] {
|
||
num += 1;
|
||
if num > 2 { return false; }
|
||
}
|
||
}
|
||
true
|
||
}
|
||
let (n, m) = (strs.len(), strs[0].len());
|
||
let mut parent = (0..n).collect::<Vec<usize>>();
|
||
let bytes_arr = strs.into_iter().map(|s| s.into_bytes()).collect::<Vec<Vec<u8>>>();
|
||
for i in 0..n {
|
||
for j in i + 1..n {
|
||
let (fi, fj) = (find(&mut parent, i), find(&mut parent, j));
|
||
if fi == fj { continue; }
|
||
if check(&bytes_arr[i], &bytes_arr[j], m) {
|
||
parent[fi] = fj;
|
||
}
|
||
}
|
||
}
|
||
parent.into_iter().enumerate().filter(|(i, n)| *i == *n).count() as i32
|
||
}
|
||
|
||
/// 888.公平的糖果棒交换
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/fair-candy-swap/)
|
||
pub fn fair_candy_swap(a: Vec<i32>, b: Vec<i32>) -> Vec<i32> {
|
||
use std::iter::FromIterator;
|
||
let delta = (a.iter().sum::<i32>() - b.iter().sum::<i32>()) / 2;
|
||
let set = std::collections::HashSet::<i32>::from_iter(a.into_iter());
|
||
let mut ans = vec![];
|
||
for y in b {
|
||
let x = y + delta;
|
||
if set.contains(&x) {
|
||
ans = vec![x, y];
|
||
break;
|
||
}
|
||
}
|
||
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
|
||
}
|
||
|
||
/// 61.旋转链表
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/rotate-list/)
|
||
pub fn rotate_right(mut head: Option<Box<ListNode>>, k: i32) -> Option<Box<ListNode>> {
|
||
if head.is_none() || head.as_ref().unwrap().next.is_none() { return head; }
|
||
unimplemented!()
|
||
}
|
||
|
||
/// 480.滑动窗口中位数
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/sliding-window-median/)
|
||
pub fn median_sliding_window(nums: Vec<i32>, k: i32) -> Vec<f64> {
|
||
use std::cmp::Reverse;
|
||
use std::collections::binary_heap::BinaryHeap;
|
||
use std::collections::HashMap;
|
||
struct DualHeap {
|
||
small: BinaryHeap<i32>,
|
||
large: BinaryHeap<Reverse<i32>>,
|
||
delayed: HashMap<i32, usize>,
|
||
k: usize,
|
||
small_size: usize,
|
||
large_size: usize,
|
||
}
|
||
|
||
impl DualHeap {
|
||
fn new(k: usize) -> DualHeap {
|
||
DualHeap {
|
||
small: BinaryHeap::<i32>::new(),
|
||
large: BinaryHeap::<Reverse<i32>>::new(),
|
||
delayed: HashMap::<i32, usize>::new(),
|
||
k,
|
||
small_size: 0,
|
||
large_size: 0,
|
||
}
|
||
}
|
||
fn prune(&mut self, heap: &mut BinaryHeap<i32>) {
|
||
unimplemented!()
|
||
}
|
||
fn make_balance(&mut self) {
|
||
unimplemented!()
|
||
}
|
||
fn insert(&mut self, num: i32) {
|
||
unimplemented!()
|
||
}
|
||
fn erase(&mut self, num: i32) {
|
||
unimplemented!()
|
||
}
|
||
fn get_median(&mut self) -> f64 {
|
||
unimplemented!()
|
||
}
|
||
}
|
||
let k = k as usize;
|
||
if k > nums.len() {
|
||
return vec![];
|
||
}
|
||
|
||
let mut dh = DualHeap::new(k);
|
||
for i in 0..k {
|
||
dh.insert(nums[i]);
|
||
}
|
||
let mut ret = vec![dh.get_median()];
|
||
for i in k..nums.len() {
|
||
dh.insert(nums[i]);
|
||
dh.erase(nums[i - k]);
|
||
ret.push(dh.get_median());
|
||
}
|
||
ret
|
||
}
|
||
|
||
/// 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
|
||
}
|
||
|
||
/// 1004.最大连续1的个数 III
|
||
///
|
||
/// [原题链接](https://leetcode-cn.com/problems/max-consecutive-ones-iii/)
|
||
pub fn longest_ones(a: Vec<i32>, k: i32) -> i32 {
|
||
/*let mut num = vec![0; 2];
|
||
let n = a.len();
|
||
let (mut max_n, mut left, mut right, k) = (0usize, 0usize, 0usize, k as usize);
|
||
while right < n {
|
||
num[(a[right]) as usize] += 1;
|
||
max_n = max_n.max(num[(a[right]) as usize]);
|
||
if right - left + 1 - max_n > k {
|
||
num[(a[left]) as usize] -= 1;
|
||
left += 1;
|
||
}
|
||
right += 1;
|
||
}
|
||
(right - left) as i32*/
|
||
unimplemented!()
|
||
}
|
||
}
|
||
|
||
// 单元测试
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
/*#[test]
|
||
fn test_sqrt() {
|
||
use std::time::Instant;
|
||
|
||
let t1 = Instant::now();
|
||
let n = 2147395599;
|
||
let t = 10000000;
|
||
for i in 0..t {
|
||
let z = 1.0 / (n as f64).sqrt();
|
||
}
|
||
println!("{}", t1.elapsed().as_millis());
|
||
let t2 = Instant::now();
|
||
for i in 0..t {
|
||
Solution::my_sqrt(n);
|
||
}
|
||
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]];
|
||
let i = Solution::minimum_effort_path(h);
|
||
//println!("{}", i);
|
||
assert_eq!(i, 2);
|
||
}
|
||
|
||
#[test]
|
||
fn test_add_to_array_form() {
|
||
let a = vec![1];
|
||
let k = 9999;
|
||
let b = Solution::add_to_array_form(a, k);
|
||
//println!("{:?}", b);
|
||
assert_eq!(b, vec![1, 0, 0, 0, 0]);
|
||
}
|
||
|
||
#[test]
|
||
fn test_find_critical_and_pseudo_critical_edges() {
|
||
let n = 5;
|
||
let edges = vec![vec![0, 1, 1], vec![1, 2, 1], vec![2, 3, 2], vec![0, 3, 2], vec![0, 4, 3], vec![3, 4, 3], vec![1, 4, 6]];
|
||
let ret = Solution::find_critical_and_pseudo_critical_edges(n, edges);
|
||
//println!("{:?}", ret);
|
||
assert_eq!(ret, vec![vec![1, 0], vec![2, 3, 4, 5]]);
|
||
}
|
||
|
||
#[test]
|
||
fn test_min_cost_connect_points() {
|
||
let points = vec![vec![0, 0], vec![2, 2], vec![3, 10], vec![5, 2], vec![7, 0]];
|
||
let ret = Solution::min_cost_connect_points(points);
|
||
//println!("{}", ret);
|
||
assert_eq!(ret, 20);
|
||
}
|
||
|
||
#[test]
|
||
fn test_hit_bricks() {
|
||
let grid = vec![vec![1, 0, 0, 0], vec![1, 1, 1, 0]];
|
||
let hits = vec![vec![1, 0]];
|
||
let vec1 = Solution::hit_bricks(grid, hits);
|
||
//println!("{:?}", vec1);
|
||
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_fib() {
|
||
let n = 14;
|
||
let an = Solution::fib(n);
|
||
//println!("{}", an);
|
||
assert_eq!(an, 377);
|
||
}
|
||
|
||
#[test]
|
||
fn test_large_group_positions() {
|
||
let s = "abcdddeeeeaabbbcd".to_string();
|
||
let vec = Solution::large_group_positions(s);
|
||
//println!("{:?}", vec);
|
||
assert_eq!(vec, vec![vec![3, 5], vec![6, 9], vec![12, 14]]);
|
||
}
|
||
|
||
#[test]
|
||
fn test_find_numbers() {
|
||
let i = vec![12, 345, 2, 6, 7896];
|
||
let n = Solution::find_numbers(i);
|
||
//println!("{}", n);
|
||
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_rotate() {
|
||
let mut nums = vec![1, 2, 3, 4, 5, 6, 7];
|
||
let k = 3;
|
||
Solution::rotate(&mut nums, k);
|
||
//println!("{:?}", nums);
|
||
assert_eq!(nums, vec![5, 6, 7, 1, 2, 3, 4]);
|
||
}
|
||
|
||
#[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_title_to_number() {
|
||
let t = "AA".to_string();
|
||
let number = Solution::title_to_number(t);
|
||
//println!("{}", number);
|
||
assert_eq!(number, 27i32);
|
||
}
|
||
|
||
#[test]
|
||
fn test_find_redundant_connection() {
|
||
let edges = vec![vec![1, 2], vec![2, 3], vec![3, 4], vec![1, 4], vec![1, 5]];
|
||
let redundant_connection = Solution::find_redundant_connection(edges);
|
||
//println!("{:?}", redundant_connection);
|
||
assert_eq!(redundant_connection, vec![1, 4]);
|
||
}
|
||
|
||
#[test]
|
||
fn test_prefixes_div_by5() {
|
||
let a = vec![0, 1, 1, 1, 1, 1, 0, 1, 0];
|
||
let by5 = Solution::prefixes_div_by5(a);
|
||
//println!("{:?}", by5);
|
||
assert_eq!(by5, vec![true, false, false, false, true, false, false, true, true]);
|
||
}
|
||
|
||
#[test]
|
||
fn test_length_of_longest_substring() {
|
||
let s = "tmmzuxt".to_string();
|
||
let substring_len = Solution::length_of_longest_substring(s);
|
||
//println!("{}", substring_len);
|
||
assert_eq!(substring_len, 5);
|
||
}
|
||
|
||
#[test]
|
||
fn test_my_atoi() {
|
||
let s = "123leetcode".to_string();
|
||
let n = Solution::my_atoi(s);
|
||
//println!("{}", n);
|
||
assert_eq!(n, 123);
|
||
}
|
||
|
||
#[test]
|
||
fn test_divide() {
|
||
let dividend = i32::MIN;
|
||
let divisor = -1;
|
||
let d = Solution::divide(dividend, divisor);
|
||
//println!("{}", d);
|
||
assert_eq!(d, i32::MAX);
|
||
}
|
||
|
||
#[test]
|
||
fn test_my_sqrt() {
|
||
let x = 2147395599;
|
||
let i = Solution::my_sqrt(x);
|
||
//println!("{}", i);
|
||
assert_eq!(i, 46339);
|
||
}
|
||
|
||
#[test]
|
||
fn test_remove_stones() {
|
||
let stones = vec![vec![0, 0], vec![0, 1], vec![1, 0], vec![1, 2], vec![2, 1], vec![2, 2]];
|
||
let i = Solution::remove_stones(stones);
|
||
//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);
|
||
}
|
||
|
||
#[test]
|
||
fn test_sum_nums() {
|
||
let n = 100;
|
||
assert_eq!(Solution::sum_nums(n), n * (n + 1) /2);
|
||
}
|
||
} |