Skip to content

Commit 056e377

Browse files
author
Lee Johnson
committed
opencamp-cn#1. [Header部分只有一行,包括三个字段]:type(必需)、scope(必需)和subject(必需):
opencamp-cn#1.1 <type:commit类型>: 必填项, 指定commit类型:feature/fix/refactor/style(如格式化)/test/build/docs/revert(执行git revert) opencamp-cn#1.2 <scope1:(JIRA号)>: 对应的Epic/Story/Task等JIRA号, 没有则填"None" opencamp-cn#1.3 <scope2:[功能模块]>: 必填项, 填写本次改动的功能模块名, 如微服务中module名, 多级module需要填全路径,如paip-common/paip-common-core opencamp-cn#1.4 <subject:简述>: 必填项, 简述本次提交内容, 如实现了功能名/模块名, 可直接拷贝对应JIRA号的标题 opencamp-cn#2. [Body:详细描述]: 填写详细描述, 主要描述改动之前的情况及修改动机, 对于小的修改不作要求, 但是重大需求更新等必须添加 opencamp-cn#3. [Footer:BREAKING CHANGE]: 当前代码与上一个版本不兼容, 以BREAKING CHANGE开头, 后面是对变动的描述变动理由和迁移方法 feature: 根据注释要求,完成所有功能 [详细描述] #[BREAKING CHANGE]:
1 parent b704787 commit 056e377

30 files changed

Lines changed: 1097 additions & 104 deletions

exercises/easy/algorithm1.rs

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,42 @@ impl<T> LinkedList<T> {
6969
},
7070
}
7171
}
72-
pub fn merge(list_a:LinkedList<T>,list_b:LinkedList<T>) -> Self
72+
pub fn merge(list_a: LinkedList<T>, list_b: LinkedList<T>) -> Self
73+
where
74+
T: Ord,
7375
{
74-
//TODO
75-
Self {
76-
length: 0,
77-
start: None,
78-
end: None,
79-
}
76+
let mut merged = LinkedList::new();
77+
let mut current_a = list_a.start;
78+
let mut current_b = list_b.start;
79+
80+
// 同时遍历两个链表,比较并添加较小的节点
81+
while let (Some(ptr_a), Some(ptr_b)) = (current_a, current_b) {
82+
let node_a = unsafe { &*ptr_a.as_ptr() };
83+
let node_b = unsafe { &*ptr_b.as_ptr() };
84+
85+
if node_a.val <= node_b.val {
86+
merged.add(node_a.val);
87+
current_a = node_a.next;
88+
} else {
89+
merged.add(node_b.val);
90+
current_b = node_b.next;
91+
}
92+
}
93+
94+
// 处理剩余的节点
95+
while let Some(ptr_a) = current_a {
96+
let node_a = unsafe { &*ptr_a.as_ptr() };
97+
merged.add(node_a.val);
98+
current_a = node_a.next;
99+
}
100+
101+
while let Some(ptr_b) = current_b {
102+
let node_b = unsafe { &*ptr_b.as_ptr() };
103+
merged.add(node_b.val);
104+
current_b = node_b.next;
105+
}
106+
107+
merged
80108
}
81109
}
82110

@@ -104,6 +132,15 @@ where
104132
}
105133
}
106134

