2025年6月29日 星期日

在 Rust 上又遇到了一次跟 C++ 一樣的問題

今天在練習 LeetCode 1498. Number of Subsequences That Satisfy the Given Sum Condition 這題時,用 Rust 寫出了以下的程式碼。

impl Solution {
    pub fn num_subseq(mut nums: Vec<i32>, target: i32) -> i32 {
        let MOD = 1e9 as i32 + 7;
        let n = nums.len();
        let mut pow2 = vec![1; n];
        for i in 1..n {
            pow2[i] = (pow2[i-1] << 1) % MOD;
        }
        nums.sort();
        let (mut l, mut r, mut count) = (0, n - 1, 0);
        while l <= r {
            if nums[l] + nums[r] <= target {
                count = (count + pow2[r-l]) % MOD;
                l += 1;
            } else {
                r -= 1;
            }
        }
        count
    }
}

心想說應該沒什麼問題吧,就用跟其他程式語言同樣的邏輯,再寫一遍就好了。

結果就撞到了跟上次 C++ 的 std::string::size() 使用上要小心的地方 同樣的問題。 Orz

r 在 0 之後變成了 usize 的最大值,然後就爆掉了。

應該要特地將 r 弄成 i32 才對,可是不覺得上面的程式碼看起來很順暢不是嗎?盡量少用 as,讓型別自動推導出來,然後就爆掉了,果然魔鬼都是藏在細節裡面。囧rz

impl Solution {
    pub fn num_subseq(mut nums: Vec<i32>, target: i32) -> i32 {
        let MOD = 1e9 as i32 + 7;
        let n = nums.len();
        let mut pow2 = vec![1; n];
        for i in 1..n {
            pow2[i] = (pow2[i-1] << 1) % MOD;
        }
        nums.sort();
        let (mut l, mut r, mut count) = (0, n as i32 - 1, 0);
        while l <= r {
            if nums[l] + nums[r] <= target {
                count = (count + pow2[(r-l) as usize]) % MOD;
                l += 1;
            } else {
                r -= 1;
            }
        }
        count
    }
}

沒有留言: