cargo fmt rust code (#1131)

* cargo fmt code

* Add empty line to seperate unrelated comments

* Fix review

* Update bubble_sort.rs

* Update merge_sort.rs

---------

Co-authored-by: Yudong Jin <krahets@163.com>
This commit is contained in:
rongyi
2024-03-16 02:13:41 +08:00
committed by GitHub
parent 54ceef3443
commit 7b1094318b
70 changed files with 1021 additions and 836 deletions

View File

@@ -79,7 +79,7 @@ fn main() {
// 在 Rust 中,指定长度时([i32; 5])为数组
// 由于 Rust 的数组被设计为在编译期确定长度,因此只能使用常量来指定长度
// 为了方便实现扩容 extend() 方法,以下将(Vec) 看作数组Array也是rust一般情况下使用动态数组的类型
let nums = vec![ 1, 3, 2, 5, 4 ];
let nums = vec![1, 3, 2, 5, 4];
print!("\n数组 nums = ");
print_util::print_array(&nums);

View File

@@ -6,14 +6,14 @@
include!("../include/include.rs");
use std::rc::Rc;
use std::cell::RefCell;
use list_node::ListNode;
use std::cell::RefCell;
use std::rc::Rc;
/* 在链表的节点 n0 之后插入节点 P */
#[allow(non_snake_case)]
pub fn insert<T>(n0: &Rc<RefCell<ListNode<T>>>, P: Rc<RefCell<ListNode<T>>>) {
let n1 = n0.borrow_mut().next.take();
let n1 = n0.borrow_mut().next.take();
P.borrow_mut().next = n1;
n0.borrow_mut().next = Some(P);
}
@@ -21,7 +21,9 @@ pub fn insert<T>(n0: &Rc<RefCell<ListNode<T>>>, P: Rc<RefCell<ListNode<T>>>) {
/* 删除链表的节点 n0 之后的首个节点 */
#[allow(non_snake_case)]
pub fn remove<T>(n0: &Rc<RefCell<ListNode<T>>>) {
if n0.borrow().next.is_none() {return};
if n0.borrow().next.is_none() {
return;
};
// n0 -> P -> n1
let P = n0.borrow_mut().next.take();
if let Some(node) = P {
@@ -32,7 +34,9 @@ pub fn remove<T>(n0: &Rc<RefCell<ListNode<T>>>) {
/* 访问链表中索引为 index 的节点 */
pub fn access<T>(head: Rc<RefCell<ListNode<T>>>, index: i32) -> Rc<RefCell<ListNode<T>>> {
if index <= 0 {return head};
if index <= 0 {
return head;
};
if let Some(node) = &head.borrow_mut().next {
return access(node.clone(), index - 1);
}
@@ -41,7 +45,9 @@ pub fn access<T>(head: Rc<RefCell<ListNode<T>>>, index: i32) -> Rc<RefCell<ListN
/* 在链表中查找值为 target 的首个节点 */
pub fn find<T: PartialEq>(head: Rc<RefCell<ListNode<T>>>, target: T, index: i32) -> i32 {
if head.borrow().val == target {return index};
if head.borrow().val == target {
return index;
};
if let Some(node) = &head.borrow_mut().next {
return find(node.clone(), target, index + 1);
}
@@ -51,7 +57,7 @@ pub fn find<T: PartialEq>(head: Rc<RefCell<ListNode<T>>>, target: T, index: i32)
/* Driver Code */
fn main() {
/* 初始化链表 */
// 初始化各个节点
// 初始化各个节点
let n0 = ListNode::new(1);
let n1 = ListNode::new(3);
let n2 = ListNode::new(2);

View File

@@ -9,7 +9,7 @@ include!("../include/include.rs");
/* Driver Code */
fn main() {
// 初始化列表
let mut nums: Vec<i32> = vec![ 1, 3, 2, 5, 4 ];
let mut nums: Vec<i32> = vec![1, 3, 2, 5, 4];
print!("列表 nums = ");
print_util::print_array(&nums);
@@ -58,9 +58,10 @@ fn main() {
}
// 拼接两个列表
let mut nums1 = vec![ 6, 8, 7, 10, 9 ];
nums.append(&mut nums1); // append移动 之后 nums1 为空!
// nums.extend(&nums1); // extend借用 nums1 能继续使用
let mut nums1 = vec![6, 8, 7, 10, 9];
nums.append(&mut nums1); // append移动 之后 nums1 为空!
// nums.extend(&nums1); // extend借用 nums1 能继续使用
print!("\n将列表 nums1 拼接到 nums 之后,得到 nums = ");
print_util::print_array(&nums);

View File

@@ -10,16 +10,16 @@ include!("../include/include.rs");
#[allow(dead_code)]
struct MyList {
arr: Vec<i32>, // 数组(存储列表元素)
capacity: usize, // 列表容量
size: usize, // 列表长度(当前元素数量)
extend_ratio: usize, // 每次列表扩容的倍数
capacity: usize, // 列表容量
size: usize, // 列表长度(当前元素数量)
extend_ratio: usize, // 每次列表扩容的倍数
}
#[allow(unused,unused_comparisons)]
#[allow(unused, unused_comparisons)]
impl MyList {
/* 构造方法 */
pub fn new(capacity: usize) -> Self {
let mut vec = Vec::new();
let mut vec = Vec::new();
vec.resize(capacity, 0);
Self {
arr: vec,
@@ -42,13 +42,17 @@ impl MyList {
/* 访问元素 */
pub fn get(&self, index: usize) -> i32 {
// 索引如果越界,则抛出异常,下同
if index >= self.size {panic!("索引越界")};
if index >= self.size {
panic!("索引越界")
};
return self.arr[index];
}
/* 更新元素 */
pub fn set(&mut self, index: usize, num: i32) {
if index >= self.size {panic!("索引越界")};
if index >= self.size {
panic!("索引越界")
};
self.arr[index] = num;
}
@@ -65,7 +69,9 @@ impl MyList {
/* 在中间插入元素 */
pub fn insert(&mut self, index: usize, num: i32) {
if index >= self.size() {panic!("索引越界")};
if index >= self.size() {
panic!("索引越界")
};
// 元素数量超出容量时,触发扩容机制
if self.size == self.capacity() {
self.extend_capacity();
@@ -81,7 +87,9 @@ impl MyList {
/* 删除元素 */
pub fn remove(&mut self, index: usize) -> i32 {
if index >= self.size() {panic!("索引越界")};
if index >= self.size() {
panic!("索引越界")
};
let num = self.arr[index];
// 将将索引 index 之后的元素都向前移动一位
for j in (index..self.size - 1) {

View File

@@ -5,8 +5,15 @@
*/
/* 回溯算法n 皇后 */
fn backtrack(row: usize, n: usize, state: &mut Vec<Vec<String>>, res: &mut Vec<Vec<Vec<String>>>,
cols: &mut [bool], diags1: &mut [bool], diags2: &mut [bool]) {
fn backtrack(
row: usize,
n: usize,
state: &mut Vec<Vec<String>>,
res: &mut Vec<Vec<Vec<String>>>,
cols: &mut [bool],
diags1: &mut [bool],
diags2: &mut [bool],
) {
// 当放置完所有行时,记录解
if row == n {
let mut copy_state: Vec<Vec<String>> = Vec::new();
@@ -51,7 +58,15 @@ fn n_queens(n: usize) -> Vec<Vec<Vec<String>>> {
let mut diags2 = vec![false; 2 * n - 1]; // 记录次对角线上是否有皇后
let mut res: Vec<Vec<Vec<String>>> = Vec::new();
backtrack(0, n, &mut state, &mut res, &mut cols, &mut diags1, &mut diags2);
backtrack(
0,
n,
&mut state,
&mut res,
&mut cols,
&mut diags1,
&mut diags2,
);
res
}

View File

@@ -37,7 +37,7 @@ fn permutations_i(nums: &mut [i32]) -> Vec<Vec<i32>> {
/* Driver Code */
pub fn main() {
let mut nums = [ 1, 2, 3 ];
let mut nums = [1, 2, 3];
let res = permutations_i(&mut nums);

View File

@@ -41,7 +41,7 @@ fn permutations_ii(nums: &mut [i32]) -> Vec<Vec<i32>> {
/* Driver Code */
pub fn main() {
let mut nums = [ 1, 2, 2 ];
let mut nums = [1, 2, 2];
let res = permutations_ii(&mut nums);

View File

@@ -1,50 +1,54 @@
/*
* File: preorder_traversal_ii_compact.rs
* Created Time: 2023-07-15
* Author: codingonion (coderonion@gmail.com)
*/
include!("../include/include.rs");
use std::{cell::RefCell, rc::Rc};
use tree_node::{vec_to_tree, TreeNode};
/* 前序遍历:例题二 */
fn pre_order(res: &mut Vec<Vec<Rc<RefCell<TreeNode>>>>, path: &mut Vec<Rc<RefCell<TreeNode>>>, root: Option<Rc<RefCell<TreeNode>>>) {
if root.is_none() {
return;
}
if let Some(node) = root {
// 尝试
path.push(node.clone());
if node.borrow().val == 7 {
// 记录解
res.push(path.clone());
}
pre_order(res, path, node.borrow().left.clone());
pre_order(res, path, node.borrow().right.clone());
// 回退
path.remove(path.len() - 1);
}
}
/* Driver Code */
pub fn main() {
let root = vec_to_tree([1, 7, 3, 4, 5, 6, 7].map(|x| Some(x)).to_vec());
println!("初始化二叉树");
print_util::print_tree(root.as_ref().unwrap());
// 前序遍历
let mut path = Vec::new();
let mut res = Vec::new();
pre_order(&mut res, &mut path, root);
println!("\n输出所有根节点到节点 7 的路径");
for path in res {
let mut vals = Vec::new();
for node in path {
vals.push(node.borrow().val)
}
println!("{:?}", vals);
}
}
/*
* File: preorder_traversal_ii_compact.rs
* Created Time: 2023-07-15
* Author: codingonion (coderonion@gmail.com)
*/
include!("../include/include.rs");
use std::{cell::RefCell, rc::Rc};
use tree_node::{vec_to_tree, TreeNode};
/* 前序遍历:例题二 */
fn pre_order(
res: &mut Vec<Vec<Rc<RefCell<TreeNode>>>>,
path: &mut Vec<Rc<RefCell<TreeNode>>>,
root: Option<Rc<RefCell<TreeNode>>>,
) {
if root.is_none() {
return;
}
if let Some(node) = root {
// 尝试
path.push(node.clone());
if node.borrow().val == 7 {
// 记录解
res.push(path.clone());
}
pre_order(res, path, node.borrow().left.clone());
pre_order(res, path, node.borrow().right.clone());
// 回退
path.remove(path.len() - 1);
}
}
/* Driver Code */
pub fn main() {
let root = vec_to_tree([1, 7, 3, 4, 5, 6, 7].map(|x| Some(x)).to_vec());
println!("初始化二叉树");
print_util::print_tree(root.as_ref().unwrap());
// 前序遍历
let mut path = Vec::new();
let mut res = Vec::new();
pre_order(&mut res, &mut path, root);
println!("\n输出所有根节点到节点 7 的路径");
for path in res {
let mut vals = Vec::new();
for node in path {
vals.push(node.borrow().val)
}
println!("{:?}", vals);
}
}

View File

@@ -1,51 +1,55 @@
/*
* File: preorder_traversal_iii_compact.rs
* Created Time: 2023-07-15
* Author: codingonion (coderonion@gmail.com)
*/
include!("../include/include.rs");
use std::{cell::RefCell, rc::Rc};
use tree_node::{vec_to_tree, TreeNode};
/* 前序遍历:例题三 */
fn pre_order(res: &mut Vec<Vec<Rc<RefCell<TreeNode>>>>, path: &mut Vec<Rc<RefCell<TreeNode>>>, root: Option<Rc<RefCell<TreeNode>>>) {
// 剪枝
if root.is_none() || root.as_ref().unwrap().borrow().val == 3 {
return;
}
if let Some(node) = root {
// 尝试
path.push(node.clone());
if node.borrow().val == 7 {
// 记录解
res.push(path.clone());
}
pre_order(res, path, node.borrow().left.clone());
pre_order(res, path, node.borrow().right.clone());
// 回退
path.remove(path.len() - 1);
}
}
/* Driver Code */
pub fn main() {
let root = vec_to_tree([1, 7, 3, 4, 5, 6, 7].map(|x| Some(x)).to_vec());
println!("初始化二叉树");
print_util::print_tree(root.as_ref().unwrap());
// 前序遍历
let mut path = Vec::new();
let mut res = Vec::new();
pre_order(&mut res, &mut path, root);
println!("\n输出所有根节点到节点 7 的路径,路径中不包含值为 3 的节点");
for path in res {
let mut vals = Vec::new();
for node in path {
vals.push(node.borrow().val)
}
println!("{:?}", vals);
}
}
/*
* File: preorder_traversal_iii_compact.rs
* Created Time: 2023-07-15
* Author: codingonion (coderonion@gmail.com)
*/
include!("../include/include.rs");
use std::{cell::RefCell, rc::Rc};
use tree_node::{vec_to_tree, TreeNode};
/* 前序遍历:例题三 */
fn pre_order(
res: &mut Vec<Vec<Rc<RefCell<TreeNode>>>>,
path: &mut Vec<Rc<RefCell<TreeNode>>>,
root: Option<Rc<RefCell<TreeNode>>>,
) {
// 剪枝
if root.is_none() || root.as_ref().unwrap().borrow().val == 3 {
return;
}
if let Some(node) = root {
// 尝试
path.push(node.clone());
if node.borrow().val == 7 {
// 记录解
res.push(path.clone());
}
pre_order(res, path, node.borrow().left.clone());
pre_order(res, path, node.borrow().right.clone());
// 回退
path.remove(path.len() - 1);
}
}
/* Driver Code */
pub fn main() {
let root = vec_to_tree([1, 7, 3, 4, 5, 6, 7].map(|x| Some(x)).to_vec());
println!("初始化二叉树");
print_util::print_tree(root.as_ref().unwrap());
// 前序遍历
let mut path = Vec::new();
let mut res = Vec::new();
pre_order(&mut res, &mut path, root);
println!("\n输出所有根节点到节点 7 的路径,路径中不包含值为 3 的节点");
for path in res {
let mut vals = Vec::new();
for node in path {
vals.push(node.borrow().val)
}
println!("{:?}", vals);
}
}

View File

@@ -1,76 +1,90 @@
/*
* File: preorder_traversal_iii_template.rs
* Created Time: 2023-07-15
* Author: codingonion (coderonion@gmail.com)
*/
include!("../include/include.rs");
use std::{cell::RefCell, rc::Rc};
use tree_node::{vec_to_tree, TreeNode};
/* 判断当前状态是否为解 */
fn is_solution(state: &mut Vec<Rc<RefCell<TreeNode>>>) -> bool {
return !state.is_empty() && state.get(state.len() - 1).unwrap().borrow().val == 7;
}
/* 记录解 */
fn record_solution(state: &mut Vec<Rc<RefCell<TreeNode>>>, res: &mut Vec<Vec<Rc<RefCell<TreeNode>>>>) {
res.push(state.clone());
}
/* 判断在当前状态下,该选择是否合法 */
fn is_valid(_: &mut Vec<Rc<RefCell<TreeNode>>>, choice: Rc<RefCell<TreeNode>>) -> bool {
return choice.borrow().val != 3;
}
/* 更新状态 */
fn make_choice(state: &mut Vec<Rc<RefCell<TreeNode>>>, choice: Rc<RefCell<TreeNode>>) {
state.push(choice);
}
/* 恢复状态 */
fn undo_choice(state: &mut Vec<Rc<RefCell<TreeNode>>>, _: Rc<RefCell<TreeNode>>) {
state.remove(state.len() - 1);
}
/* 回溯算法:例题三 */
fn backtrack(state: &mut Vec<Rc<RefCell<TreeNode>>>, choices: &mut Vec<Rc<RefCell<TreeNode>>>, res: &mut Vec<Vec<Rc<RefCell<TreeNode>>>>) {
// 检查是否为解
if is_solution(state) {
// 记录解
record_solution(state, res);
}
// 遍历所有选择
for choice in choices {
// 剪枝:检查选择是否合法
if is_valid(state, choice.clone()) {
// 尝试:做出选择,更新状态
make_choice(state, choice.clone());
// 进行下一轮选择
backtrack(state, &mut vec![choice.borrow().left.clone().unwrap(), choice.borrow().right.clone().unwrap()], res);
// 回退:撤销选择,恢复到之前的状态
undo_choice(state, choice.clone());
}
}
}
/* Driver Code */
pub fn main() {
let root = vec_to_tree([1, 7, 3, 4, 5, 6, 7].map(|x| Some(x)).to_vec());
println!("初始化二叉树");
print_util::print_tree(root.as_ref().unwrap());
// 回溯算法
let mut res = Vec::new();
backtrack(&mut Vec::new(), &mut vec![root.unwrap()], &mut res);
println!("\n输出所有根节点到节点 7 的路径,要求路径中不包含值为 3 的节点");
for path in res {
let mut vals = Vec::new();
for node in path {
vals.push(node.borrow().val)
}
println!("{:?}", vals);
}
}
/*
* File: preorder_traversal_iii_template.rs
* Created Time: 2023-07-15
* Author: codingonion (coderonion@gmail.com)
*/
include!("../include/include.rs");
use std::{cell::RefCell, rc::Rc};
use tree_node::{vec_to_tree, TreeNode};
/* 判断当前状态是否为解 */
fn is_solution(state: &mut Vec<Rc<RefCell<TreeNode>>>) -> bool {
return !state.is_empty() && state.get(state.len() - 1).unwrap().borrow().val == 7;
}
/* 记录解 */
fn record_solution(
state: &mut Vec<Rc<RefCell<TreeNode>>>,
res: &mut Vec<Vec<Rc<RefCell<TreeNode>>>>,
) {
res.push(state.clone());
}
/* 判断在当前状态下,该选择是否合法 */
fn is_valid(_: &mut Vec<Rc<RefCell<TreeNode>>>, choice: Rc<RefCell<TreeNode>>) -> bool {
return choice.borrow().val != 3;
}
/* 更新状态 */
fn make_choice(state: &mut Vec<Rc<RefCell<TreeNode>>>, choice: Rc<RefCell<TreeNode>>) {
state.push(choice);
}
/* 恢复状态 */
fn undo_choice(state: &mut Vec<Rc<RefCell<TreeNode>>>, _: Rc<RefCell<TreeNode>>) {
state.remove(state.len() - 1);
}
/* 回溯算法:例题三 */
fn backtrack(
state: &mut Vec<Rc<RefCell<TreeNode>>>,
choices: &mut Vec<Rc<RefCell<TreeNode>>>,
res: &mut Vec<Vec<Rc<RefCell<TreeNode>>>>,
) {
// 检查是否为解
if is_solution(state) {
// 记录解
record_solution(state, res);
}
// 遍历所有选择
for choice in choices {
// 剪枝:检查选择是否合法
if is_valid(state, choice.clone()) {
// 尝试:做出选择,更新状态
make_choice(state, choice.clone());
// 进行下一轮选择
backtrack(
state,
&mut vec![
choice.borrow().left.clone().unwrap(),
choice.borrow().right.clone().unwrap(),
],
res,
);
// 回退:撤销选择,恢复到之前的状态
undo_choice(state, choice.clone());
}
}
}
/* Driver Code */
pub fn main() {
let root = vec_to_tree([1, 7, 3, 4, 5, 6, 7].map(|x| Some(x)).to_vec());
println!("初始化二叉树");
print_util::print_tree(root.as_ref().unwrap());
// 回溯算法
let mut res = Vec::new();
backtrack(&mut Vec::new(), &mut vec![root.unwrap()], &mut res);
println!("\n输出所有根节点到节点 7 的路径,要求路径中不包含值为 3 的节点");
for path in res {
let mut vals = Vec::new();
for node in path {
vals.push(node.borrow().val)
}
println!("{:?}", vals);
}
}

View File

@@ -1,50 +1,56 @@
/*
* File: subset_sum_i.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 回溯算法:子集和 I */
fn backtrack(mut state: Vec<i32>, target: i32, choices: &[i32], start: usize, res: &mut Vec<Vec<i32>>) {
// 子集和等于 target 时,记录解
if target == 0 {
res.push(state);
return;
}
// 遍历所有选择
// 剪枝二:从 start 开始遍历,避免生成重复子集
for i in start..choices.len() {
// 剪枝一:若子集和超过 target ,则直接结束循环
// 这是因为数组已排序,后边元素更大,子集和一定超过 target
if target - choices[i] < 0 {
break;
}
// 尝试:做出选择,更新 target, start
state.push(choices[i]);
// 进行下一轮选择
backtrack(state.clone(), target - choices[i], choices, i, res);
// 回退:撤销选择,恢复到之前的状态
state.pop();
}
}
/* 求解子集和 I */
fn subset_sum_i(nums: &mut [i32], target: i32) -> Vec<Vec<i32>> {
let state = Vec::new(); // 状态(子集)
nums.sort(); // 对 nums 进行排序
let start = 0; // 遍历起始点
let mut res = Vec::new(); // 结果列表(子集列表)
backtrack(state, target, nums, start, &mut res);
res
}
/* Driver Code */
pub fn main() {
let mut nums = [ 3, 4, 5 ];
let target = 9;
let res = subset_sum_i(&mut nums, target);
println!("输入数组 nums = {:?}, target = {}", &nums, target);
println!("所有和等于 {} 的子集 res = {:?}", target, &res);
}
/*
* File: subset_sum_i.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 回溯算法:子集和 I */
fn backtrack(
mut state: Vec<i32>,
target: i32,
choices: &[i32],
start: usize,
res: &mut Vec<Vec<i32>>,
) {
// 子集和等于 target 时,记录解
if target == 0 {
res.push(state);
return;
}
// 遍历所有选择
// 剪枝二:从 start 开始遍历,避免生成重复子集
for i in start..choices.len() {
// 剪枝一:若子集和超过 target ,则直接结束循环
// 这是因为数组已排序,后边元素更大,子集和一定超过 target
if target - choices[i] < 0 {
break;
}
// 尝试:做出选择,更新 target, start
state.push(choices[i]);
// 进行下一轮选择
backtrack(state.clone(), target - choices[i], choices, i, res);
// 回退:撤销选择,恢复到之前的状态
state.pop();
}
}
/* 求解子集和 I */
fn subset_sum_i(nums: &mut [i32], target: i32) -> Vec<Vec<i32>> {
let state = Vec::new(); // 状态(子集)
nums.sort(); // 对 nums 进行排序
let start = 0; // 遍历起始点
let mut res = Vec::new(); // 结果列表(子集列表)
backtrack(state, target, nums, start, &mut res);
res
}
/* Driver Code */
pub fn main() {
let mut nums = [3, 4, 5];
let target = 9;
let res = subset_sum_i(&mut nums, target);
println!("输入数组 nums = {:?}, target = {}", &nums, target);
println!("所有和等于 {} 的子集 res = {:?}", target, &res);
}

View File

@@ -1,48 +1,54 @@
/*
* File: subset_sum_i_naive.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 回溯算法:子集和 I */
fn backtrack(mut state: Vec<i32>, target: i32, total: i32, choices: &[i32], res: &mut Vec<Vec<i32>>) {
// 子集和等于 target 时,记录解
if total == target {
res.push(state);
return;
}
// 遍历所有选择
for i in 0..choices.len() {
// 剪枝:若子集和超过 target ,则跳过该选择
if total + choices[i] > target {
continue;
}
// 尝试:做出选择,更新元素和 total
state.push(choices[i]);
// 进行下一轮选择
backtrack(state.clone(), target, total + choices[i], choices, res);
// 回退:撤销选择,恢复到之前的状态
state.pop();
}
}
/* 求解子集和 I包含重复子集 */
fn subset_sum_i_naive(nums: &[i32], target: i32) -> Vec<Vec<i32>> {
let state = Vec::new(); // 状态(子集)
let total = 0; // 子集和
let mut res = Vec::new(); // 结果列表(子集列表)
backtrack(state, target, total, nums, &mut res);
res
}
/* Driver Code */
pub fn main() {
let nums = [ 3, 4, 5 ];
let target = 9;
let res = subset_sum_i_naive(&nums, target);
println!("输入数组 nums = {:?}, target = {}", &nums, target);
println!("所有和等于 {} 的子集 res = {:?}", target, &res);
println!("请注意,该方法输出的结果包含重复集合");
}
/*
* File: subset_sum_i_naive.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 回溯算法:子集和 I */
fn backtrack(
mut state: Vec<i32>,
target: i32,
total: i32,
choices: &[i32],
res: &mut Vec<Vec<i32>>,
) {
// 子集和等于 target 时,记录解
if total == target {
res.push(state);
return;
}
// 遍历所有选择
for i in 0..choices.len() {
// 剪枝:若子集和超过 target ,则跳过该选择
if total + choices[i] > target {
continue;
}
// 尝试:做出选择,更新元素和 total
state.push(choices[i]);
// 进行下一轮选择
backtrack(state.clone(), target, total + choices[i], choices, res);
// 回退:撤销选择,恢复到之前的状态
state.pop();
}
}
/* 求解子集和 I包含重复子集 */
fn subset_sum_i_naive(nums: &[i32], target: i32) -> Vec<Vec<i32>> {
let state = Vec::new(); // 状态(子集)
let total = 0; // 子集和
let mut res = Vec::new(); // 结果列表(子集列表)
backtrack(state, target, total, nums, &mut res);
res
}
/* Driver Code */
pub fn main() {
let nums = [3, 4, 5];
let target = 9;
let res = subset_sum_i_naive(&nums, target);
println!("输入数组 nums = {:?}, target = {}", &nums, target);
println!("所有和等于 {} 的子集 res = {:?}", target, &res);
println!("请注意,该方法输出的结果包含重复集合");
}

View File

@@ -1,55 +1,61 @@
/*
* File: subset_sum_ii.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 回溯算法:子集和 II */
fn backtrack(mut state: Vec<i32>, target: i32, choices: &[i32], start: usize, res: &mut Vec<Vec<i32>>) {
// 子集和等于 target 时,记录解
if target == 0 {
res.push(state);
return;
}
// 遍历所有选择
// 剪枝二:从 start 开始遍历,避免生成重复子集
// 剪枝三:从 start 开始遍历,避免重复选择同一元素
for i in start..choices.len() {
// 剪枝一:若子集和超过 target ,则直接结束循环
// 这是因为数组已排序,后边元素更大,子集和一定超过 target
if target - choices[i] < 0 {
break;
}
// 剪枝四:如果该元素与左边元素相等,说明该搜索分支重复,直接跳过
if i > start && choices[i] == choices[i - 1] {
continue;
}
// 尝试:做出选择,更新 target, start
state.push(choices[i]);
// 进行下一轮选择
backtrack(state.clone(), target - choices[i], choices, i, res);
// 回退:撤销选择,恢复到之前的状态
state.pop();
}
}
/* 求解子集和 II */
fn subset_sum_ii(nums: &mut [i32], target: i32) -> Vec<Vec<i32>> {
let state = Vec::new(); // 状态(子集)
nums.sort(); // 对 nums 进行排序
let start = 0; // 遍历起始点
let mut res = Vec::new(); // 结果列表(子集列表)
backtrack(state, target, nums, start, &mut res);
res
}
/* Driver Code */
pub fn main() {
let mut nums = [ 4, 4, 5 ];
let target = 9;
let res = subset_sum_ii(&mut nums, target);
println!("输入数组 nums = {:?}, target = {}", &nums, target);
println!("所有和等于 {} 的子集 res = {:?}", target, &res);
}
/*
* File: subset_sum_ii.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 回溯算法:子集和 II */
fn backtrack(
mut state: Vec<i32>,
target: i32,
choices: &[i32],
start: usize,
res: &mut Vec<Vec<i32>>,
) {
// 子集和等于 target 时,记录解
if target == 0 {
res.push(state);
return;
}
// 遍历所有选择
// 剪枝二:从 start 开始遍历,避免生成重复子集
// 剪枝三:从 start 开始遍历,避免重复选择同一元素
for i in start..choices.len() {
// 剪枝一:若子集和超过 target ,则直接结束循环
// 这是因为数组已排序,后边元素更大,子集和一定超过 target
if target - choices[i] < 0 {
break;
}
// 剪枝四:如果该元素与左边元素相等,说明该搜索分支重复,直接跳过
if i > start && choices[i] == choices[i - 1] {
continue;
}
// 尝试:做出选择,更新 target, start
state.push(choices[i]);
// 进行下一轮选择
backtrack(state.clone(), target - choices[i], choices, i, res);
// 回退:撤销选择,恢复到之前的状态
state.pop();
}
}
/* 求解子集和 II */
fn subset_sum_ii(nums: &mut [i32], target: i32) -> Vec<Vec<i32>> {
let state = Vec::new(); // 状态(子集)
nums.sort(); // 对 nums 进行排序
let start = 0; // 遍历起始点
let mut res = Vec::new(); // 结果列表(子集列表)
backtrack(state, target, nums, start, &mut res);
res
}
/* Driver Code */
pub fn main() {
let mut nums = [4, 4, 5];
let target = 9;
let res = subset_sum_ii(&mut nums, target);
println!("输入数组 nums = {:?}, target = {}", &nums, target);
println!("所有和等于 {} 的子集 res = {:?}", target, &res);
}

View File

@@ -4,7 +4,6 @@
* Author: night-cruise (2586447362@qq.com)
*/
/* for 循环 */
fn for_loop(n: i32) -> i32 {
let mut res = 0;
@@ -13,12 +12,13 @@ fn for_loop(n: i32) -> i32 {
res += i;
}
res
}
}
/* while 循环 */
fn while_loop(n: i32) -> i32 {
let mut res = 0;
let mut i = 1; // 初始化条件变量
// 循环求和 1, 2, ..., n-1, n
while i <= n {
res += i;
@@ -31,6 +31,7 @@ fn while_loop(n: i32) -> i32 {
fn while_loop_ii(n: i32) -> i32 {
let mut res = 0;
let mut i = 1; // 初始化条件变量
// 循环求和 1, 4, 10, ...
while i <= n {
res += i;
@@ -53,7 +54,7 @@ fn nested_for_loop(n: i32) -> String {
}
res.join("")
}
/* Driver Code */
fn main() {
let n = 5;
@@ -70,4 +71,4 @@ fn main() {
let res = nested_for_loop(n);
println!("\n双层 for 循环的遍历结果 {res}");
}
}

View File

@@ -4,7 +4,6 @@
* Author: night-cruise (2586447362@qq.com)
*/
/* 递归 */
fn recur(n: i32) -> i32 {
// 终止条件
@@ -71,7 +70,7 @@ fn main() {
res = tail_recur(n, 0);
println!("\n尾递归函数的求和结果 res = {res}");
res = fib(n);
println!("\n斐波那契数列的第 {n} 项为 {res}");
}
}

View File

@@ -6,14 +6,14 @@
include!("../include/include.rs");
use list_node::ListNode;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use list_node::ListNode;
use tree_node::TreeNode;
/* 函数 */
fn function() ->i32 {
fn function() -> i32 {
// 执行某些操作
return 0;
}
@@ -56,7 +56,9 @@ fn linear(n: i32) {
/* 线性阶(递归实现) */
fn linear_recur(n: i32) {
println!("递归 n = {}", n);
if n == 1 {return};
if n == 1 {
return;
};
linear_recur(n - 1);
}
@@ -78,7 +80,9 @@ fn quadratic(n: i32) {
/* 平方阶(递归实现) */
fn quadratic_recur(n: i32) -> i32 {
if n <= 0 {return 0};
if n <= 0 {
return 0;
};
// 数组 nums 长度为 n, n-1, ..., 2, 1
let nums = vec![0; n as usize];
println!("递归 n = {} 中的 nums 长度 = {}", n, nums.len());
@@ -87,7 +91,9 @@ fn quadratic_recur(n: i32) -> i32 {
/* 指数阶(建立满二叉树) */
fn build_tree(n: i32) -> Option<Rc<RefCell<TreeNode>>> {
if n == 0 {return None};
if n == 0 {
return None;
};
let root = TreeNode::new(0);
root.borrow_mut().left = build_tree(n - 1);
root.borrow_mut().right = build_tree(n - 1);
@@ -107,5 +113,5 @@ fn main() {
quadratic_recur(n);
// 指数阶
let root = build_tree(n);
print_util::print_tree(&root.unwrap());
}
print_util::print_tree(&root.unwrap());
}

View File

@@ -49,9 +49,10 @@ fn quadratic(n: i32) -> i32 {
/* 平方阶(冒泡排序) */
fn bubble_sort(nums: &mut [i32]) -> i32 {
let mut count = 0; // 计数器
// 外循环:未排序区间为 [0, i]
for i in (1..nums.len()).rev() {
// 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端
// 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端
for j in 0..i {
if nums[j] > nums[j + 1] {
// 交换 nums[j] 与 nums[j + 1]
@@ -112,10 +113,10 @@ fn linear_log_recur(n: f32) -> i32 {
return 1;
}
let mut count = linear_log_recur(n / 2.0) + linear_log_recur(n / 2.0);
for _ in 0 ..n as i32 {
for _ in 0..n as i32 {
count += 1;
}
return count
return count;
}
/* 阶乘阶(递归实现) */

View File

@@ -40,4 +40,4 @@ fn main() {
print_util::print_array(&nums);
println!("\n数字 1 的索引为 {}", index);
}
}
}

View File

@@ -7,7 +7,9 @@
/* 二分查找:问题 f(i, j) */
fn dfs(nums: &[i32], target: i32, i: i32, j: i32) -> i32 {
// 若区间为空,代表无目标元素,则返回 -1
if i > j { return -1; }
if i > j {
return -1;
}
let m: i32 = (i + j) / 2;
if nums[m as usize] < target {
// 递归子问题 f(m+1, j)
@@ -31,7 +33,7 @@ fn binary_search(nums: &[i32], target: i32) -> i32 {
/* Driver Code */
pub fn main() {
let target = 6;
let nums = [ 1, 3, 6, 8, 12, 15, 23, 26, 31, 35 ];
let nums = [1, 3, 6, 8, 12, 15, 23, 26, 31, 35];
// 二分查找(双闭区间)
let index = binary_search(&nums, target);

View File

@@ -1,49 +1,57 @@
/*
* File: build_tree.rs
* Created Time: 2023-07-15
* Author: codingonion (coderonion@gmail.com)
*/
use std::{cell::RefCell, rc::Rc};
use std::collections::HashMap;
include!("../include/include.rs");
use tree_node::TreeNode;
/* 构建二叉树:分治 */
fn dfs(preorder: &[i32], inorder_map: &HashMap<i32, i32>, i: i32, l: i32, r: i32) -> Option<Rc<RefCell<TreeNode>>> {
// 子树区间为空时终止
if r - l < 0 { return None; }
// 初始化根节点
let root = TreeNode::new(preorder[i as usize]);
// 查询 m ,从而划分左右子树
let m = inorder_map.get(&preorder[i as usize]).unwrap();
// 子问题:构建左子树
root.borrow_mut().left = dfs(preorder, inorder_map, i + 1, l, m - 1);
// 子问题:构建右子树
root.borrow_mut().right = dfs(preorder, inorder_map, i + 1 + m - l, m + 1, r);
// 返回根节点
Some(root)
}
/* 构建二叉树 */
fn build_tree(preorder: &[i32], inorder: &[i32]) -> Option<Rc<RefCell<TreeNode>>> {
// 初始化哈希表,存储 inorder 元素到索引的映射
let mut inorder_map: HashMap<i32, i32> = HashMap::new();
for i in 0..inorder.len() {
inorder_map.insert(inorder[i], i as i32);
}
let root = dfs(preorder, &inorder_map, 0, 0, inorder.len() as i32 - 1);
root
}
/* Driver Code */
fn main() {
let preorder = [ 3, 9, 2, 1, 7 ];
let inorder = [ 9, 3, 1, 2, 7 ];
println!("中序遍历 = {:?}", preorder);
println!("前序遍历 = {:?}", inorder);
let root = build_tree(&preorder, &inorder);
println!("构建的二叉树为:");
print_util::print_tree(root.as_ref().unwrap());
}
/*
* File: build_tree.rs
* Created Time: 2023-07-15
* Author: codingonion (coderonion@gmail.com)
*/
use std::collections::HashMap;
use std::{cell::RefCell, rc::Rc};
include!("../include/include.rs");
use tree_node::TreeNode;
/* 构建二叉树:分治 */
fn dfs(
preorder: &[i32],
inorder_map: &HashMap<i32, i32>,
i: i32,
l: i32,
r: i32,
) -> Option<Rc<RefCell<TreeNode>>> {
// 子树区间为空时终止
if r - l < 0 {
return None;
}
// 初始化根节点
let root = TreeNode::new(preorder[i as usize]);
// 查询 m ,从而划分左右子树
let m = inorder_map.get(&preorder[i as usize]).unwrap();
// 子问题:构建左子树
root.borrow_mut().left = dfs(preorder, inorder_map, i + 1, l, m - 1);
// 子问题:构建右子树
root.borrow_mut().right = dfs(preorder, inorder_map, i + 1 + m - l, m + 1, r);
// 返回根节点
Some(root)
}
/* 构建二叉树 */
fn build_tree(preorder: &[i32], inorder: &[i32]) -> Option<Rc<RefCell<TreeNode>>> {
// 初始化哈希表,存储 inorder 元素到索引的映射
let mut inorder_map: HashMap<i32, i32> = HashMap::new();
for i in 0..inorder.len() {
inorder_map.insert(inorder[i], i as i32);
}
let root = dfs(preorder, &inorder_map, 0, 0, inorder.len() as i32 - 1);
root
}
/* Driver Code */
fn main() {
let preorder = [3, 9, 2, 1, 7];
let inorder = [9, 3, 1, 2, 7];
println!("中序遍历 = {:?}", preorder);
println!("前序遍历 = {:?}", inorder);
let root = build_tree(&preorder, &inorder);
println!("构建的二叉树为:");
print_util::print_tree(root.as_ref().unwrap());
}

View File

@@ -1,37 +1,41 @@
/*
* File: climbing_stairs_backtrack.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 回溯 */
fn backtrack(choices: &[i32], state: i32, n: i32, res: &mut [i32]) {
// 当爬到第 n 阶时,方案数量加 1
if state == n { res[0] = res[0] + 1; }
// 遍历所有选择
for &choice in choices {
// 剪枝:不允许越过第 n 阶
if state + choice > n { continue; }
// 尝试:做出选择,更新状态
backtrack(choices, state + choice, n, res);
// 回退
}
}
/* 爬楼梯:回溯 */
fn climbing_stairs_backtrack(n: usize) -> i32 {
let choices = vec![ 1, 2 ]; // 可选择向上爬 1 阶或 2 阶
let state = 0; // 从第 0 阶开始爬
let mut res = Vec::new();
res.push(0); // 使用 res[0] 记录方案数量
backtrack(&choices, state, n as i32, &mut res);
res[0]
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_backtrack(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}
/*
* File: climbing_stairs_backtrack.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 回溯 */
fn backtrack(choices: &[i32], state: i32, n: i32, res: &mut [i32]) {
// 当爬到第 n 阶时,方案数量加 1
if state == n {
res[0] = res[0] + 1;
}
// 遍历所有选择
for &choice in choices {
// 剪枝:不允许越过第 n 阶
if state + choice > n {
continue;
}
// 尝试:做出选择,更新状态
backtrack(choices, state + choice, n, res);
// 回退
}
}
/* 爬楼梯:回溯 */
fn climbing_stairs_backtrack(n: usize) -> i32 {
let choices = vec![1, 2]; // 可选择向上爬 1 阶或 2 阶
let state = 0; // 从第 0 阶开始爬
let mut res = Vec::new();
res.push(0); // 使用 res[0] 记录方案数量
backtrack(&choices, state, n as i32, &mut res);
res[0]
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_backtrack(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}

View File

@@ -1,31 +1,33 @@
/*
* File: climbing_stairs_constraint_dp.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 带约束爬楼梯:动态规划 */
fn climbing_stairs_constraint_dp(n: usize) -> i32 {
if n == 1 || n == 2 { return 1 };
// 初始化 dp 表,用于存储子问题的解
let mut dp = vec![vec![-1; 3]; n + 1];
// 初始状态:预设最小子问题的解
dp[1][1] = 1;
dp[1][2] = 0;
dp[2][1] = 0;
dp[2][2] = 1;
// 状态转移:从较小子问题逐步求解较大子问题
for i in 3..=n {
dp[i][1] = dp[i - 1][2];
dp[i][2] = dp[i - 2][1] + dp[i - 2][2];
}
dp[n][1] + dp[n][2]
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_constraint_dp(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}
/*
* File: climbing_stairs_constraint_dp.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 带约束爬楼梯:动态规划 */
fn climbing_stairs_constraint_dp(n: usize) -> i32 {
if n == 1 || n == 2 {
return 1;
};
// 初始化 dp 表,用于存储子问题的解
let mut dp = vec![vec![-1; 3]; n + 1];
// 初始状态:预设最小子问题的解
dp[1][1] = 1;
dp[1][2] = 0;
dp[2][1] = 0;
dp[2][2] = 1;
// 状态转移:从较小子问题逐步求解较大子问题
for i in 3..=n {
dp[i][1] = dp[i - 1][2];
dp[i][2] = dp[i - 2][1] + dp[i - 2][2];
}
dp[n][1] + dp[n][2]
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_constraint_dp(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}

View File

@@ -1,27 +1,29 @@
/*
* File: climbing_stairs_dfs.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 搜索 */
fn dfs(i: usize) -> i32 {
// 已知 dp[1] 和 dp[2] ,返回之
if i == 1 || i == 2 { return i as i32; }
// dp[i] = dp[i-1] + dp[i-2]
let count = dfs(i - 1) + dfs(i - 2);
count
}
/* 爬楼梯:搜索 */
fn climbing_stairs_dfs(n: usize) -> i32 {
dfs(n)
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_dfs(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}
/*
* File: climbing_stairs_dfs.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 搜索 */
fn dfs(i: usize) -> i32 {
// 已知 dp[1] 和 dp[2] ,返回之
if i == 1 || i == 2 {
return i as i32;
}
// dp[i] = dp[i-1] + dp[i-2]
let count = dfs(i - 1) + dfs(i - 2);
count
}
/* 爬楼梯:搜索 */
fn climbing_stairs_dfs(n: usize) -> i32 {
dfs(n)
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_dfs(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}

View File

@@ -1,33 +1,37 @@
/*
* File: climbing_stairs_dfs_mem.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 记忆化搜索 */
fn dfs(i: usize, mem: &mut [i32]) -> i32 {
// 已知 dp[1] 和 dp[2] ,返回之
if i == 1 || i == 2 { return i as i32; }
// 若存在记录 dp[i] ,则直接返回之
if mem[i] != -1 { return mem[i]; }
// dp[i] = dp[i-1] + dp[i-2]
let count = dfs(i - 1, mem) + dfs(i - 2, mem);
// 记录 dp[i]
mem[i] = count;
count
}
/* 爬楼梯:记忆化搜索 */
fn climbing_stairs_dfs_mem(n: usize) -> i32 {
// mem[i] 记录爬到第 i 阶的方案总数,-1 代表无记录
let mut mem = vec![-1; n + 1];
dfs(n, &mut mem)
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_dfs_mem(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}
/*
* File: climbing_stairs_dfs_mem.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 记忆化搜索 */
fn dfs(i: usize, mem: &mut [i32]) -> i32 {
// 已知 dp[1] 和 dp[2] ,返回之
if i == 1 || i == 2 {
return i as i32;
}
// 若存在记录 dp[i] ,则直接返回之
if mem[i] != -1 {
return mem[i];
}
// dp[i] = dp[i-1] + dp[i-2]
let count = dfs(i - 1, mem) + dfs(i - 2, mem);
// 记录 dp[i]
mem[i] = count;
count
}
/* 爬楼梯:记忆化搜索 */
fn climbing_stairs_dfs_mem(n: usize) -> i32 {
// mem[i] 记录爬到第 i 阶的方案总数,-1 代表无记录
let mut mem = vec![-1; n + 1];
dfs(n, &mut mem)
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_dfs_mem(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}

View File

@@ -1,44 +1,48 @@
/*
* File: climbing_stairs_dp.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 爬楼梯:动态规划 */
fn climbing_stairs_dp(n: usize) -> i32 {
// 已知 dp[1] 和 dp[2] ,返回之
if n == 1 || n == 2 { return n as i32; }
// 初始化 dp 表,用于存储子问题的解
let mut dp = vec![-1; n + 1];
// 初始状态:预设最小子问题的解
dp[1] = 1;
dp[2] = 2;
// 状态转移:从较小子问题逐步求解较大子问题
for i in 3..=n {
dp[i] = dp[i - 1] + dp[i - 2];
}
dp[n]
}
/* 爬楼梯:空间优化后的动态规划 */
fn climbing_stairs_dp_comp(n: usize) -> i32 {
if n == 1 || n == 2 { return n as i32; }
let (mut a, mut b) = (1, 2);
for _ in 3..=n {
let tmp = b;
b = a + b;
a = tmp;
}
b
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_dp(n);
println!("{n} 阶楼梯共有 {res} 种方案");
let res = climbing_stairs_dp_comp(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}
/*
* File: climbing_stairs_dp.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
/* 爬楼梯:动态规划 */
fn climbing_stairs_dp(n: usize) -> i32 {
// 已知 dp[1] 和 dp[2] ,返回之
if n == 1 || n == 2 {
return n as i32;
}
// 初始化 dp 表,用于存储子问题的解
let mut dp = vec![-1; n + 1];
// 初始状态:预设最小子问题的解
dp[1] = 1;
dp[2] = 2;
// 状态转移:从较小子问题逐步求解较大子问题
for i in 3..=n {
dp[i] = dp[i - 1] + dp[i - 2];
}
dp[n]
}
/* 爬楼梯:空间优化后的动态规划 */
fn climbing_stairs_dp_comp(n: usize) -> i32 {
if n == 1 || n == 2 {
return n as i32;
}
let (mut a, mut b) = (1, 2);
for _ in 3..=n {
let tmp = b;
b = a + b;
a = tmp;
}
b
}
/* Driver Code */
pub fn main() {
let n: usize = 9;
let res = climbing_stairs_dp(n);
println!("{n} 阶楼梯共有 {res} 种方案");
let res = climbing_stairs_dp_comp(n);
println!("{n} 阶楼梯共有 {res} 种方案");
}

View File

@@ -11,7 +11,7 @@ fn coin_change_dp(coins: &[i32], amt: usize) -> i32 {
// 初始化 dp 表
let mut dp = vec![vec![0; amt + 1]; n + 1];
// 状态转移:首行首列
for a in 1..= amt {
for a in 1..=amt {
dp[0][a] = max;
}
// 状态转移:其余行和列
@@ -26,7 +26,11 @@ fn coin_change_dp(coins: &[i32], amt: usize) -> i32 {
}
}
}
if dp[n][amt] != max { return dp[n][amt] as i32; } else { -1 }
if dp[n][amt] != max {
return dp[n][amt] as i32;
} else {
-1
}
}
/* 零钱兑换:空间优化后的动态规划 */
@@ -49,12 +53,16 @@ fn coin_change_dp_comp(coins: &[i32], amt: usize) -> i32 {
}
}
}
if dp[amt] != max { return dp[amt] as i32; } else { -1 }
if dp[amt] != max {
return dp[amt] as i32;
} else {
-1
}
}
/* Driver Code */
pub fn main() {
let coins = [ 1, 2, 5 ];
let coins = [1, 2, 5];
let amt: usize = 4;
// 动态规划

View File

@@ -10,7 +10,7 @@ fn coin_change_ii_dp(coins: &[i32], amt: usize) -> i32 {
// 初始化 dp 表
let mut dp = vec![vec![0; amt + 1]; n + 1];
// 初始化首列
for i in 0..= n {
for i in 0..=n {
dp[i][0] = 1;
}
// 状态转移
@@ -51,7 +51,7 @@ fn coin_change_ii_dp_comp(coins: &[i32], amt: usize) -> i32 {
/* Driver Code */
pub fn main() {
let coins = [ 1, 2, 5 ];
let coins = [1, 2, 5];
let amt: usize = 5;
// 动态规划

View File

@@ -7,11 +7,17 @@
/* 编辑距离:暴力搜索 */
fn edit_distance_dfs(s: &str, t: &str, i: usize, j: usize) -> i32 {
// 若 s 和 t 都为空,则返回 0
if i == 0 && j == 0 { return 0; }
if i == 0 && j == 0 {
return 0;
}
// 若 s 为空,则返回 t 长度
if i == 0 { return j as i32; }
if i == 0 {
return j as i32;
}
// 若 t 为空,则返回 s 长度
if j == 0 {return i as i32; }
if j == 0 {
return i as i32;
}
// 若两字符相等,则直接跳过此两字符
if s.chars().nth(i - 1) == t.chars().nth(j - 1) {
return edit_distance_dfs(s, t, i - 1, j - 1);
@@ -27,13 +33,21 @@ fn edit_distance_dfs(s: &str, t: &str, i: usize, j: usize) -> i32 {
/* 编辑距离:记忆化搜索 */
fn edit_distance_dfs_mem(s: &str, t: &str, mem: &mut Vec<Vec<i32>>, i: usize, j: usize) -> i32 {
// 若 s 和 t 都为空,则返回 0
if i == 0 && j == 0 { return 0; }
if i == 0 && j == 0 {
return 0;
}
// 若 s 为空,则返回 t 长度
if i == 0 { return j as i32; }
if i == 0 {
return j as i32;
}
// 若 t 为空,则返回 s 长度
if j == 0 {return i as i32; }
if j == 0 {
return i as i32;
}
// 若已有记录,则直接返回之
if mem[i][j] != -1 { return mem[i][j]; }
if mem[i][j] != -1 {
return mem[i][j];
}
// 若两字符相等,则直接跳过此两字符
if s.chars().nth(i - 1) == t.chars().nth(j - 1) {
return edit_distance_dfs_mem(s, t, mem, i - 1, j - 1);
@@ -52,7 +66,7 @@ fn edit_distance_dp(s: &str, t: &str) -> i32 {
let (n, m) = (s.len(), t.len());
let mut dp = vec![vec![0; m + 1]; n + 1];
// 状态转移:首行首列
for i in 1..= n {
for i in 1..=n {
dp[i][0] = i as i32;
}
for j in 1..m {
@@ -66,7 +80,8 @@ fn edit_distance_dp(s: &str, t: &str) -> i32 {
dp[i][j] = dp[i - 1][j - 1];
} else {
// 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1
dp[i][j] = std::cmp::min(std::cmp::min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
dp[i][j] =
std::cmp::min(std::cmp::min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
}
}
}

View File

@@ -56,7 +56,10 @@ fn knapsack_dp(wgt: &[i32], val: &[i32], cap: usize) -> i32 {
dp[i][c] = dp[i - 1][c];
} else {
// 不选和选物品 i 这两种方案的较大值
dp[i][c] = std::cmp::max(dp[i - 1][c], dp[i - 1][c - wgt[i - 1] as usize] + val[i - 1]);
dp[i][c] = std::cmp::max(
dp[i - 1][c],
dp[i - 1][c - wgt[i - 1] as usize] + val[i - 1],
);
}
}
}
@@ -83,8 +86,8 @@ fn knapsack_dp_comp(wgt: &[i32], val: &[i32], cap: usize) -> i32 {
/* Driver Code */
pub fn main() {
let wgt = [ 10, 20, 30, 40, 50 ];
let val = [ 50, 120, 150, 210, 240 ];
let wgt = [10, 20, 30, 40, 50];
let val = [50, 120, 150, 210, 240];
let cap: usize = 50;
let n = wgt.len();

View File

@@ -1,48 +1,52 @@
/*
* File: min_cost_climbing_stairs_dp.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
use std::cmp;
/* 爬楼梯最小代价:动态规划 */
fn min_cost_climbing_stairs_dp(cost: &[i32]) -> i32 {
let n = cost.len() - 1;
if n == 1 || n == 2 { return cost[n]; }
// 初始化 dp 表,用于存储子问题的解
let mut dp = vec![-1; n + 1];
// 初始状态:预设最小子问题的解
dp[1] = cost[1];
dp[2] = cost[2];
// 状态转移:从较小子问题逐步求解较大子问题
for i in 3..=n {
dp[i] = cmp::min(dp[i - 1], dp[i - 2]) + cost[i];
}
dp[n]
}
/* 爬楼梯最小代价:空间优化后的动态规划 */
fn min_cost_climbing_stairs_dp_comp(cost: &[i32]) -> i32 {
let n = cost.len() - 1;
if n == 1 || n == 2 { return cost[n] };
let (mut a, mut b) = (cost[1], cost[2]);
for i in 3..=n {
let tmp = b;
b = cmp::min(a, tmp) + cost[i];
a = tmp;
}
b
}
/* Driver Code */
pub fn main() {
let cost = [ 0, 1, 10, 1, 1, 1, 10, 1, 1, 10, 1 ];
println!("输入楼梯的代价列表为 {:?}", &cost);
let res = min_cost_climbing_stairs_dp(&cost);
println!("爬完楼梯的最低代价为 {res}");
let res = min_cost_climbing_stairs_dp_comp(&cost);
println!("爬完楼梯的最低代价为 {res}");
}
/*
* File: min_cost_climbing_stairs_dp.rs
* Created Time: 2023-07-09
* Author: codingonion (coderonion@gmail.com)
*/
use std::cmp;
/* 爬楼梯最小代价:动态规划 */
fn min_cost_climbing_stairs_dp(cost: &[i32]) -> i32 {
let n = cost.len() - 1;
if n == 1 || n == 2 {
return cost[n];
}
// 初始化 dp 表,用于存储子问题的解
let mut dp = vec![-1; n + 1];
// 初始状态:预设最小子问题的解
dp[1] = cost[1];
dp[2] = cost[2];
// 状态转移:从较小子问题逐步求解较大子问题
for i in 3..=n {
dp[i] = cmp::min(dp[i - 1], dp[i - 2]) + cost[i];
}
dp[n]
}
/* 爬楼梯最小代价:空间优化后的动态规划 */
fn min_cost_climbing_stairs_dp_comp(cost: &[i32]) -> i32 {
let n = cost.len() - 1;
if n == 1 || n == 2 {
return cost[n];
};
let (mut a, mut b) = (cost[1], cost[2]);
for i in 3..=n {
let tmp = b;
b = cmp::min(a, tmp) + cost[i];
a = tmp;
}
b
}
/* Driver Code */
pub fn main() {
let cost = [0, 1, 10, 1, 1, 1, 10, 1, 1, 10, 1];
println!("输入楼梯的代价列表为 {:?}", &cost);
let res = min_cost_climbing_stairs_dp(&cost);
println!("爬完楼梯的最低代价为 {res}");
let res = min_cost_climbing_stairs_dp_comp(&cost);
println!("爬完楼梯的最低代价为 {res}");
}

View File

@@ -91,10 +91,11 @@ fn min_path_sum_dp_comp(grid: &Vec<Vec<i32>>) -> i32 {
/* Driver Code */
pub fn main() {
let grid = vec![
vec![ 1, 3, 1, 5 ],
vec![ 2, 2, 4, 2 ],
vec![ 5, 3, 2, 1 ],
vec![ 4, 3, 5, 2 ]];
vec![1, 3, 1, 5],
vec![2, 2, 4, 2],
vec![5, 3, 2, 1],
vec![4, 3, 5, 2],
];
let (n, m) = (grid.len(), grid[0].len());
// 暴力搜索

View File

@@ -46,8 +46,8 @@ fn unbounded_knapsack_dp_comp(wgt: &[i32], val: &[i32], cap: usize) -> i32 {
/* Driver Code */
pub fn main() {
let wgt = [ 1, 2, 3 ];
let val = [ 5, 11, 15 ];
let wgt = [1, 2, 3];
let val = [5, 11, 15];
let cap: usize = 4;
// 动态规划

View File

@@ -6,9 +6,9 @@
mod graph_adjacency_list;
use std::collections::{HashSet, VecDeque};
use graph_adjacency_list::GraphAdjList;
use graph_adjacency_list::{Vertex, vets_to_vals, vals_to_vets};
use graph_adjacency_list::{vals_to_vets, vets_to_vals, Vertex};
use std::collections::{HashSet, VecDeque};
/* 广度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
@@ -25,7 +25,8 @@ fn graph_bfs(graph: GraphAdjList, start_vet: Vertex) -> Vec<Vertex> {
while !que.is_empty() {
let vet = que.pop_front().unwrap(); // 队首顶点出队
res.push(vet); // 记录访问顶点
// 遍历该顶点的所有邻接顶点
// 遍历该顶点的所有邻接顶点
if let Some(adj_vets) = graph.adj_list.get(&vet) {
for &adj_vet in adj_vets {
if visited.contains(&adj_vet) {

View File

@@ -6,9 +6,9 @@
mod graph_adjacency_list;
use std::collections::HashSet;
use graph_adjacency_list::GraphAdjList;
use graph_adjacency_list::{Vertex, vets_to_vals, vals_to_vets};
use graph_adjacency_list::{vals_to_vets, vets_to_vals, Vertex};
use std::collections::HashSet;
/* 深度优先遍历辅助函数 */
fn dfs(graph: &GraphAdjList, visited: &mut HashSet<Vertex>, res: &mut Vec<Vertex>, vet: Vertex) {

View File

@@ -12,13 +12,15 @@ pub struct Pair {
}
/* 基于数组实现的哈希表 */
pub struct ArrayHashMap {
buckets: Vec<Option<Pair>>
buckets: Vec<Option<Pair>>,
}
impl ArrayHashMap {
pub fn new() -> ArrayHashMap {
// 初始化数组,包含 100 个桶
Self { buckets: vec![None; 100] }
Self {
buckets: vec![None; 100],
}
}
/* 哈希函数 */
@@ -50,17 +52,26 @@ impl ArrayHashMap {
/* 获取所有键值对 */
pub fn entry_set(&self) -> Vec<&Pair> {
self.buckets.iter().filter_map(|pair| pair.as_ref()).collect()
self.buckets
.iter()
.filter_map(|pair| pair.as_ref())
.collect()
}
/* 获取所有键 */
pub fn key_set(&self) -> Vec<&i32> {
self.buckets.iter().filter_map(|pair| pair.as_ref().map(|pair| &pair.key)).collect()
self.buckets
.iter()
.filter_map(|pair| pair.as_ref().map(|pair| &pair.key))
.collect()
}
/* 获取所有值 */
pub fn value_set(&self) -> Vec<&String> {
self.buckets.iter().filter_map(|pair| pair.as_ref().map(|pair| &pair.val)).collect()
self.buckets
.iter()
.filter_map(|pair| pair.as_ref().map(|pair| &pair.val))
.collect()
}
/* 打印哈希表 */

View File

@@ -151,10 +151,13 @@ pub fn main() {
/* 查询操作 */
// 向哈希表中输入键 key ,得到值 value
println!("\n输入学号 13276,查询到姓名 {}", match map.get(13276) {
Some(value) => value,
None => "Not a valid Key"
});
println!(
"\n输入学号 13276,查询到姓名 {}",
match map.get(13276) {
Some(value) => value,
None => "Not a valid Key",
}
);
/* 删除操作 */
// 在哈希表中删除键值对 (key, value)

View File

@@ -12,15 +12,14 @@ use array_hash_map::Pair;
/* 开放寻址哈希表 */
struct HashMapOpenAddressing {
size: usize, // 键值对数量
capacity: usize, // 哈希表容量
load_thres: f64, // 触发扩容的负载因子阈值
extend_ratio: usize, // 扩容倍数
buckets: Vec<Option<Pair>>, // 桶数组
TOMBSTONE: Option<Pair>, // 删除标记
size: usize, // 键值对数量
capacity: usize, // 哈希表容量
load_thres: f64, // 触发扩容的负载因子阈值
extend_ratio: usize, // 扩容倍数
buckets: Vec<Option<Pair>>, // 桶数组
TOMBSTONE: Option<Pair>, // 删除标记
}
impl HashMapOpenAddressing {
/* 构造方法 */
fn new() -> Self {
@@ -30,7 +29,10 @@ impl HashMapOpenAddressing {
load_thres: 2.0 / 3.0,
extend_ratio: 2,
buckets: vec![None; 4],
TOMBSTONE: Some(Pair {key: -1, val: "-1".to_string()}),
TOMBSTONE: Some(Pair {
key: -1,
val: "-1".to_string(),
}),
}
}
@@ -56,9 +58,9 @@ impl HashMapOpenAddressing {
if first_tombstone != -1 {
self.buckets[first_tombstone as usize] = self.buckets[index].take();
self.buckets[index] = self.TOMBSTONE.clone();
return first_tombstone as usize; // 返回移动后的桶索引
return first_tombstone as usize; // 返回移动后的桶索引
}
return index; // 返回桶索引
return index; // 返回桶索引
}
// 记录遇到的首个删除标记
if first_tombstone == -1 && self.buckets[index] == self.TOMBSTONE {
@@ -68,7 +70,11 @@ impl HashMapOpenAddressing {
index = (index + 1) % self.capacity;
}
// 若 key 不存在,则返回添加点的索引
if first_tombstone == -1 { index } else { first_tombstone as usize }
if first_tombstone == -1 {
index
} else {
first_tombstone as usize
}
}
/* 查询操作 */

View File

@@ -4,7 +4,6 @@
* Author: night-cruise (2586447362@qq.com)
*/
/* 加法哈希 */
fn add_hash(key: &str) -> i32 {
let mut hash = 0_i64;
@@ -15,7 +14,7 @@ fn add_hash(key: &str) -> i32 {
}
hash as i32
}
}
/* 乘法哈希 */
fn mul_hash(key: &str) -> i32 {
@@ -68,4 +67,4 @@ fn main() {
let hash = rot_hash(key);
println!("旋转哈希值为 {hash}");
}
}

View File

@@ -162,4 +162,4 @@ fn main() {
/* 判断堆是否为空 */
let is_empty = max_heap.is_empty();
println!("\n堆是否为空 {}", is_empty);
}
}

View File

@@ -36,4 +36,4 @@ fn main() {
let res = top_k_heap(nums, k);
println!("最大的 {} 个元素为", k);
print_util::print_heap(res.into_iter().map(|item| item.0).collect());
}
}

View File

@@ -11,14 +11,17 @@ fn binary_search(nums: &[i32], target: i32) -> i32 {
let mut j = nums.len() as i32 - 1;
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
while i <= j {
let m = i + (j - i) / 2; // 计算中点索引 m
if nums[m as usize] < target { // 此情况说明 target 在区间 [m+1, j] 中
let m = i + (j - i) / 2; // 计算中点索引 m
if nums[m as usize] < target {
// 此情况说明 target 在区间 [m+1, j] 中
i = m + 1;
} else if nums[m as usize] > target { // 此情况说明 target 在区间 [i, m-1] 中
} else if nums[m as usize] > target {
// 此情况说明 target 在区间 [i, m-1] 中
j = m - 1;
} else { // 找到目标元素,返回其索引
} else {
// 找到目标元素,返回其索引
return m;
}
}
}
// 未找到目标元素,返回 -1
return -1;
@@ -31,14 +34,17 @@ fn binary_search_lcro(nums: &[i32], target: i32) -> i32 {
let mut j = nums.len() as i32;
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
while i < j {
let m = i + (j - i) / 2; // 计算中点索引 m
if nums[m as usize] < target { // 此情况说明 target 在区间 [m+1, j) 中
let m = i + (j - i) / 2; // 计算中点索引 m
if nums[m as usize] < target {
// 此情况说明 target 在区间 [m+1, j) 中
i = m + 1;
} else if nums[m as usize] > target { // 此情况说明 target 在区间 [i, m) 中
} else if nums[m as usize] > target {
// 此情况说明 target 在区间 [i, m) 中
j = m;
} else { // 找到目标元素,返回其索引
} else {
// 找到目标元素,返回其索引
return m;
}
}
}
// 未找到目标元素,返回 -1
return -1;
@@ -47,8 +53,8 @@ fn binary_search_lcro(nums: &[i32], target: i32) -> i32 {
/* Driver Code */
pub fn main() {
let target = 6;
let nums = [ 1, 3, 6, 8, 12, 15, 23, 26, 31, 35 ];
let nums = [1, 3, 6, 8, 12, 15, 23, 26, 31, 35];
// 二分查找(双闭区间)
let mut index = binary_search(&nums, target);
println!("目标元素 6 的索引 = {index}");

View File

@@ -8,7 +8,6 @@ mod binary_search_insertion;
use binary_search_insertion::binary_search_insertion;
/* 二分查找最左一个 target */
fn binary_search_left_edge(nums: &[i32], target: i32) -> i32 {
// 等价于查找 target 的插入点
@@ -48,4 +47,4 @@ fn main() {
let index = binary_search_right_edge(&nums, target);
println!("最右一个元素 {} 的索引为 {}", target, index);
}
}
}

View File

@@ -7,13 +7,13 @@
/* 二分查找插入点(无重复元素) */
fn binary_search_insertion_simple(nums: &[i32], target: i32) -> i32 {
let (mut i, mut j) = (0, nums.len() as i32 - 1); // 初始化双闭区间 [0, n-1]
let (mut i, mut j) = (0, nums.len() as i32 - 1); // 初始化双闭区间 [0, n-1]
while i <= j {
let m = i + (j - i) / 2; // 计算中点索引 m
let m = i + (j - i) / 2; // 计算中点索引 m
if nums[m as usize] < target {
i = m + 1; // target 在区间 [m+1, j] 中
i = m + 1; // target 在区间 [m+1, j] 中
} else if nums[m as usize] > target {
j = m - 1; // target 在区间 [i, m-1] 中
j = m - 1; // target 在区间 [i, m-1] 中
} else {
return m;
}
@@ -24,22 +24,21 @@ fn binary_search_insertion_simple(nums: &[i32], target: i32) -> i32 {
/* 二分查找插入点(存在重复元素) */
pub fn binary_search_insertion(nums: &[i32], target: i32) -> i32 {
let (mut i, mut j) = (0, nums.len() as i32 - 1); // 初始化双闭区间 [0, n-1]
let (mut i, mut j) = (0, nums.len() as i32 - 1); // 初始化双闭区间 [0, n-1]
while i <= j {
let m = i + (j - i) / 2; // 计算中点索引 m
let m = i + (j - i) / 2; // 计算中点索引 m
if nums[m as usize] < target {
i = m + 1; // target 在区间 [m+1, j] 中
i = m + 1; // target 在区间 [m+1, j] 中
} else if nums[m as usize] > target {
j = m - 1; // target 在区间 [i, m-1] 中
j = m - 1; // target 在区间 [i, m-1] 中
} else {
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
}
}
// 返回插入点 i
i
}
/* Driver Code */
fn main() {
// 无重复元素的数组
@@ -59,4 +58,4 @@ fn main() {
let index = binary_search_insertion(&nums, target);
println!("元素 {} 的插入点的索引为 {}", target, index);
}
}
}

View File

@@ -6,10 +6,10 @@
include!("../include/include.rs");
use list_node::ListNode;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use list_node::ListNode;
/* 哈希查找(数组) */
fn hashing_search_array<'a>(map: &'a HashMap<i32, usize>, target: i32) -> Option<&'a usize> {
@@ -19,7 +19,10 @@ fn hashing_search_array<'a>(map: &'a HashMap<i32, usize>, target: i32) -> Option
}
/* 哈希查找(链表) */
fn hashing_search_linked_list(map: &HashMap<i32, Rc<RefCell<ListNode<i32>>>>, target: i32) -> Option<&Rc<RefCell<ListNode<i32>>>> {
fn hashing_search_linked_list(
map: &HashMap<i32, Rc<RefCell<ListNode<i32>>>>,
target: i32,
) -> Option<&Rc<RefCell<ListNode<i32>>>> {
// 哈希表的 key: 目标节点值value: 节点对象
// 若哈希表中无此 key ,返回 None
map.get(&target)
@@ -30,7 +33,7 @@ pub fn main() {
let target = 3;
/* 哈希查找(数组) */
let nums = [ 1, 5, 3, 2, 4, 7, 5, 9, 10, 8 ];
let nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
// 初始化哈希表
let mut map = HashMap::new();
for (i, num) in nums.iter().enumerate() {

View File

@@ -6,9 +6,9 @@
include!("../include/include.rs");
use std::rc::Rc;
use std::cell::RefCell;
use list_node::ListNode;
use std::cell::RefCell;
use std::rc::Rc;
/* 线性查找(数组) */
fn linear_search_array(nums: &[i32], target: i32) -> i32 {
@@ -24,9 +24,14 @@ fn linear_search_array(nums: &[i32], target: i32) -> i32 {
}
/* 线性查找(链表) */
fn linear_search_linked_list(head: Rc<RefCell<ListNode<i32>>>, target: i32) -> Option<Rc<RefCell<ListNode<i32>>>> {
fn linear_search_linked_list(
head: Rc<RefCell<ListNode<i32>>>,
target: i32,
) -> Option<Rc<RefCell<ListNode<i32>>>> {
// 找到目标节点,返回之
if head.borrow().val == target {return Some(head)};
if head.borrow().val == target {
return Some(head);
};
// 找到目标节点,返回之
if let Some(node) = &head.borrow_mut().next {
return linear_search_linked_list(node.clone(), target);
@@ -40,7 +45,7 @@ pub fn main() {
let target = 3;
/* 在数组中执行线性查找 */
let nums = [ 1, 5, 3, 2, 4, 7, 5, 9, 10, 8 ];
let nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
let index = linear_search_array(&nums, target);
println!("目标元素 3 的索引 = {}", index);

View File

@@ -30,7 +30,7 @@ pub fn two_sum_hash_table(nums: &Vec<i32>, target: i32) -> Option<Vec<i32>> {
for (i, num) in nums.iter().enumerate() {
match dic.get(&(target - num)) {
Some(v) => return Some(vec![*v as i32, i as i32]),
None => dic.insert(num, i as i32)
None => dic.insert(num, i as i32),
};
}
None
@@ -38,7 +38,7 @@ pub fn two_sum_hash_table(nums: &Vec<i32>, target: i32) -> Option<Vec<i32>> {
fn main() {
// ======= Test Case =======
let nums = vec![ 2, 7, 11, 15 ];
let nums = vec![2, 7, 11, 15];
let target = 13;
// ====== Driver Code ======

View File

@@ -10,7 +10,7 @@ include!("../include/include.rs");
fn bubble_sort(nums: &mut [i32]) {
// 外循环:未排序区间为 [0, i]
for i in (1..nums.len()).rev() {
// 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端
// 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端
for j in 0..i {
if nums[j] > nums[j + 1] {
// 交换 nums[j] 与 nums[j + 1]
@@ -27,29 +27,32 @@ fn bubble_sort_with_flag(nums: &mut [i32]) {
// 外循环:未排序区间为 [0, i]
for i in (1..nums.len()).rev() {
let mut flag = false; // 初始化标志位
// 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端
// 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端
for j in 0..i {
if nums[j] > nums[j + 1] {
// 交换 nums[j] 与 nums[j + 1]
let tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
flag = true; // 记录交换元素
flag = true; // 记录交换元素
}
}
if !flag {break}; // 此轮“冒泡”未交换任何元素,直接跳出
if !flag {
break; // 此轮“冒泡”未交换任何元素,直接跳出
};
}
}
/* Driver Code */
pub fn main() {
let mut nums = [ 4, 1, 3, 1, 5, 2 ];
let mut nums = [4, 1, 3, 1, 5, 2];
bubble_sort(&mut nums);
print!("冒泡排序完成后 nums = ");
print_util::print_array(&nums);
let mut nums1 = [ 4, 1, 3, 1, 5, 2 ];
let mut nums1 = [4, 1, 3, 1, 5, 2];
bubble_sort_with_flag(&mut nums1);
print!("\n冒泡排序完成后 nums1 = ");
print_util::print_array(&nums1);
}
}

View File

@@ -40,4 +40,4 @@ fn main() {
bucket_sort(&mut nums);
print!("桶排序完成后 nums = ");
print_util::print_array(&nums);
}
}

View File

@@ -69,4 +69,4 @@ fn main() {
counting_sort(&mut nums1);
print!("\n计数排序完成后 nums1 = ");
print_util::print_array(&nums1);
}
}

View File

@@ -55,4 +55,4 @@ fn main() {
heap_sort(&mut nums);
print!("堆排序完成后 nums = ");
print_util::print_array(&nums);
}
}

View File

@@ -10,13 +10,13 @@ include!("../include/include.rs");
fn insertion_sort(nums: &mut [i32]) {
// 外循环:已排序区间为 [0, i-1]
for i in 1..nums.len() {
let (base, mut j) = (nums[i], (i - 1) as i32);
let (base, mut j) = (nums[i], (i - 1) as i32);
// 内循环:将 base 插入到已排序区间 [0, i-1] 中的正确位置
while j >= 0 && nums[j as usize] > base {
nums[(j + 1) as usize] = nums[j as usize]; // 将 nums[j] 向右移动一位
j -= 1;
}
nums[(j + 1) as usize] = base; // 将 base 赋值到正确位置
nums[(j + 1) as usize] = base; // 将 base 赋值到正确位置
}
}
@@ -26,4 +26,4 @@ fn main() {
insertion_sort(&mut nums);
print!("插入排序完成后 nums = ");
print_util::print_array(&nums);
}
}

View File

@@ -43,11 +43,15 @@ fn merge(nums: &mut [i32], left: usize, mid: usize, right: usize) {
/* 归并排序 */
fn merge_sort(nums: &mut [i32], left: usize, right: usize) {
// 终止条件
if left >= right { return; } // 当子数组长度为 1 时终止递归
if left >= right {
return; // 当子数组长度为 1 时终止递归
}
// 划分阶段
let mid = (left + right) / 2; // 计算中点
merge_sort(nums, left, mid); // 递归左子数组
merge_sort(nums, mid + 1, right); // 递归右子数组
let mid = (left + right) / 2; // 计算中点
merge_sort(nums, left, mid); // 递归左子数组
merge_sort(nums, mid + 1, right); // 递归右子数组
// 合并阶段
merge(nums, left, mid, right);
}
@@ -59,4 +63,4 @@ fn main() {
let right = nums.len() - 1;
merge_sort(&mut nums, 0, right);
println!("归并排序完成后 nums = {:?}", nums);
}
}

View File

@@ -4,7 +4,6 @@
* Author: xBLACKICEx (xBLACKICE@outlook.com)
*/
/* 快速排序 */
struct QuickSort;
@@ -15,15 +14,15 @@ impl QuickSort {
let (mut i, mut j) = (left, right);
while i < j {
while i < j && nums[j] >= nums[left] {
j -= 1; // 从右向左找首个小于基准数的元素
j -= 1; // 从右向左找首个小于基准数的元素
}
while i < j && nums[i] <= nums[left] {
i += 1; // 从左向右找首个大于基准数的元素
i += 1; // 从左向右找首个大于基准数的元素
}
nums.swap(i, j); // 交换这两个元素
}
nums.swap(i, left); // 将基准数交换至两子数组的分界线
i // 返回基准数的索引
nums.swap(i, left); // 将基准数交换至两子数组的分界线
i // 返回基准数的索引
}
/* 快速排序 */
@@ -66,15 +65,15 @@ impl QuickSortMedian {
let (mut i, mut j) = (left, right);
while i < j {
while i < j && nums[j] >= nums[left] {
j -= 1; // 从右向左找首个小于基准数的元素
j -= 1; // 从右向左找首个小于基准数的元素
}
while i < j && nums[i] <= nums[left] {
i += 1; // 从左向右找首个大于基准数的元素
i += 1; // 从左向右找首个大于基准数的元素
}
nums.swap(i, j); // 交换这两个元素
}
nums.swap(i, left); // 将基准数交换至两子数组的分界线
i // 返回基准数的索引
nums.swap(i, left); // 将基准数交换至两子数组的分界线
i // 返回基准数的索引
}
/* 快速排序 */
@@ -101,15 +100,15 @@ impl QuickSortTailCall {
let (mut i, mut j) = (left, right);
while i < j {
while i < j && nums[j] >= nums[left] {
j -= 1; // 从右向左找首个小于基准数的元素
j -= 1; // 从右向左找首个小于基准数的元素
}
while i < j && nums[i] <= nums[left] {
i += 1; // 从左向右找首个大于基准数的元素
i += 1; // 从左向右找首个大于基准数的元素
}
nums.swap(i, j); // 交换这两个元素
}
nums.swap(i, left); // 将基准数交换至两子数组的分界线
i // 返回基准数的索引
nums.swap(i, left); // 将基准数交换至两子数组的分界线
i // 返回基准数的索引
}
/* 快速排序(尾递归优化) */
@@ -119,9 +118,9 @@ impl QuickSortTailCall {
// 哨兵划分操作
let pivot = Self::partition(nums, left as usize, right as usize) as i32;
// 对两个子数组中较短的那个执行快速排序
if pivot - left < right - pivot {
Self::quick_sort(left, pivot - 1, nums); // 递归排序左子数组
left = pivot + 1; // 剩余未排序区间为 [pivot + 1, right]
if pivot - left < right - pivot {
Self::quick_sort(left, pivot - 1, nums); // 递归排序左子数组
left = pivot + 1; // 剩余未排序区间为 [pivot + 1, right]
} else {
Self::quick_sort(pivot + 1, right, nums); // 递归排序右子数组
right = pivot - 1; // 剩余未排序区间为 [left, pivot - 1]

View File

@@ -62,4 +62,4 @@ fn main() {
radix_sort(&mut nums);
print!("基数排序完成后 nums = ");
print_util::print_array(&nums);
}
}

View File

@@ -13,10 +13,10 @@ fn selection_sort(nums: &mut [i32]) {
}
let n = nums.len();
// 外循环:未排序区间为 [i, n-1]
for i in 0..n-1 {
for i in 0..n - 1 {
// 内循环:找到未排序区间内的最小元素
let mut k = i;
for j in i+1..n {
for j in i + 1..n {
if nums[j] < nums[k] {
k = j; // 记录最小元素的索引
}
@@ -32,4 +32,4 @@ pub fn main() {
selection_sort(&mut nums);
print!("\n选择排序完成后 nums = ");
print_util::print_array(&nums);
}
}

View File

@@ -8,9 +8,9 @@ include!("../include/include.rs");
/* 基于环形数组实现的双向队列 */
struct ArrayDeque {
nums: Vec<i32>, // 用于存储双向队列元素的数组
front: usize, // 队首指针,指向队首元素
que_size: usize, // 双向队列长度
nums: Vec<i32>, // 用于存储双向队列元素的数组
front: usize, // 队首指针,指向队首元素
que_size: usize, // 双向队列长度
}
impl ArrayDeque {
@@ -50,7 +50,7 @@ impl ArrayDeque {
pub fn push_first(&mut self, num: i32) {
if self.que_size == self.capacity() {
println!("双向队列已满");
return
return;
}
// 队首指针向左移动一位
// 通过取余操作实现 front 越过数组头部后回到尾部
@@ -64,7 +64,7 @@ impl ArrayDeque {
pub fn push_last(&mut self, num: i32) {
if self.que_size == self.capacity() {
println!("双向队列已满");
return
return;
}
// 计算队尾指针,指向队尾索引 + 1
let rear = self.index(self.front as i32 + self.que_size as i32);
@@ -91,18 +91,22 @@ impl ArrayDeque {
/* 访问队首元素 */
fn peek_first(&self) -> i32 {
if self.is_empty() { panic!("双向队列为空") };
if self.is_empty() {
panic!("双向队列为空")
};
self.nums[self.front]
}
/* 访问队尾元素 */
fn peek_last(&self) -> i32 {
if self.is_empty() { panic!("双向队列为空") };
if self.is_empty() {
panic!("双向队列为空")
};
// 计算尾元素索引
let last = self.index(self.front as i32 + self.que_size as i32 - 1);
self.nums[last]
}
/* 返回数组用于打印 */
fn to_array(&self) -> Vec<i32> {
// 仅转换有效长度范围内的列表元素
@@ -146,7 +150,7 @@ fn main() {
print_util::print_array(&deque.to_array());
let pop_first = deque.pop_first();
print!("\n队首出队元素 = {},队首出队后 deque = ", pop_first);
print_util::print_array(&deque.to_array());
print_util::print_array(&deque.to_array());
/* 获取双向队列的长度 */
let size = deque.size();

View File

@@ -6,10 +6,10 @@
/* 基于环形数组实现的队列 */
struct ArrayQueue {
nums: Vec<i32>, // 用于存储队列元素的数组
front: i32, // 队首指针,指向队首元素
que_size: i32, // 队列长度
que_capacity: i32, // 队列容量
nums: Vec<i32>, // 用于存储队列元素的数组
front: i32, // 队首指针,指向队首元素
que_size: i32, // 队列长度
que_capacity: i32, // 队列容量
}
impl ArrayQueue {

View File

@@ -14,7 +14,9 @@ struct ArrayStack<T> {
impl<T> ArrayStack<T> {
/* 初始化栈 */
fn new() -> ArrayStack<T> {
ArrayStack::<T> { stack: Vec::<T>::new() }
ArrayStack::<T> {
stack: Vec::<T>::new(),
}
}
/* 获取栈的长度 */
@@ -42,7 +44,9 @@ impl<T> ArrayStack<T> {
/* 访问栈顶元素 */
fn peek(&self) -> Option<&T> {
if self.is_empty() { panic!("栈为空") };
if self.is_empty() {
panic!("栈为空")
};
self.stack.last()
}
@@ -82,4 +86,4 @@ fn main() {
// 判断是否为空
let is_empty = stack.is_empty();
print!("\n栈是否为空 = {is_empty}");
}
}

View File

@@ -12,16 +12,16 @@ use std::collections::VecDeque;
pub fn main() {
// 初始化双向队列
let mut deque: VecDeque<i32> = VecDeque::new();
deque.push_back(3);
deque.push_back(3);
deque.push_back(2);
deque.push_back(5);
print!("双向队列 deque = ");
print_util::print_queue(&deque);
// 访问元素
let peek_first = deque.front().unwrap();
let peek_first = deque.front().unwrap();
print!("\n队首元素 peekFirst = {peek_first}");
let peek_last = deque.back().unwrap();
let peek_last = deque.back().unwrap();
print!("\n队尾元素 peekLast = {peek_last}");
/* 元素入队 */
@@ -47,4 +47,4 @@ pub fn main() {
// 判断双向队列是否为空
let is_empty = deque.is_empty();
print!("\n双向队列是否为空 = {is_empty}");
}
}

View File

@@ -6,8 +6,8 @@
include!("../include/include.rs");
use std::rc::Rc;
use std::cell::RefCell;
use std::rc::Rc;
/* 双向链表节点 */
pub struct ListNode<T> {
@@ -29,9 +29,9 @@ impl<T> ListNode<T> {
/* 基于双向链表实现的双向队列 */
#[allow(dead_code)]
pub struct LinkedListDeque<T> {
front: Option<Rc<RefCell<ListNode<T>>>>, // 头节点 front
rear: Option<Rc<RefCell<ListNode<T>>>>, // 尾节点 rear
que_size: usize, // 双向队列的长度
front: Option<Rc<RefCell<ListNode<T>>>>, // 头节点 front
rear: Option<Rc<RefCell<ListNode<T>>>>, // 尾节点 rear
que_size: usize, // 双向队列的长度
}
impl<T: Copy> LinkedListDeque<T> {
@@ -39,7 +39,7 @@ impl<T: Copy> LinkedListDeque<T> {
Self {
front: None,
rear: None,
que_size: 0,
que_size: 0,
}
}
@@ -71,7 +71,7 @@ impl<T: Copy> LinkedListDeque<T> {
self.front = Some(node); // 更新头节点
}
}
}
}
// 队尾入队操作
else {
match self.rear.take() {
@@ -104,8 +104,8 @@ impl<T: Copy> LinkedListDeque<T> {
/* 出队操作 */
pub fn pop(&mut self, is_front: bool) -> Option<T> {
// 若队列为空,直接返回 None
if self.is_empty() {
return None
if self.is_empty() {
return None;
};
// 队首出队操作
if is_front {
@@ -113,7 +113,7 @@ impl<T: Copy> LinkedListDeque<T> {
match old_front.borrow_mut().next.take() {
Some(new_front) => {
new_front.borrow_mut().prev.take();
self.front = Some(new_front); // 更新头节点
self.front = Some(new_front); // 更新头节点
}
None => {
self.rear.take();
@@ -122,15 +122,14 @@ impl<T: Copy> LinkedListDeque<T> {
self.que_size -= 1; // 更新队列长度
Rc::try_unwrap(old_front).ok().unwrap().into_inner().val
})
}
}
// 队尾出队操作
else {
self.rear.take().map(|old_rear| {
match old_rear.borrow_mut().prev.take() {
Some(new_rear) => {
new_rear.borrow_mut().next.take();
self.rear = Some(new_rear); // 更新尾节点
self.rear = Some(new_rear); // 更新尾节点
}
None => {
self.front.take();
@@ -203,7 +202,7 @@ fn main() {
print_util::print_array(&deque.to_array(deque.peek_first()));
let pop_first = deque.pop_first().unwrap();
print!("\n队首出队元素 = {},队首出队后 deque = ", pop_first);
print_util::print_array(&deque.to_array(deque.peek_first()));
print_util::print_array(&deque.to_array(deque.peek_first()));
/* 获取双向队列的长度 */
let size = deque.size();

View File

@@ -6,16 +6,16 @@
include!("../include/include.rs");
use std::rc::Rc;
use std::cell::RefCell;
use list_node::ListNode;
use std::cell::RefCell;
use std::rc::Rc;
/* 基于链表实现的队列 */
#[allow(dead_code)]
pub struct LinkedListQueue<T> {
front: Option<Rc<RefCell<ListNode<T>>>>, // 头节点 front
rear: Option<Rc<RefCell<ListNode<T>>>>, // 尾节点 rear
que_size: usize, // 队列的长度
front: Option<Rc<RefCell<ListNode<T>>>>, // 头节点 front
rear: Option<Rc<RefCell<ListNode<T>>>>, // 尾节点 rear
que_size: usize, // 队列的长度
}
impl<T: Copy> LinkedListQueue<T> {
@@ -23,7 +23,7 @@ impl<T: Copy> LinkedListQueue<T> {
Self {
front: None,
rear: None,
que_size: 0,
que_size: 0,
}
}
@@ -118,4 +118,4 @@ fn main() {
/* 判断队列是否为空 */
let is_empty = queue.is_empty();
print!("\n队列是否为空 = {}", is_empty);
}
}

View File

@@ -6,15 +6,15 @@
include!("../include/include.rs");
use std::rc::Rc;
use std::cell::RefCell;
use list_node::ListNode;
use std::cell::RefCell;
use std::rc::Rc;
/* 基于链表实现的栈 */
#[allow(dead_code)]
pub struct LinkedListStack<T> {
stack_peek: Option<Rc<RefCell<ListNode<T>>>>, // 将头节点作为栈顶
stk_size: usize, // 栈的长度
stack_peek: Option<Rc<RefCell<ListNode<T>>>>, // 将头节点作为栈顶
stk_size: usize, // 栈的长度
}
impl<T: Copy> LinkedListStack<T> {
@@ -105,4 +105,4 @@ fn main() {
/* 判断是否为空 */
let is_empty = stack.is_empty();
print!("\n栈是否为空 = {}", is_empty);
}
}

View File

@@ -38,4 +38,4 @@ pub fn main() {
// 判断队列是否为空
let is_empty = queue.is_empty();
print!("\n队列是否为空 = {is_empty}");
}
}

View File

@@ -37,4 +37,4 @@ pub fn main() {
// 判断栈是否为空
let is_empty = stack.is_empty();
print!("\n栈是否为空 = {is_empty}");
}
}

View File

@@ -196,4 +196,4 @@ fn main() {
println!("中序遍历为:{:?}", res);
res = abt.post_order();
println!("后序遍历为:{:?}", res);
}
}

View File

@@ -6,10 +6,10 @@
include!("../include/include.rs");
use tree_node::TreeNode;
use std::rc::Rc;
use std::cmp::Ordering;
use std::cell::RefCell;
use std::cmp::Ordering;
use std::rc::Rc;
use tree_node::TreeNode;
type OptionTreeNodeRc = Option<Rc<RefCell<TreeNode>>>;
@@ -157,6 +157,7 @@ impl AVLTree {
}
}
Self::update_height(Some(node.clone())); // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = Self::rotate(Some(node)).unwrap();
// 返回子树的根节点
@@ -211,6 +212,7 @@ impl AVLTree {
node.borrow_mut().val = temp.borrow().val;
}
Self::update_height(Some(node.clone())); // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = Self::rotate(Some(node)).unwrap();
// 返回子树的根节点

View File

@@ -7,8 +7,8 @@
include!("../include/include.rs");
use std::cell::RefCell;
use std::rc::Rc;
use std::cmp::Ordering;
use std::rc::Rc;
use tree_node::TreeNode;
@@ -89,8 +89,8 @@ impl BinarySearchTree {
/* 删除节点 */
pub fn remove(&mut self, num: i32) {
// 若树为空,直接提前返回
if self.root.is_none() {
return;
if self.root.is_none() {
return;
}
let mut cur = self.root.clone();
let mut pre = None;
@@ -171,7 +171,11 @@ fn main() {
/* 查找结点 */
let node = bst.search(7);
println!("\n查找到的节点对象为 {:?},节点值 = {}", node.clone().unwrap(), node.clone().unwrap().borrow().val);
println!(
"\n查找到的节点对象为 {:?},节点值 = {}",
node.clone().unwrap(),
node.clone().unwrap().borrow().val
);
/* 插入节点 */
bst.insert(16);

View File

@@ -3,7 +3,6 @@
* Created Time: 2023-02-27
* Author: xBLACKICEx (xBLACKICE@outlook.com)
*/
use std::rc::Rc;
include!("../include/include.rs");
use tree_node::TreeNode;
@@ -37,4 +36,4 @@ fn main() {
n1.borrow_mut().left = Some(Rc::clone(&n2));
println!("\n删除节点 P 后\n");
print_util::print_tree(&n1);
}
}

View File

@@ -18,13 +18,14 @@ fn level_order(root: &Rc<RefCell<TreeNode>>) -> Vec<i32> {
// 初始化一个列表,用于保存遍历序列
let mut vec = Vec::new();
while let Some(node) = que.pop_front() { // 队列出队
vec.push(node.borrow().val); // 保存节点值
while let Some(node) = que.pop_front() {
// 队列出队
vec.push(node.borrow().val); // 保存节点值
if let Some(left) = node.borrow().left.as_ref() {
que.push_back(Rc::clone(left)); // 左子节点入队
que.push_back(Rc::clone(left)); // 左子节点入队
}
if let Some(right) = node.borrow().right.as_ref() {
que.push_back(Rc::clone(right)); // 右子节点入队
que.push_back(Rc::clone(right)); // 右子节点入队
};
}
vec

View File

@@ -68,4 +68,4 @@ fn main() {
/* 后序遍历 */
let vec = post_order(root.as_ref());
print!("\n后序遍历的节点打印序列 = {:?}", vec);
}
}