Rust中检查usize整数溢出的规范方法及合并有序数组问题求解
Rust 合并有序数组的无溢出规范实现
原有代码的核心问题在于usize是无符号整数类型,0 <= m_idx这类判断永远为真,索引减到0后继续执行减法会直接触发溢出panic,且当入参m或n为0时,初始的(m-1) as usize转换就会产生非法值。
以下是完全符合Rust安全规范、可读性高的实现方案,无需修改题目给定的入参格式:
impl Solution { pub fn merge(nums1: &mut Vec<i32>, m: i32, nums2: &mut Vec<i32>, n: i32) { // 统一转成usize类型,全程用无符号数操作避免类型转换问题 let (mut m_idx, mut n_idx) = (m as usize, n as usize); let mut cur_idx = m_idx + n_idx; // 两个数组都有未处理元素时循环,确认索引大于0才进入逻辑,完全规避溢出 while m_idx > 0 && n_idx > 0 { // 先减索引再取值,保证索引最小为0 if nums1[m_idx - 1] > nums2[n_idx - 1] { nums1[cur_idx - 1] = nums1[m_idx - 1]; m_idx -= 1; } else { nums1[cur_idx - 1] = nums2[n_idx - 1]; n_idx -= 1; } cur_idx -= 1; } // 仅需处理nums2剩余元素,nums1剩余元素本身就在正确位置无需移动 while n_idx > 0 { nums1[cur_idx - 1] = nums2[n_idx - 1]; n_idx -= 1; cur_idx -= 1; } } }
如果偏好使用checked系列方法的函数式写法,可以参考以下等价实现,利用checked_sub返回None的特性作为循环退出条件,同样完全规避溢出风险:
impl Solution { pub fn merge(nums1: &mut Vec<i32>, m: i32, nums2: &mut Vec<i32>, n: i32) { let mut m_idx = m as usize; let mut n_idx = n as usize; let mut cur_idx = m_idx + n_idx; while let (Some(mi), Some(ni)) = (m_idx.checked_sub(1), n_idx.checked_sub(1)) { if nums1[mi] > nums2[ni] { nums1[cur_idx - 1] = nums1[mi]; m_idx = mi; } else { nums1[cur_idx - 1] = nums2[ni]; n_idx = ni; } cur_idx -= 1; } while let Some(ni) = n_idx.checked_sub(1) { nums1[cur_idx - 1] = nums2[ni]; n_idx = ni; cur_idx -= 1; } } }
内容的提问来源于stack exchange,提问作者Alex Coleman
相关产品推荐
相关产品推荐

