移动部分的题的实现

This commit is contained in:
游由 2022-02-18 16:57:58 +08:00
parent 03cfe2f5f6
commit 63b0036263
19 changed files with 1356 additions and 0 deletions

View File

@ -8,27 +8,40 @@ mod q0007;
mod q0008;
mod q0009;
mod q0012;
mod q0011;
mod q0013;
mod q0014;
mod q0020;
mod q0021;
mod q0026;
mod q0027;
mod q0028;
mod q0029;
mod q0035;
mod q0036;
mod q0045;
mod q0046;
mod q0048;
mod q0053;
mod q0055;
mod q0058;
mod q0066;
mod q0067;
mod q0069;
mod q0070;
mod q0078;
mod q0080;
mod q0081;
mod q0086;
mod q0087;
mod q0088;
mod q0090;
mod q0091;
mod q0094;
mod q0100;
mod q0101;
mod q0102;
mod q0104;
mod q0112;
mod q0110;
mod q0111;
@ -36,6 +49,7 @@ mod q0118;
mod q0119;
mod q0121;
mod q0122;
mod q0125;
mod q0136;
mod q0137;
mod q0144;
@ -43,6 +57,10 @@ mod q0152;
mod q0153;
mod q0154;
mod q0167;
mod q0168;
mod q0169;
mod q0171;
mod q0172;
mod q0179;
mod q0189;
mod q0190;

View File

@ -0,0 +1,73 @@
use crate::Solution;
impl Solution {
/// [11.盛最多水的容器](https://leetcode-cn.com/problems/container-with-most-water/)
///
/// 2022-02-18 14:37:33
///
/// 给定一个长度为 `n` 的整数数组 `height` 。有 `n` 条垂线,第 `i` 条线的两个端点是 `(i, 0)` 和 `(i, height[i])` 。
///
/// 找出其中的两条线,使得它们与 `x` 轴共同构成的容器可以容纳最多的水。
///
/// 返回容器可以储存的最大水量。
///
/// **说明:** 你不能倾斜容器。
///
/// + **示例 1**
/// + ![](https://aliyun-lc-upload.oss-cn-hangzhou.aliyuncs.com/aliyun-lc-upload/uploads/2018/07/25/question_11.jpg)
/// + **输入:** \[1,8,6,2,5,4,8,3,7\]
/// + **输出:** 49
/// + **解释:** 图中垂直线代表输入数组 \[1,8,6,2,5,4,8,3,7\]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
/// + **示例 2**
/// + **输入:** height = \[1,1\]
/// + **输出:** 1
/// + **提示:**
/// * `n == height.length`
/// * `2 <= n <= 105`
/// * `0 <= height[i] <= 104`
/// + Related Topics
/// * 贪心
/// * 数组
/// * 双指针
/// * 👍 3190
/// * 👎 0
/// 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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0011() {
let height = vec![1, 8, 6, 2, 5, 4, 8, 3, 7];
assert_eq!(Solution::max_area(height), 49);
}
}

View File

@ -0,0 +1,171 @@
use crate::Solution;
impl Solution {
/// [14.最长公共前缀](https://leetcode-cn.com/problems/longest-common-prefix/)
///
/// 2022-02-18 14:23:27
///
/// 编写一个函数来查找字符串数组中的最长公共前缀。
///
/// 如果不存在公共前缀,返回空字符串 `""`。
///
/// + **示例 1**
/// + **输入:** strs = \["flower","flow","flight"\]
/// + **输出:** "fl"
/// + **示例 2**
/// + **输入:** strs = \["dog","racecar","car"\]
/// + **输出:** ""
/// + **解释:** 输入不存在公共前缀。
/// + **提示:**
/// * `1 <= strs.length <= 200`
/// * `0 <= strs[i].length <= 200`
/// * `strs[i]` 仅由小写英文字母组成
/// + Related Topics
/// * 字符串
/// * 👍 2033
/// * 👎 0
///
/// 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();
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0014() {
let strs = vec!["flower".to_string(), "flow".to_string(), "flight".to_string()];
assert_eq!(Solution::longest_common_prefix(strs), "fl".to_string());
}
}

View File

