只能說Rust鏈表題的畫風(fēng)和C++完全不一樣,作為新手一時間還不太適應(yīng),于是單獨為鏈表、智能指針開一篇,主要記錄leetcode相關(guān)題型的答案以及注意事項。
??關(guān)鍵操作
as_ref()
將Option<T>
、&Option<T>
或者&mut Option<T>
轉(zhuǎn)換為Option<&T>
as_mut()
將Option<T>
、&mut Option<T>
轉(zhuǎn)換為Option<&mut T>
,不能對&Option<T>
進行轉(zhuǎn)換
??以及注意&
和&mut
叫做借用是非常形象的,既然是借用他人的物品,就不能轉(zhuǎn)移他人物品的所有權(quán)
如果要拿走他人物品的所有權(quán),請使用take()
??l1 = p.next
這個操作是希望把節(jié)點p的next賦給l1,但實際上如果p是對Box<ListNode>
的可變借用,就會報錯,因為這個過程會有所有權(quán)轉(zhuǎn)移,p既然是借用,它就無權(quán)處置“物主”擁有的物品。所以此時用take()
,l1 = p.next.take()
表示通過p這個借用,將所有權(quán)“拿走”給l1,并將p.next
設(shè)置為None
。總之如果要通過借用來轉(zhuǎn)移所有權(quán),可以使用take()
leetcode 2 兩數(shù)相加——模式匹配+單鏈表+Box
??兩個注意點
??里面有官方提供的單鏈表的實現(xiàn),可以參考下;
??遍歷鏈表可以用loop+match模式匹配的方式
// Definition for singly-linked list.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>
}
impl ListNode {
#[inline]
fn new(val: i32) -> Self {
ListNode {
next: None,
val
}
}
}
impl Solution {
pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let mut t = (l1, l2, 0, 0);
let mut result = None;
let mut tail = &mut result;
loop {
t = match t {
(None, None, _, 0) => break,
(Some(l1), Some(l2), _, mut carry) => {
let temp = l1.val + l2.val + carry;
let res_temp = temp % 10;
carry = temp / 10;
(l1.next, l2.next, res_temp, carry)
}
(Some(l), None, _, mut carry) | (None, Some(l), _, mut carry) => {
let temp = l.val + carry;
let res_temp = temp % 10;
carry = temp / 10;
(l.next, None, res_temp, carry)
}
(None, None, _, carry) => {
(None, None, carry, 0)
}
};
*tail = Some(Box::new(ListNode::new(t.2)));
tail = &mut tail.as_mut().unwrap().next;
}
result
}
}
??#[inline] 是什么?
是Rust 中的一個屬性,用于提示編譯器嘗試對函數(shù)進行內(nèi)聯(lián)展開優(yōu)化。 內(nèi)聯(lián)展開是一種優(yōu)化技術(shù),可以將函數(shù)調(diào)用的地方替換為函數(shù)體的內(nèi)容,減少了函數(shù)調(diào)用的開銷,提高代碼的執(zhí)行速度。 通過在函數(shù)定義之前使用 #[inline] 屬性,你可以向編譯器發(fā)出建議,讓它在合適的情況下嘗試內(nèi)聯(lián)展開函數(shù)。文章來源:http://www.zghlxwxcb.cn/news/detail-671445.html
另一個解法,更像是C++或者Java選手的思維文章來源地址http://www.zghlxwxcb.cn/news/detail-671445.html
impl Solution {
pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let (mut l1, mut l2) = (l1, l2);
let mut head = Box::new(ListNode::new(0));
let mut p = &mut head;
let mut carry = 0;
let mut temp = 0;
while let (Some(node1), Some(node2)) = (l1.as_ref(), l2.as_ref()) {
temp = node1.val + node2.val + carry;
p.next = Some(Box::new(ListNode::new(temp % 10)));
p = p.next.as_mut().unwrap();
carry = temp / 10;
l1 = l1.unwrap().next;
l2 = l2.unwrap().next;
}
while let Some(node) = l1.as_ref() {
temp = node.val + carry;
p.next = Some(Box::new(ListNode::new(temp % 10)));
p = p.next.as_mut().unwrap();
carry = temp / 10;
l1 = l1.unwrap().next;
}
while let Some(node) = l2.as_ref() {
temp = node.val + carry;
p.next = Some(Box::new(ListNode::new(temp % 10)));
p = p.next.as_mut().unwrap();
carry = temp / 10;
l2 = l2.unwrap().next;
}
if carry != 0 {
p.next = Some(Box::new(ListNode::new(carry)));
p = p.next.as_mut().unwrap();
}
head.next
}
}
??????leetcode 21 合并有序鏈表——as_ref()、as_mut()、take()的使用
// Definition for singly-linked list.
// #[derive(PartialEq, Eq, Clone, Debug)]
// pub struct ListNode {
// pub val: i32,
// pub next: Option<Box<ListNode>>
// }
//
// impl ListNode {
// #[inline]
// fn new(val: i32) -> Self {
// ListNode {
// next: None,
// val
// }
// }
// }
impl Solution {
// 對于鏈表而言,下面兩個操作非常關(guān)鍵
// as_ref()將Option<T>、&Option<T>或者&mut Option<T>轉(zhuǎn)換為Option<&T>
// as_mut()將Option<T>、&mut Option<T>轉(zhuǎn)換為Option<&mut T>,不能對&Option<T>進行轉(zhuǎn)換
// ??以及注意&和&mut叫做借用是非常形象的,既然是借用他人的物品,就不能轉(zhuǎn)移他人物品的所有權(quán)
// 如果要拿走他人物品的所有權(quán),請使用take()
// 堆上創(chuàng)建頭結(jié)點
pub fn merge_two_lists(mut l1: Option<Box<ListNode>>, mut l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
// 對于鏈表而言,下面兩個操作非常關(guān)鍵
// as_ref()將Option<T>、&Option<T>或者&mut Option<T>轉(zhuǎn)換為Option<&T>
// as_mut()將Option<T>、&mut Option<T>轉(zhuǎn)換為Option<&mut T>,不能對&Option<T>進行轉(zhuǎn)換
// ??以及注意&和&mut叫做借用是非常形象的,既然是借用他人的物品,就不能轉(zhuǎn)移他人物品的所有權(quán)
// 如果要拿走他人物品的所有權(quán),請使用take()
// 堆上創(chuàng)建頭結(jié)點
let mut head = Box::new(ListNode::new(0));
let mut p = &mut head; // 尾節(jié)點的可變借用
while let (Some(node1), Some(node2)) = (l1.as_ref(), l2.as_ref()) {
if node1.val < node2.val {
p.next = l1;
p = p.next.as_mut().unwrap();
l1 = p.next.take(); // 將p.next擁有的轉(zhuǎn)移給l1,并設(shè)置p.next為None
}
else {
p.next = l2;
p = p.next.as_mut().unwrap();
l2 = p.next.take();
}
}
if l1.is_some() {
p.next = l1;
}
else {
p.next = l2;
}
head.next
}
}
到了這里,關(guān)于Rust踩雷筆記(5)——刷點鏈表的題(涉及智能指針Box,持續(xù)更新)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!