my_leetcode/rust/src/leet_code.rs

4306 lines
139 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 题库
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);
}
}