首页 > 解决方案 > 值移动到这里,在循环的前一次迭代中

问题描述

这是我为LeetCode 写的:添加两个数字

//2. Add Two Numbers
// 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 }
    }
}

struct Solution;

impl Solution {
    pub fn list_to_num(ls: &Option<Box<ListNode>>) -> i64 {
        let mut vec = vec![];
        let mut head = ls;

        while let Some(node) = head {
            vec.push(node.val);
            head = &node.next;
        }

        vec.reverse();

        let mut num = 0i64;

        for x in vec {
            num *= 10;
            num += x as i64;
        }

        num
    }

    pub fn num_to_list(num: i64) -> Option<Box<ListNode>> {
        let num_str = num.to_string();
        let vec = num_str
            .chars()
            .map(|x| x.to_digit(10).unwrap() as i32)
            .collect::<Vec<_>>();

        let mut res = None;
        for x in vec {
            let mut one = ListNode::new(x);
            one.next = res;
            res = Some(Box::new(one));
        }

        res
    }

    pub fn add_two_numbers(
        l1: Option<Box<ListNode>>,
        l2: Option<Box<ListNode>>,
    ) -> Option<Box<ListNode>> {
        let mut vec = vec![] as Vec<i32>;
        let mut step = 0;
        let mut left = l1;
        let mut right = l2;
        loop {
            match (left, right) {
                (None, None) => {
                    if step != 0 {
                        vec.push(step);
                    }
                    break;
                }
                (Some(leftN), None) => {
                    let curr = leftN.val + step;
                    if curr >= 10 {
                        vec.push(curr - 10);
                        step = 1
                    } else {
                        vec.push(curr);
                        step = 0
                    }
                    left = leftN.next
                }
                (None, Some(rightN)) => {
                    let curr = rightN.val + step;
                    if curr >= 10 {
                        vec.push(curr - 10);
                        step = 1
                    } else {
                        vec.push(curr);
                        step = 0
                    }
                    right = rightN.next
                }
                (Some(leftN), Some(rightN)) => {
                    let curr = leftN.val + rightN.val + step;
                    if curr >= 10 {
                        vec.push(curr - 10);
                        step = 1
                    } else {
                        vec.push(curr);
                        step = 0
                    }
                    right = rightN.next;
                    left = leftN.next
                }
            }
        }

        vec.reverse();

        let mut res = None;

        for x in vec {
            let mut next = ListNode::new(x);
            next.next = res;
            res = Some(Box::new(next));
        }
        res
    }
}

fn main() {
    let list1 = Solution::num_to_list(9);
    let list2 = Solution::num_to_list(991);
    println!("list1 {:?}", list1);
    println!("list2 {:?}", list2);
    let res = Solution::add_two_numbers(list1, list2);
    println!("summed {:#?}", res);
}

我得到一个编译错误

error[E0382]: use of moved value: `left`
  --> src/main.rs:66:20
   |
63 |         let mut left = l1;
   |             -------- move occurs because `left` has type `std::option::Option<std::boxed::Box<ListNode>>`, which does not implement the `Copy` trait
...
66 |             match (left, right) {
   |                    ^^^^ value moved here, in previous iteration of loop

error[E0382]: use of moved value: `right`
  --> src/main.rs:66:26
   |
64 |         let mut right = l2;
   |             --------- move occurs because `right` has type `std::option::Option<std::boxed::Box<ListNode>>`, which does not implement the `Copy` trait
65 |         loop {
66 |             match (left, right) {
   |                          ^^^^^ value moved here, in previous iteration of loop

我认为每次迭代都是独立的,如果该值是由先前的迭代借用的,则应该在“this”迭代中返回。

如果我用 替换match (left, right) {match (left.clone(), right.clone()) {代码会编译,但它可能会消耗比必要更多的内存。使其编译并节省内存的更好方法是什么?

标签: rust

解决方案


您不是在借用节点,而是在移动它们。

为了使用引用,您应该替换

let mut left = l1;
let mut right = l2;

let mut left = &l1;
let mut right = &l2;

然后稍后

right = rightN.next;

right = &rightN.next;

等等

操场


推荐阅读