检查 usize 中整数溢出的规范方法
Canonical way to check for integer overflow in usize
我试图在 Rust 中解决以下 leetcode problem:
impl Solution {
pub fn merge(nums1: &mut Vec<i32>, m: i32, nums2: &mut Vec<i32>, n: i32) {
let mut backwards_idx: usize = (m + n - 1) as usize;
let (m_size, n_size) = (m as usize, n as usize);
let (mut m_idx, mut n_idx) = ((m-1) as usize, (n-1) as usize);
while 0 <= m_idx && 0 <= n_idx {
let (nums1_elem, nums2_elem) = (nums1[m_idx], nums2[n_idx]);
if nums1_elem <= nums2_elem {
nums1[backwards_idx] = nums2_elem;
n_idx = n_idx - 1;
} else {
nums1[backwards_idx] = nums1_elem;
m_idx = m_idx - 1;
}
backwards_idx = backwards_idx - 1;
}
while 0 <= m_idx {
nums1[backwards_idx] = nums1[m_idx];
m_idx = m_idx - 1;
backwards_idx = backwards_idx - 1;
}
while 0 <= n_idx {
nums1[backwards_idx] = nums2[n_idx];
n_idx = n_idx - 1;
backwards_idx = backwards_idx - 1;
}
}
}
但是,这行不通,因为从 0 中减去 m_size
和 n_size
会溢出。我知道这不是规范的 Rust,但由于问题在 i32
,我改不了多少。
有 ,但它似乎很难阅读,而不是直接在 while 循环条件下写入它。在 while 循环体中设置退出条件似乎不是个好主意。
一种避免溢出的方法是用不同的方式构造循环.... Rust 没有明确的 do-while
语法,但它确实有 loop
你可以 break
使用标签从,甚至突破到任意数量的外循环。
loop {
nums1[backwards_idx] = nums1[m_idx];
if m_idx == 0 { break; }
m_idx -= 1;
backwards_idx -= 1;
}
避免必须检查溢出的一个简单方法是保证您的 usize 类型,它们只会被减 1,从不为 0在这些循环中开始。将 idx 类型重构为计数,并在我们想要获得索引时减去 1,这是一种方法...
impl Solution {
pub fn merge(nums1: &mut Vec<i32>, m: i32, nums2: &mut Vec<i32>, n: i32) {
let mut numbers_left: usize = (m + n) as usize;
let (mut m_left, mut n_left) = (m as usize, n as usize);
while m_left > 0 && n_left > 0 {
let (nums1_elem, nums2_elem) = (nums1[m_left-1], nums2[n_left-1]);
if nums1_elem <= nums2_elem {
nums1[numbers_left-1] = nums2_elem;
n_left = n_left - 1;
} else {
nums1[numbers_left-1] = nums1_elem;
m_left = m_left - 1;
}
numbers_left = numbers_left - 1;
}
while m_left > 0 {
nums1[numbers_left-1] = nums1[m_left-1];
m_left = m_left - 1;
numbers_left = numbers_left - 1;
}
while n_idx > 0 {
nums1[numbers_left-1] = nums2[n_left-1];
n_left = n_left - 1;
numbers_left = numbers_left - 1;
}
}
}
我试图在 Rust 中解决以下 leetcode problem:
impl Solution {
pub fn merge(nums1: &mut Vec<i32>, m: i32, nums2: &mut Vec<i32>, n: i32) {
let mut backwards_idx: usize = (m + n - 1) as usize;
let (m_size, n_size) = (m as usize, n as usize);
let (mut m_idx, mut n_idx) = ((m-1) as usize, (n-1) as usize);
while 0 <= m_idx && 0 <= n_idx {
let (nums1_elem, nums2_elem) = (nums1[m_idx], nums2[n_idx]);
if nums1_elem <= nums2_elem {
nums1[backwards_idx] = nums2_elem;
n_idx = n_idx - 1;
} else {
nums1[backwards_idx] = nums1_elem;
m_idx = m_idx - 1;
}
backwards_idx = backwards_idx - 1;
}
while 0 <= m_idx {
nums1[backwards_idx] = nums1[m_idx];
m_idx = m_idx - 1;
backwards_idx = backwards_idx - 1;
}
while 0 <= n_idx {
nums1[backwards_idx] = nums2[n_idx];
n_idx = n_idx - 1;
backwards_idx = backwards_idx - 1;
}
}
}
但是,这行不通,因为从 0 中减去 m_size
和 n_size
会溢出。我知道这不是规范的 Rust,但由于问题在 i32
,我改不了多少。
有
一种避免溢出的方法是用不同的方式构造循环.... Rust 没有明确的 do-while
语法,但它确实有 loop
你可以 break
使用标签从,甚至突破到任意数量的外循环。
loop {
nums1[backwards_idx] = nums1[m_idx];
if m_idx == 0 { break; }
m_idx -= 1;
backwards_idx -= 1;
}
避免必须检查溢出的一个简单方法是保证您的 usize 类型,它们只会被减 1,从不为 0在这些循环中开始。将 idx 类型重构为计数,并在我们想要获得索引时减去 1,这是一种方法...
impl Solution {
pub fn merge(nums1: &mut Vec<i32>, m: i32, nums2: &mut Vec<i32>, n: i32) {
let mut numbers_left: usize = (m + n) as usize;
let (mut m_left, mut n_left) = (m as usize, n as usize);
while m_left > 0 && n_left > 0 {
let (nums1_elem, nums2_elem) = (nums1[m_left-1], nums2[n_left-1]);
if nums1_elem <= nums2_elem {
nums1[numbers_left-1] = nums2_elem;
n_left = n_left - 1;
} else {
nums1[numbers_left-1] = nums1_elem;
m_left = m_left - 1;
}
numbers_left = numbers_left - 1;
}
while m_left > 0 {
nums1[numbers_left-1] = nums1[m_left-1];
m_left = m_left - 1;
numbers_left = numbers_left - 1;
}
while n_idx > 0 {
nums1[numbers_left-1] = nums2[n_left-1];
n_left = n_left - 1;
numbers_left = numbers_left - 1;
}
}
}