移动部分的题的实现

This commit is contained in:
游由 2022-02-18 17:38:02 +08:00
parent 2d5172de39
commit 1f5413830d
9 changed files with 501 additions and 202 deletions

View File

@ -66,19 +66,26 @@ mod q0189;
mod q0190;
mod q0191;
mod q0198;
mod q0201;
mod q0206;
mod q0213;
mod q0217;
mod q0220;
mod q0224;
mod q0226;
mod q0228;
mod q0231;
mod q0257;
mod q0258;
mod q0260;
mod q0263;
mod q0264;
mod q0268;
mod q0278; //交互 没有测试
mod q0283;
mod q0287;
mod q0289;
mod q0292;
mod q0299;
mod q0319;
mod q0342;

View File

@ -0,0 +1,84 @@
use crate::Solution;
impl Solution {
/// [201.数字范围按位与](https://leetcode-cn.com/problems/bitwise-and-of-numbers-range/)
///
/// 2022-02-18 17:00:11
///
/// 给你两个整数 `left` 和 `right` ,表示区间 `[left, right]` ,返回此区间内所有数字 **按位与** 的结果(包含 `left` 、`right` 端点)。
///
/// + **示例 1**
/// + **输入:** left = 5, right = 7
/// + **输出:** 4
/// + **示例 2**
/// + **输入:** left = 0, right = 0
/// + **输出:** 0
/// + **示例 3**
/// + **输入:** left = 1, right = 2147483647
/// + **输出:** 0
/// + **提示:**
/// * `0 <= left <= right <= 231 - 1`
/// + Related Topics
/// * 位运算
/// * 👍 361
/// * 👎 0
///
/// 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)
/// ```
pub fn range_bitwise_and(left: i32, right: i32) -> i32 {
if left == right {
return left;
}
let mut mask = left ^ right;
mask |= (mask >> 1);
mask |= (mask >> 2);
mask |= (mask >> 4);
mask |= (mask >> 8);
mask |= (mask >> 16);
left & (!mask)
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0201() {
assert_eq!(Solution::range_bitwise_and(5, 7), 4);
}
}

View File

@ -0,0 +1,48 @@
use crate::Solution;
impl Solution {
/// [217.存在重复元素](https://leetcode-cn.com/problems/contains-duplicate/)
///
/// 2022-02-18 17:07:55
///
/// 给你一个整数数组 `nums` 。如果任一值在数组中出现 **至少两次** ,返回 `true` ;如果数组中每个元素互不相同,返回 `false` 。
///
/// + **示例 1**
/// + **输入:** nums = \[1,2,3,1\]
/// + **输出:** true
/// + **示例 2**
/// + **输入:** nums = \[1,2,3,4\]
/// + **输出:** false
/// + **示例 3**
/// + **输入:** nums = \[1,1,1,3,3,4,3,2,4,2\]
/// + **输出:** true
/// + **提示:**
/// * `1 <= nums.length <= 105`
/// * `-109 <= nums[i] <= 109`
/// + Related Topics
/// * 数组
/// * 哈希表
/// * 排序
/// * 👍 626
/// * 👎 0
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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0217() {
assert_eq!(Solution::contains_duplicate(vec![1, 2, 3, 1]), true);
}
}

View File

@ -0,0 +1,87 @@
use crate::Solution;
impl Solution {
/// [224.基本计算器](https://leetcode-cn.com/problems/basic-calculator/)
///
/// 2022-02-18 17:12:40
///
/// 给你一个字符串表达式 `s` ,请你实现一个基本计算器来计算并返回它的值。
///
/// 注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 `eval()` 。
///
/// + **示例 1**
/// + **输入:** s = "1 + 1"
/// + **输出:** 2
/// + **示例 2**
/// + **输入:** s = " 2-1 + 2 "
/// + **输出:** 3
/// + **示例 3**
/// + **输入:** s = "(1+(4+5+2)-3)+(6+8)"
/// + **输出:** 23
/// + **提示:**
/// * `1 <= s.length <= 3 * 105`
/// * `s` 由数字、`'+'`、`'-'`、`'('`、`')'`、和 `' '` 组成
/// * `s` 表示一个有效的表达式
/// * '+' 不能用作一元运算(例如, "+1" 和 `"+(2 + 3)"` 无效)
/// * '-' 可以用作一元运算(即 "-1" 和 `"-(2 + 3)"` 是有效的)
/// * 输入中不存在两个连续的操作符
/// * 每个数字和运行的计算将适合于一个有符号的 32位 整数
/// + Related Topics
/// * 栈
/// * 递归
/// * 数学
/// * 字符串
/// * 👍 709
/// * 👎 0
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)
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0224() {
assert_eq!(Solution::calculate("(1+(4+5+2)-3)+(6+8)".to_string()), 23);
}
}