@ -0,0 +1,94 @@
use crate::Solution;
impl Solution {
/// [20.有效的括号](https://leetcode-cn.com/problems/valid-parentheses/)
///
/// 2022-02-18 14:32:08
///
/// 给定一个只包括 `'('``')'``'{'``'}'``'['``']'` 的字符串 `s` ,判断字符串是否有效。
///
/// 有效字符串需满足:
///
/// > 1. 左括号必须用相同类型的右括号闭合。
/// > 2. 左括号必须以正确的顺序闭合。
///
/// + **示例 1**
/// + **输入:** s = "()"
/// + **输出:** true
/// + **示例 2**
/// + **输入:** s = "()\[\]{}"
/// + **输出:** true
/// + **示例 3**
/// + **输入:** s = "(\]"
/// + **输出:** false
/// + **示例 4**
/// + **输入:** s = "(\[)\]"
/// + **输出:** false
/// + **示例 5**
/// + **输入:** s = "{\[\]}"
/// + **输出:** true
/// + **提示:**
/// * `1 <= s.length <= 104`
/// * `s` 仅由括号 `'()[]{}'` 组成
/// + Related Topics
/// * 栈
/// * 字符串
/// * 👍 2979
/// * 👎 0
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()
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0020() {
assert_eq!(Solution::is_valid("()[]{}".to_string()), true);
}
}

View File

@ -0,0 +1,76 @@
use crate::Solution;
impl Solution {
/// [29.两数相除](https://leetcode-cn.com/problems/divide-two-integers/)
///
/// 2022-02-18 14:42:40
///
/// 给定两个整数,被除数 `dividend` 和除数 `divisor`。将两数相除,要求不使用乘法、除法和 mod 运算符。
///
/// 返回被除数 `dividend` 除以除数 `divisor` 得到的商。
///
/// 整数除法的结果应当截去(`truncate`)其小数部分,例如:`truncate(8.345) = 8` 以及 `truncate(-2.7335) = -2`
///
/// + **示例 1:**
/// + **输入:** dividend = 10, divisor = 3
/// + **输出:** 3
/// + **解释:** 10/3 = truncate(3.33333..) = truncate(3) = 3
/// + **示例 2:**
/// + **输入:** dividend = 7, divisor = -3
/// + **输出:** -2
/// + **解释:** 7/-3 = truncate(-2.33333..) = -2
/// + **提示:**
/// * 被除数和除数均为 32 位有符号整数。
/// * 除数不为 0。
/// * 假设我们的环境只能存储 32 位有符号整数,其数值范围是 \[231, 231 1\]。本题中,如果除法结果溢出,则返回 231 1。
/// + Related Topics
/// * 位运算
/// * 数学
/// * 👍 839
/// * 👎 0
///
/// 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. 位运算除法
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;
}
}
match negative {
true => -ret,
_ => ret
}
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0029() {
assert_eq!(Solution::divide(10, 3), 3);
}
}

View File

