[lc-rs] 双指针
lc94
从 root 里安全取出节点并借用其内容
let node = root.as_ref().unwrap().borrow();
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
fn dfs(root: &Option<Rc<RefCell<TreeNode>>>, ans: &mut Vec<i32>) {
if root.is_none() {
return;
}
let node = root.as_ref().unwrap().borrow();
Self::dfs(&node.left, ans);
ans.push(node.val);
Self::dfs(&node.right, ans);
}
pub fn inorder_traversal(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
let mut ans = vec![];
Self::dfs(&root, &mut ans);
ans
}
}
lc24
交换链表
rust写链表尤其需要注意所有权转移
一般考虑顺序遍历
逐个节点获取所有权,再进行操作
impl Solution {
pub fn swap_pairs(head: Option<Box<ListNode>>) -> Option<Box<ListNode>>
{
let mut remain = head;
let mut result = ListNode::new(0);
let mut tail = &mut result;
while let Some(mut n1) = remain {
remain = n1.next.take(); // take()将n1打断,这样n1只有一个值,返回值是除n1节点外的剩余节点
if let Some(mut n2) = remain
{
remain = n2.next.take();
n2.next = Some(n1);
tail.next = Some(n2);
tail = tail.next.as_mut().unwrap().next.as_mut().unwrap();
}
else {
tail.next = Some(n1);
tail = tail.next.as_mut().unwrap();
}
}
result.next
}
}
lc11
双指针从数组两端向中间收缩
每次移动较短的垂线(因短边限制面积),实时更新最大矩形面积
impl Solution {
pub fn max_area(height: Vec<i32>) -> i32
{
let mut ans = 0;
let mut left = 0;
let mut right = height.len() - 1;
while left < right
{
let area = (right - left) as i32 * height[left].min(height[right]);
ans = ans.max(area);
if height[left] < height[right] {
// height[left] 与右边的任意垂线都无法组成一个比 ans 更大的面积
left += 1;
} else {
right -= 1;
}
}
ans
}
}
lc15
排序后固定首个数字,用双指针找另外两数使和为0
跳过重复元素+边界预判优化
高效找不重复三元组
impl Solution {
pub fn three_sum(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
nums.sort_unstable();
let n = nums.len();
let mut ans = vec![];
for i in 0..n - 2 {
let x = nums[i];
if i > 0 && x == nums[i - 1] { // 跳过重复数字
continue;
}
if x + nums[i + 1] + nums[i + 2] > 0 { // 优化一
break;
}
if x + nums[n - 2] + nums[n - 1] < 0 { // 优化二
continue;
}
let mut j = i + 1;
let mut k = n - 1;
while j < k {
let s = x + nums[j] + nums[k];
if s > 0 {
k -= 1;
} else if s < 0 {
j += 1;
} else { // 三数之和为 0
ans.push(vec![x, nums[j], nums[k]]);
j += 1;
while j < k && nums[j] == nums[j - 1] { // 跳过重复数字
j += 1;
}
k -= 1;
while k > j && nums[k] == nums[k + 1] { // 跳过重复数字
k -= 1;
}
}
}
}
ans
}
}