View File

@ -0,0 +1,79 @@
use crate::Solution;
impl Solution {
/// [228.汇总区间](https://leetcode-cn.com/problems/summary-ranges/)
///
/// 2022-02-18 17:16:43
///
/// 给定一个 **无重复元素** 的 **有序** 整数数组 `nums` 。
///
/// 返回 _**恰好覆盖数组中所有数字** 的 **最小有序** 区间范围列表 _。也就是说`nums` 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 `nums` 的数字 `x` 。
///
/// 列表中的每个区间范围 `[a,b]` 应该按如下格式输出:
///
/// * `"a->b"` ,如果 `a != b`
/// * `"a"` ,如果 `a == b`
/// + **示例 1**
/// + **输入:** nums = \[0,1,2,4,5,7\]
/// + **输出:** \["0->2","4->5","7"\]
/// + **解释:** 区间范围是:
///
/// \[0,2\] --> "0->2"
///
/// \[4,5\] --> "4->5"
///
/// \[7,7\] --> "7"
///
/// + **示例 2**
/// + **输入:** nums = \[0,2,3,4,6,8,9\]
/// + **输出:** \["0","2->4","6","8->9"\]
/// + **解释:** 区间范围是:
///
/// \[0,0\] --> "0"
///
/// \[2,4\] --> "2->4"
///
/// \[6,6\] --> "6"
///
/// \[8,9\] --> "8->9"
///
/// + **提示:**
/// * `0 <= nums.length <= 20`
/// * `-231 <= nums[i] <= 231 - 1`
/// * `nums` 中的所有值都 **互不相同**
/// * `nums` 按升序排列
/// Related Topics
/// * 数组
/// * 👍 201
/// * 👎 0
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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0228() {
assert_eq!(Solution::summary_ranges(vec![0, 2, 3, 4, 6, 8, 9]), vec!["0".to_string(), "2->4".to_string(), "6".to_string(), "8->9".to_string()]);
}
}

View File

@ -0,0 +1,49 @@
use crate::Solution;
impl Solution {
/// [260.只出现一次的数字 III](https://leetcode-cn.com/problems/single-number-iii/)
///
/// 2022-02-18 17:22:33
///
/// 给定一个整数数组 `nums`,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 **任意顺序** 返回答案。
///
/// + **进阶:**你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?
/// + **示例 1**
/// + **输入:** nums = \[1,2,1,3,2,5\]
/// + **输出:** \[3,5\]
/// + **解释:** \[5, 3\] 也是有效的答案。
/// + **示例 2**
/// + **输入:** nums = \[-1,0\]
/// + **输出:** \[-1,0\]
/// + **示例 3**
/// + **输入:** nums = \[0,1\]
/// + **输出:** \[1,0\]
/// + **提示:**
/// * `2 <= nums.length <= 3 * 104`
/// * `-231 <= nums[i] <= 231 - 1`
/// * 除两个只出现一次的整数外,`nums` 中的其他数字都出现两次
/// + Related Topics
/// * 位运算
/// * 数组
/// * 👍 570
/// * 👎 0
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]
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0260() {
assert_eq!(Solution::single_number3(vec![1, 2, 1, 3, 2, 5]), vec![3, 5]);
}
}

View File