@ -0,0 +1,98 @@
use crate::Solution;
impl Solution {
/// [36.有效的数独](https://leetcode-cn.com/problems/valid-sudoku/)
///
/// 2022-02-18 14:48:44
///
/// 请你判断一个 `9 x 9` 的数独是否有效。只需要 **根据以下规则** ,验证已经填入的数字是否有效即可。
///
/// > 1. 数字 `1-9` 在每一行只能出现一次。
/// > 2. 数字 `1-9` 在每一列只能出现一次。
/// > 3. 数字 `1-9` 在每一个以粗实线分隔的 `3x3` 宫内只能出现一次。(请参考示例图)
///
/// + **注意:**
/// * 一个有效的数独(部分已被填充)不一定是可解的。
/// * 只需要根据以上规则,验证已经填入的数字是否有效即可。
/// * 空白格用 `'.'` 表示。
/// + **示例 1**
/// + ![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2021/04/12/250px-sudoku-by-l2g-20050714svg.png)
/// + **输入:**
/// ``` txt
/// board = [["5","3",".",".","7",".",".",".","."],
/// ["6",".",".","1","9","5",".",".","."],
/// [".","9","8",".",".",".",".","6","."],
/// ["8",".",".",".","6",".",".",".","3"],
/// ["4",".",".","8",".","3",".",".","1"],
/// ["7",".",".",".","2",".",".",".","6"],
/// [".","6",".",".",".",".","2","8","."],
/// [".",".",".","4","1","9",".",".","5"],
/// [".",".",".",".","8",".",".","7","9"]]
/// ```
/// + **输出:** true
/// + **示例 2**
/// + **输入:**
/// ``` txt
/// board = [["8","3",".",".","7",".",".",".","."],
/// ["6",".",".","1","9","5",".",".","."],
/// [".","9","8",".",".",".",".","6","."],
/// ["8",".",".",".","6",".",".",".","3"],
/// ["4",".",".","8",".","3",".",".","1"],
/// ["7",".",".",".","2",".",".",".","6"],
/// [".","6",".",".",".",".","2","8","."],
/// [".",".",".","4","1","9",".",".","5"],
/// [".",".",".",".","8",".",".","7","9"]]
/// ```
/// + **输出:** false
/// + **解释:** 除了第一行的第一个数字从 **5** 改为 **8** 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
/// + **提示:**
/// * `board.length == 9`
/// * `board[i].length == 9`
/// * `board[i][j]` 是一位数字(`1-9`)或者 `'.'`
/// + Related Topics
/// * 数组
/// * 哈希表
/// * 矩阵
/// * 👍 768
/// * 👎 0
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;
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0036() {
let board =
vec![vec!['5', '3', '.', '.', '7', '.', '.', '.', '.'],
vec!['6', '.', '.', '1', '9', '5', '.', '.', '.'],
vec!['.', '9', '8', '.', '.', '.', '.', '6', '.'],
vec!['8', '.', '.', '.', '6', '.', '.', '.', '3'],
vec!['4', '.', '.', '8', '.', '3', '.', '.', '1'],
vec!['7', '.', '.', '.', '2', '.', '.', '.', '6'],
vec!['.', '6', '.', '.', '.', '.', '2', '8', '.'],
vec!['.', '.', '.', '4', '1', '9', '.', '.', '5'],
vec!['.', '.', '.', '.', '8', '.', '.', '7', '9']];
assert_eq!(Solution::is_valid_sudoku(board), true);
}
}

View File

@ -0,0 +1,92 @@
use crate::Solution;
impl Solution {
/// [48.旋转图像](https://leetcode-cn.com/problems/rotate-image/)
///
/// 2022-02-18 15:03:55
///
/// 给定一个 _n _× _n_ 的二维矩阵 `matrix` 表示一个图像。请你将图像顺时针旋转 90 度。
///
/// 你必须在 **[原地](https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95)** 旋转图像,这意味着你需要直接修改输入的二维矩阵。**请不要** 使用另一个矩阵来旋转图像。
///
/// + **示例 1**
/// + ![](https://assets.leetcode.com/uploads/2020/08/28/mat1.jpg)
/// + **输入:** matrix = \[\[1,2,3\],\[4,5,6\],\[7,8,9\]\]
/// + **输出:** \[\[7,4,1\],\[8,5,2\],\[9,6,3\]\]
/// + **示例 2**
/// + ![](https://assets.leetcode.com/uploads/2020/08/28/mat2.jpg)
/// + **输入:** matrix = \[\[5,1,9,11\],\[2,4,8,10\],\[13,3,6,7\],\[15,14,12,16\]\]
/// + **输出:** \[\[15,13,2,5\],\[14,3,4,1\],\[12,6,8,9\],\[16,7,10,11\]\]
/// + **提示:**
/// * `n == matrix.length == matrix[i].length`
/// * `1 <= n <= 20`
/// * `-1000 <= matrix[i][j] <= 1000`
/// + Related Topics
/// * 数组
/// * 数学
/// * 矩阵
/// * 👍 1169
/// * 👎 0
///
/// 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];
}
}
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0048() {
let mut matrix = vec![vec![5, 1, 9, 11], vec![2, 4, 8, 10], vec![13, 3, 6, 7], vec![15, 14, 12, 16]];
let ans = vec![vec![15, 13, 2, 5], vec![14, 3, 4, 1], vec![12, 6, 8, 9], vec![16, 7, 10, 11]];
Solution::rotate1(&mut matrix);
assert_eq!(matrix, ans);
}
}

View File