135+
impl<T> Drop for LinkedList<T> {
136+
fn drop(&mut self) {
137+
while let Some(node_ptr) = self.start {
138+
let node = unsafe { Box::from_raw(node_ptr.as_ptr()) };
139+
self.start = node.next;
140+
}
141+
}
142+
}
143+
107144
#[cfg(test)]
108145
mod tests {
109146
use super::LinkedList;

exercises/easy/algorithm10.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,36 @@ impl Graph for UndirectedGraph {
2929
&self.adjacency_table
3030
}
3131
fn add_edge(&mut self, edge: (&str, &str, i32)) {
32-
//TODO
32+
let (from, to, weight) = edge;
33+
34+
// 确保两个节点都存在
35+
self.add_node(from);
36+
self.add_node(to);
37+
38+
// 因为是无向图,需要添加双向边
39+
self.adjacency_table_mutable()
40+
.get_mut(from)
41+
.unwrap()
42+
.push((to.to_string(), weight));
43+
44+
self.adjacency_table_mutable()
45+
.get_mut(to)
46+
.unwrap()
47+
.push((from.to_string(), weight));
3348
}
3449
}
3550
pub trait Graph {
3651
fn new() -> Self;
3752
fn adjacency_table_mutable(&mut self) -> &mut HashMap<String, Vec<(String, i32)>>;
3853
fn adjacency_table(&self) -> &HashMap<String, Vec<(String, i32)>>;
3954
fn add_node(&mut self, node: &str) -> bool {
40-
//TODO
41-
true
42-
}
43-
fn add_edge(&mut self, edge: (&str, &str, i32)) {
44-
//TODO
55+
if self.contains(node) {
56+
return false;
57+
}
58+
self.adjacency_table_mutable().insert(node.to_string(), Vec::new());
59+
true
4560
}
61+
fn add_edge(&mut self, edge: (&str, &str, i32));
4662
fn contains(&self, node: &str) -> bool {
4763
self.adjacency_table().get(node).is_some()
4864
}

exercises/easy/algorithm11.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,16 @@
1414
use std::fmt::{self, Display, Formatter};
1515

1616
pub fn find_missing_number(nums: Vec<i32>) -> i32 {
17-
// TODO: Implement the logic to find the missing number
18-
0 // Placeholder return value
17+
let n = (nums.len() + 1) as i32; // 数组长度加1就是完整序列的长度
18+
19+
// 计算从1到n的理论总和
20+
let expected_sum = n * (n + 1) / 2;
21+
22+
// 计算实际数组的总和
23+
let actual_sum: i32 = nums.iter().sum();
24+
25+
// 理论总和减去实际总和就是缺失的数字
26+
expected_sum - actual_sum
1927
}
2028

2129
#[cfg(test)]

exercises/easy/algorithm12.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,31 @@
1212
use std::fmt::{self, Display, Formatter};
1313

1414
pub fn is_palindrome(s: String) -> bool {
15-
// TODO: Implement the logic to check if the string is a palindrome
16-
false // Placeholder return value
15+
// 将字符串转换为小写并只保留字母字符
16+
let chars: Vec<char> = s
17+
.to_lowercase()
18+
.chars()
19+
.filter(|c| c.is_alphabetic())
20+
.collect();
21+
22+
// 如果处理后的字符串为空,返回true
23+
if chars.is_empty() {
24+
return true;
25+
}
26+
27+
// 使用双指针从两端向中间比较
28+
let mut left = 0;
29+
let mut right = chars.len() - 1;
30+
31+
while left < right {
32+
if chars[left] != chars[right] {
33+
return false;
34+
}
35+
left += 1;
36+
right -= 1;
37+
}
38+
39+
true
1740
}
1841

1942
#[cfg(test)]

exercises/easy/algorithm13.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,30 @@
1414
use std::fmt::{self, Display, Formatter};
1515

1616
pub fn are_anagrams(s1: String, s2: String) -> bool {
17-
// TODO: Implement the logic to check if two strings are anagrams
18-
false // Placeholder return value
17+
// 将字符串转换为小写并只保留字母字符
18+
let mut chars1: Vec<char> = s1
19+
.to_lowercase()
20+
.chars()
21+
.filter(|c| c.is_alphabetic())
22+
.collect();
23+
24+
let mut chars2: Vec<char> = s2
25+
.to_lowercase()
26+
.chars()
27+
.filter(|c| c.is_alphabetic())
28+
.collect();
29+
30+
// 如果处理后的字符串长度不同,一定不是变位词
31+
if chars1.len() != chars2.len() {
32+
return false;
33+
}
34+
35+
// 对两个字符数组进行排序
36+
chars1.sort_unstable();
37+
chars2.sort_unstable();
38+
39+
// 比较排序后的字符数组是否相同
40+
chars1 == chars2
1941
}
2042

2143
#[cfg(test)]

exercises/easy/algorithm14.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,29 @@
1212
use std::fmt::{self, Display, Formatter};
1313

1414
pub fn find_duplicates(nums: Vec<i32>) -> Vec<i32> {
15-
// TODO: Implement the logic to find all duplicates in the array
16-
Vec::new() // Placeholder return value
15+
let mut nums = nums; // 获取数组的可变引用
16+
let mut result = Vec::new();
17+
18+
// 使用数组元素的正负号来标记是否出现过
19+
for i in 0..nums.len() {
20+
// 获取当前数字的绝对值作为索引(减1是因为数组索引从0开始)
21+
let index = nums[i].abs() as usize - 1;
22+
23+
// 如果对应位置的数字已经是负数,说明这个数字之前出现过
24+
if nums[index] < 0 {
25+
// 避免重复添加相同的数字
26+
if !result.contains(&(index as i32 + 1)) {
27+
result.push(index as i32 + 1);
28+
}
29+
} else {
30+
// 将对应位置的数字标记为负数,表示这个数字已经出现过
31+
nums[index] = -nums[index];
32+
}
33+
}
34+
35+
// 对结果进行排序,保证输出顺序一致
36+
result.sort_unstable();
37+
result
1738
}
1839

1940
#[cfg(test)]

exercises/easy/algorithm15.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,31 @@
1010
*/
1111

1212
use std::fmt::{self, Display, Formatter};
13+
use std::collections::HashMap;
1314

1415
pub fn longest_substring_without_repeating_chars(s: String) -> i32 {
15-
// TODO: Implement the logic to find the longest substring without repeating characters
16-
0 // Placeholder return value
16+
let chars: Vec<char> = s.chars().collect();
17+
let mut char_index = HashMap::new(); // 记录字符最后出现的位置
18+
let mut max_length = 0;
19+
let mut start = 0; // 滑动窗口的起始位置
20+
21+
for (end, &ch) in chars.iter().enumerate() {
22+
// 如果字符已经在当前窗口中出现过,更新窗口起始位置
23+
if let Some(&prev_index) = char_index.get(&ch) {
24+
// 只有当前窗口包含重复字符时才更新起始位置
25+
if prev_index >= start {
26+
start = prev_index + 1;
27+
}
28+
}
29+
30+
// 更新字符最后出现的位置
31+
char_index.insert(ch, end);
32+
33+
// 更新最大长度
34+
max_length = max_length.max(end - start + 1);
35+
}
36+
37+
max_length as i32
1738
}
1839

1940
#[cfg(test)]

exercises/easy/algorithm16.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,52 @@
1212
use std::fmt::{self, Display, Formatter};
1313

1414
pub fn rotate_matrix_90_degrees(matrix: &mut Vec<Vec<i32>>) {
15-
// TODO: Implement the logic to rotate the matrix 90 degrees in place
15+
let n = matrix.len();
16+
17+
// 处理非方阵的情况:调整矩阵大小为最大边长的方阵
18+
let max_dim = n.max(matrix[0].len());
19+
20+
// 调整矩阵行数
21+
while matrix.len() < max_dim {
22+
matrix.push(vec![0; matrix[0].len()]);
23+
}
24+
25+
// 调整矩阵列数
26+
for row in matrix.iter_mut() {
27+
while row.len() < max_dim {
28+
row.push(0);
29+
}
30+
}
31+
32+
// 从外到内,一层一层旋转
33+
for layer in 0..max_dim/2 {
34+
let last = max_dim - 1 - layer;
35+
36+
for i in layer..last {
37+
// 保存左上角的值
38+
let temp = matrix[layer][i];
39+
40+
// 左边的值移到上边
41+
matrix[layer][i] = matrix[last - (i - layer)][layer];
42+
43+
// 下边的值移到左边
44+
matrix[last - (i - layer)][layer] = matrix[last][last - (i - layer)];
45+
46+
// 右边的值移到下边
47+
matrix[last][last - (i - layer)] = matrix[i][last];
48+
49+
// 上边的值(之前保存的)移到右边
50+
matrix[i][last] = temp;
51+
}
52+
}
53+
54+
// 如果原矩阵不是方阵,需要调整结果矩阵的大小
55+
if n != matrix[0].len() {
56+
// 调整行数
57+
while matrix.len() > matrix[0].len() {
58+
matrix.pop();
59+
}
60+
}
1661
}
1762

1863
#[cfg(test)]

exercises/easy/algorithm17.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,24 @@
1010
*/
1111

1212
use std::fmt::{self, Display, Formatter};
13+
use std::collections::HashSet;
1314

1415
pub fn intersection(nums1: Vec<i32>, nums2: Vec<i32>) -> Vec<i32> {
15-
// TODO: Implement the logic to find the intersection of two arrays
16-
Vec::new() // Placeholder return value
16+
// 将第一个数组转换为 HashSet,自动去重
17+
let set1: HashSet<_> = nums1.into_iter().collect();
18+
19+
// 将第二个数组转换为 HashSet,自动去重
20+
let set2: HashSet<_> = nums2.into_iter().collect();
21+
22+
// 计算两个集合的交集并收集到 Vec 中
23+
let mut result: Vec<_> = set1.intersection(&set2)
24+
.cloned()
25+
.collect();
26+
27+
// 对结果排序以保证输出顺序一致
28+
result.sort_unstable();
29+
30+
result
1731
}
1832

1933
#[cfg(test)]

exercises/easy/algorithm18.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,33 @@
1414
use std::fmt::{self, Display, Formatter};
1515

1616
pub fn merge_intervals(intervals: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
17-
// TODO: Implement the logic to merge overlapping intervals
18-
Vec::new() // Placeholder return value
17+
if intervals.is_empty() {
18+
return Vec::new();
19+
}
20+
21+
// 创建一个可变的区间副本并按起始点排序
22+
let mut intervals = intervals;
23+
intervals.sort_by_key(|interval| interval[0]);
24+
25+
let mut result = Vec::new();
26+
let mut current = intervals[0].clone();
27+
28+
// 遍历所有区间进行合并
29+
for interval in intervals.into_iter().skip(1) {
30+
if interval[0] <= current[1] {
31+
// 区间重叠,更新当前区间的结束点
32+
current[1] = current[1].max(interval[1]);
33+
} else {
34+
// 区间不重叠,将当前区间加入结果,开始新的区间
35+
result.push(current);
36+
current = interval;
37+
}
38+
}
39+
40+
// 添加最后一个区间
41+
result.push(current);
42+
43+
result
1944
}
2045

2146
#[cfg(test)]

0 commit comments

Comments
 (0)