@ -0,0 +1,94 @@
use crate::Solution;
impl Solution {
/// [287.寻找重复数](https://leetcode-cn.com/problems/find-the-duplicate-number/)
///
/// 2022-02-18 17:28:10
///
/// 给定一个包含 `n + 1` 个整数的数组 `nums` ,其数字都在 `[1, n]` 范围内(包括 `1` 和 `n`),可知至少存在一个重复的整数。
///
/// 假设 `nums` 只有 **一个重复的整数** ,返回 **这个重复的数** 。
///
/// 你设计的解决方案必须 **不修改** 数组 `nums` 且只用常量级 `O(1)` 的额外空间。
///
/// + **示例 1**
/// + **输入:** nums = \[1,3,4,2,2\]
/// + **输出:** 2
/// + **示例 2**
/// + **输入:** nums = \[3,1,3,4,2\]
/// + **输出:** 3
/// + **提示:**
/// * `1 <= n <= 105`
/// * `nums.length == n + 1`
/// * `1 <= nums[i] <= n`
/// * `nums` 中 **只有一个整数** 出现 **两次或多次** ,其余整数均只出现 **一次**
/// + **进阶:**
/// * 如何证明 `nums` 中至少存在一个重复的数字?
/// * 你可以设计一个线性级时间复杂度 `O(n)` 的解决方案吗?
/// + Related Topics
/// * 位运算
/// * 数组
/// * 双指针
/// * 二分查找
/// * 👍 1580
/// * 👎 0
///
/// 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. 快慢指针
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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0287() {
assert_eq!(Solution::find_duplicate(vec![1, 3, 4, 2, 2]), 2);
}
}

View File

@ -0,0 +1,53 @@
use crate::Solution;
impl Solution {
/// [292.Nim 游戏](https://leetcode-cn.com/problems/nim-game/)
///
/// 2022-02-18 17:32:28
///
/// 你和你的朋友,两个人一起玩 [Nim 游戏](https://baike.baidu.com/item/Nim游戏/6737105)
///
/// * 桌子上有一堆石头。
/// * 你们轮流进行自己的回合, **你作为先手 **。
/// * 每一回合,轮到的人拿掉 1 - 3 块石头。
/// * 拿掉最后一块石头的人就是获胜者。
///
/// 假设你们每一步都是最优解。请编写一个函数,来判断你是否可以在给定石头数量为 `n` 的情况下赢得游戏。如果可以赢,返回 `true`;否则,返回 `false` 。
///
/// + **示例 1**
/// + **输入:** `n = 4`
/// + **输出:** false
/// + **解释:** 以下是可能的结果:
/// 1. 移除1颗石头。你的朋友移走了3块石头包括最后一块。你的朋友赢了。
/// 2. 移除2个石子。你的朋友移走2块石头包括最后一块。你的朋友赢了。
/// 3. 你移走3颗石子。你的朋友移走了最后一块石头。你的朋友赢了。
///
/// 在所有结果中,你的朋友是赢家。
/// + **示例 2**
/// + **输入:** n = 1
/// + **输出:** true
/// + **示例 3**
/// + **输入:** n = 2
/// + **输出:** true
/// + **提示:**
/// * `1 <= n <= 231 - 1`
/// + Related Topics
/// * 脑筋急转弯
/// * 数学
/// * 博弈
/// * 👍 565
/// * 👎 0
pub fn can_win_nim(n: i32) -> bool {
(n & 3) == 0
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0292() {
assert_eq!(Solution::can_win_nim(4), true);
}
}

View File

@ -37,19 +37,6 @@ impl Solution {
total(&nums, 0, nums.len() - 1, 1) >= 0
}
/// 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]
}
/// 338.比特位计数
///
/// [原题链接](https://leetcode-cn.com/problems/counting-bits/)
@ -140,58 +127,6 @@ impl Solution {
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/)
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)
}
/// 面试题 16.01.交换数字
///
/// [原题链接](https://leetcode-cn.com/problems/swap-numbers-lcci/)
@ -241,60 +176,6 @@ impl Solution {
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/)
@ -525,19 +406,6 @@ impl Solution {
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
}
/// 435.无重叠区间
///
/// [原题链接](https://leetcode-cn.com/problems/non-overlapping-intervals/)
@ -1016,30 +884,6 @@ impl Solution {
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/)
@ -1273,52 +1117,6 @@ impl Solution {
(stones.len() - count) as i32
}
/// 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 快慢指针
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/)