@ -0,0 +1,70 @@
use crate::Solution;
impl Solution {
/// [58.最后一个单词的长度](https://leetcode-cn.com/problems/length-of-last-word/)
///
/// 2022-02-18 15:14:10
///
/// 给你一个字符串 `s`,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度。
///
/// **单词** 是指仅由字母组成、不包含任何空格字符的最大子字符串。
///
/// + **示例 1**
/// + **输入:** s = "Hello World"
/// + **输出:** 5
/// + **示例 2**
/// + **输入:** s = " fly me to the moon "
/// + **输出:** 4
/// + **示例 3**
/// + **输入:** s = "luffy is still joyboy"
/// + **输出:** 6
/// + **提示:**
/// * `1 <= s.length <= 104`
/// * `s` 仅有英文字母和空格 `' '` 组成
/// * `s` 中至少存在一个单词
/// + Related Topics
/// * 字符串
/// * 👍 420
/// * 👎 0
/// 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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0058() {
assert_eq!(Solution::length_of_last_word("Hello World".to_string()), 5);
}
}

View File

@ -0,0 +1,55 @@
use crate::Solution;
impl Solution {
/// [66.加一](https://leetcode-cn.com/problems/plus-one/)
///
/// 2022-02-18 15:21:59
///
/// 给定一个由 **整数** 组成的 **非空** 数组所表示的非负整数,在该数的基础上加一。
///
/// 最高位数字存放在数组的首位, 数组中每个元素只存储**单个**数字。
///
/// 你可以假设除了整数 0 之外,这个整数不会以零开头。
///
/// + **示例 1**
/// + **输入:** digits = \[1,2,3\]
/// + **输出:** \[1,2,4\]
/// + **解释:** 输入数组表示数字 123。
/// + **示例 2**
/// + **输入:** digits = \[4,3,2,1\]
/// + **输出:** \[4,3,2,2\]
/// + **解释:** 输入数组表示数字 4321。
/// + **示例 3**
/// + **输入:** digits = \[0\]
/// + **输出:** \[1\]
/// + **提示:**
/// * `1 <= digits.length <= 100`
/// * `0 <= digits[i] <= 9`
/// + Related Topics
/// * 数组
/// * 数学
/// * 👍 920
/// * 👎 0
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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0066() {
assert_eq!(Solution::plus_one(vec![1, 2, 3]), vec![1, 2, 4]);
}
}

View File

@ -0,0 +1,61 @@
use crate::Solution;
impl Solution {
/// [67.二进制求和](https://leetcode-cn.com/problems/add-binary/)
///
/// 2022-02-18 15:27:04
///
/// 给你两个二进制字符串,返回它们的和(用二进制表示)。
///
/// 输入为 **非空** 字符串且只包含数字 `1` 和 `0`。
///
/// + **示例 1:**
/// + **输入:** a = "11", b = "1"
/// + **输出:** "100"
/// + **示例 2:**
/// + **输入:** a = "1010", b = "1011"
/// + **输出:** "10101"
/// + **提示:**
/// * 每个字符串仅由字符 `'0'` 或 `'1'` 组成。
/// * `1 <= a.length, b.length <= 10^4`
/// * 字符串如果不是 `"0"` ,就都不含前导零。
/// + Related Topics
/// * 位运算
/// * 数学
/// * 字符串
/// * 模拟
/// * 👍 746
/// * 👎 0
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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0067() {
assert_eq!(Solution::add_binary("11".to_string(), "1".to_string()), "100".to_string());
}
}

View File

@ -0,0 +1,49 @@
use crate::Solution;
impl Solution {
/// [78.子集](https://leetcode-cn.com/problems/subsets/)
///
/// 2022-02-18 15:34:16
///
/// 给你一个整数数组 `nums` ,数组中的元素 **互不相同** 。返回该数组所有可能的子集(幂集)。
///
/// 解集 **不能** 包含重复的子集。你可以按 **任意顺序** 返回解集。
///
/// + **示例 1**
/// + **输入:** nums = \[1,2,3\]
/// + **输出:** \[\[\],\[1\],\[2\],\[1,2\],\[3\],\[1,3\],\[2,3\],\[1,2,3\]\]
/// + **示例 2**
/// + **输入:** nums = \[0\]
/// + **输出:** \[\[\],\[0\]\]
/// + **提示:**
/// * `1 <= nums.length <= 10`
/// * `-10 <= nums[i] <= 10`
/// * `nums` 中的所有元素 **互不相同**
/// + Related Topics
/// * 位运算
/// * 数组
/// * 回溯
/// * 👍 1482
/// * 👎 0
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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0078() {
assert_eq!(Solution::subsets(vec![1, 2, 3]), vec![vec![], vec![1], vec![2], vec![1, 2], vec![3], vec![1, 3], vec![2, 3], vec![1, 2, 3]]);
}
}

View File

@ -0,0 +1,67 @@
use crate::Solution;
use crate::structure::ListNode;
impl Solution {
/// [86.分隔链表](https://leetcode-cn.com/problems/partition-list/)
///
/// 2022-02-18 15:41:39
///
/// 给你一个链表的头节点 `head` 和一个特定值 `x` ,请你对链表进行分隔,使得所有 **小于** `x` 的节点都出现在 **大于或等于** `x` 的节点之前。
///
/// 你应当 **保留** 两个分区中每个节点的初始相对位置。
///
/// + **示例 1**
/// + ![](https://assets.leetcode.com/uploads/2021/01/04/partition.jpg)
/// + **输入:** head = \[1,4,3,2,5,2\], x = 3
/// + **输出:** \[1,2,2,4,3,5\]
/// + **示例 2**
/// + **输入:** head = \[2,1\], x = 2
/// + **输出:** \[1,2\]
/// **提示:**
/// * 链表中节点的数目在范围 `[0, 200]` 内
/// * `-100 <= Node.val <= 100`
/// * `-200 <= x <= 200`
/// + Related Topics
/// * 链表
/// * 双指针
/// * 👍 526
/// * 👎 0
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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
use crate::structure::ListNode;
#[test]
fn test_q0086() {
let head = Some(Box::new(ListNode {
val:2,
next:Some(Box::new(ListNode::new(1)))
}));
let ans = Some(Box::new(ListNode {
val:1,
next:Some(Box::new(ListNode::new(2)))
}));
assert_eq!(Solution::partition(head, 2), ans);
}
}

View File

@ -0,0 +1,86 @@
use crate::Solution;
impl Solution {
/// [88.合并两个有序数组](https://leetcode-cn.com/problems/merge-sorted-array/)
///
/// 2022-02-18 15:53:34
///
/// 给你两个按 **非递减顺序** 排列的整数数组 `nums1` 和 `nums2`,另有两个整数 `m` 和 `n` ,分别表示 `nums1` 和 `nums2` 中的元素数目。
///
/// 请你 **合并** `nums2` 到 `nums1` 中,使合并后的数组同样按 **非递减顺序** 排列。
///
/// **注意:**最终,合并后数组不应由函数返回,而是存储在数组 `nums1` 中。为了应对这种情况,`nums1` 的初始长度为 `m + n`,其中前 `m` 个元素表示应合并的元素,后 `n` 个元素为 `0` ,应忽略。`nums2` 的长度为 `n` 。
///
/// + **示例 1**
/// + **输入:** nums1 = \[1,2,3,0,0,0\], m = 3, nums2 = \[2,5,6\], n = 3
/// + **输出:** \[1,2,2,3,5,6\]
/// + **解释:** 需要合并 \[1,2,3\] 和 \[2,5,6\] 。
///
/// 合并结果是 \[_**1**_,_**2**_,2,_**3**_,5,6\] ,其中斜体加粗标注的为 nums1 中的元素。
///
/// + **示例 2**
/// + **输入:** nums1 = \[1\], m = 1, nums2 = \[\], n = 0
/// + **输出:** \[1\]
/// + **解释:** 需要合并 \[1\] 和 \[\] 。
///
/// 合并结果是 \[1\] 。
///
/// + **示例 3**
/// + **输入:** nums1 = \[0\], m = 0, nums2 = \[1\], n = 1
/// + **输出:** \[1\]
/// + **解释:** 需要合并的数组是 \[\] 和 \[1\] 。
///
/// 合并结果是 \[1\] 。
///
/// 注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
/// + **提示:**
/// * `nums1.length == m + n`
/// * `nums2.length == n`
/// * `0 <= m, n <= 200`
/// * `1 <= m + n <= 200`
/// * `-109 <= nums1[i], nums2[j] <= 109`
/// + **进阶:** 你可以设计实现一个时间复杂度为 `O(m + n)` 的算法解决此问题吗?
/// + Related Topics
/// * 数组
/// * 双指针
/// * 排序
/// * 👍 1289
/// * 👎 0
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];
}
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0088() {
let mut num1 = vec![1, 2, 3, 0, 0, 0];
let m = 3;
let mut nums2 = vec![2, 5, 6];
let n = 3;
Solution::merge(&mut num1, m, &mut nums2, n);
assert_eq!(num1, vec![1, 2, 2, 3, 5, 6]);
}
}

View File

@ -0,0 +1,65 @@
use crate::Solution;
use crate::structure::TreeNode;
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
/// [104.二叉树的最大深度](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/)
///
/// 2022-02-18 16:15:29
///
/// 给定一个二叉树,找出其最大深度。
///
/// 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
///
/// + **说明:** 叶子节点是指没有子节点的节点。
/// + **示例:**
///
/// 给定二叉树 `[3,9,20,null,null,15,7]`
/// ``` txt
/// 3
/// / \
/// 9 20
/// / \
/// 15 7
/// ```
/// 返回它的最大深度 3 。
/// + Related Topics
/// * 树
/// * 深度优先搜索
/// * 广度优先搜索
/// * 二叉树
/// * 👍 1113
/// * 👎 0
pub fn max_depth(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
match root {
Some(node) => match node.borrow_mut() {
mut p => 1 + Self::max_depth(p.left.take()).max(Self::max_depth(p.right.take()))
}
_ => 0
}
}
}
#[cfg(test)]
mod test {
use crate::Solution;
use crate::structure::TreeNode;
use std::rc::Rc;
use std::cell::RefCell;
#[test]
fn test_q0104() {
let root = Some(Rc::new(RefCell::new(TreeNode {
val: 3,
left: Some(Rc::new(RefCell::new(TreeNode::new(9)))),
right: Some(Rc::new(RefCell::new(TreeNode {
val: 20,
left: Some(Rc::new(RefCell::new(TreeNode::new(15)))),
right: Some(Rc::new(RefCell::new(TreeNode::new(7)))),
}))),
})));
assert_eq!(Solution::max_depth(root), 3);
}
}

View File

@ -0,0 +1,74 @@
use crate::Solution;
impl Solution {
/// [125.验证回文串](https://leetcode-cn.com/problems/valid-palindrome/)
///
/// 2022-02-18 16:24:51
///
/// 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
///
/// + **说明:** 本题中,我们将空字符串定义为有效的回文串。
/// + **示例 1:**
/// + **输入:** "A man, a plan, a canal: Panama"
/// + **输出:** true
/// + **解释:** "amanaplanacanalpanama" 是回文串
/// + **示例 2:**
/// + **输入:** "race a car"
/// + **输出:** false
/// + **解释:** "raceacar" 不是回文串
/// + **提示:**
/// * `1 <= s.length <= 2 * 105`
/// * 字符串 `s` 由 ASCII 字符组成
/// + Related Topics
/// * 双指针
/// * 字符串
/// * 👍 472
/// * 👎 0
/// 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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0125() {
assert_eq!(Solution::is_palindrome1("A man, a plan, a canal: Panama".to_string()), true);
}
}

View File

@ -0,0 +1,59 @@
use crate::Solution;
impl Solution {
/// [168.Excel表列名称](https://leetcode-cn.com/problems/excel-sheet-column-title/)
///
/// 2022-02-18 16:31:25
///
/// 给你一个整数 `columnNumber` ,返回它在 Excel 表中相对应的列名称。
///
/// 例如:
/// ``` txt
/// A -> 1
/// B -> 2
/// C -> 3
/// ...
/// Z -> 26
/// AA -> 27
/// AB -> 28
/// ...
/// ```
/// + **示例 1**
/// + **输入:** columnNumber = 1
/// + **输出:** "A"
/// + **示例 2**
/// + **输入:** columnNumber = 28
/// + **输出:** "AB"
/// + **示例 3**
/// + **输入:** columnNumber = 701
/// + **输出:** "ZY"
/// + **示例 4**
/// + **输入:** columnNumber = 2147483647
/// + **输出:** "FXSHRXW"
/// + **提示:**
/// * `1 <= columnNumber <= 231 - 1`
/// + Related Topics
/// * 数学
/// * 字符串
/// * 👍 496
/// * 👎 0
pub fn convert_to_title(mut column_number: i32) -> String {
let mut s = String::with_capacity(8);
while column_number != 0 {
let c = (((column_number - 1) % 26) as u8 + b'A') as char;
s.insert(0, c);
column_number = (column_number - 1) / 26;
}
s
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0168() {
assert_eq!(Solution::convert_to_title(2147483647), "FXSHRXW".to_string());
}
}

View File

@ -0,0 +1,46 @@
use crate::Solution;
impl Solution {
/// [169.多数元素](https://leetcode-cn.com/problems/majority-element/)
///
/// 2022-02-18 16:37:41
///
/// 给定一个大小为 _n_ 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 **大于** `⌊ n/2 ⌋` 的元素。
///
/// 你可以假设数组是非空的,并且给定的数组总是存在多数元素。
///
/// + **示例 1**
/// + **输入:** \[3,2,3\]
/// + **输出:** 3
/// + **示例 2**
/// + **输入:** \[2,2,1,1,1,2,2\]
/// + **输出:** 2
/// + **进阶:**
/// * 尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
/// + Related Topics
/// * 数组
/// * 哈希表
/// * 分治
/// * 计数
/// * 排序
/// * 👍 1305
/// * 👎 0
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
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0169() {
assert_eq!(Solution::majority_element(vec![3, 2, 3]), 3);
}
}

View File

@ -0,0 +1,54 @@
use crate::Solution;
impl Solution {
/// [171.Excel 表列序号](https://leetcode-cn.com/problems/excel-sheet-column-number/)
///
/// 2022-02-18 16:42:37
///
/// 给你一个字符串 `columnTitle` ,表示 Excel 表格中的列名称。返回 _该列名称对应的列序号_ 。
///
/// 例如:
///
/// ``` txt
/// A -> 1
/// B -> 2
/// C -> 3
/// ...
/// Z -> 26
/// AA -> 27
/// AB -> 28
/// ...
/// ```
///
/// + **示例 1:**
/// + **输入:** columnTitle = "A"
/// + **输出:** 1
/// + **示例 2:**
/// + **输入:** columnTitle = "AB"
/// + **输出:** 28
/// + **示例 3:**
/// + **输入:** columnTitle = "ZY"
/// + **输出:** 701
/// + **提示:**
/// * `1 <= columnTitle.length <= 7`
/// * `columnTitle` 仅由大写英文组成
/// * `columnTitle` 在范围 `["A", "FXSHRXW"]` 内
/// + Related Topics
/// * 数学
/// * 字符串
/// * 👍 313
/// * 👎 0
pub fn title_to_number(column_title: String) -> i32 {
column_title.chars().fold(0, |col, c| col * 26 + c as i32 - 64)
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0171() {
assert_eq!(Solution::title_to_number("ZY".to_string()), 701);
}
}

View File

@ -0,0 +1,48 @@
use crate::Solution;
impl Solution {
/// [172.阶乘后的零](https://leetcode-cn.com/problems/factorial-trailing-zeroes/)
///
/// 2022-02-18 16:48:55
///
/// 给定一个整数 `n` ,返回 `n!` 结果中尾随零的数量。
///
/// 提示 `n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1`
///
/// + **示例 1**
/// + **输入:** n = 3
/// + **输出:** 0
/// + **解释:** 3! = 6 ,不含尾随 0
/// + **示例 2**
/// + **输入:** n = 5
/// + **输出:** 1
/// + **解释:** 5! = 120 ,有一个尾随 0
/// + **示例 3**
/// + **输入:** n = 0
/// + **输出:** 0
/// + **提示:**
/// * `0 <= n <= 104`
/// + **进阶:** 你可以设计并实现对数时间复杂度的算法来解决此问题吗?
/// + Related Topics
/// * 数学
/// * 👍 549
/// * 👎 0
pub fn trailing_zeroes(mut n: i32) -> i32 {
let mut zero_count = 0;
while n > 0 {
n /= 5;
zero_count += n;
}
zero_count
}
}
#[cfg(test)]
mod test {
use crate::Solution;
#[test]
fn test_q0172() {
assert_eq!(Solution::trailing_zeroes(5), 1);
}
}