977. 有序数组的平方
题目描述
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
解题思路
有个很直接的方法是,先取绝对值,然后sort,然后平方
但是这个是nlogn的算法,想要一个n的算法,那很显然需要用到数组有序这个特性。
其实平方是无关紧要的操作。
找到最小的元素,然后向两边双边移动?
#![allow(unused)] fn main() { struct Solution {} impl Solution { pub fn sorted_squares(mut nums: Vec<i32>) -> Vec<i32> { nums.iter_mut() .filter(|&&mut x| x < 0) .for_each(|x| *x = -*x); let low = nums.iter().enumerate() .fold((0, nums[0]), |(idx, v), (jdx, &x)| { if x < v { (jdx, x) } else { ( idx, v ) } }).0; if low == 0 { return nums.iter().map(|x| x**x).collect() } let mut left = low as isize - 1; let mut right = low + 1; let n = nums.len(); let mut v = Vec::with_capacity(n); v.push(nums[low]); // left -> 还需要处理的左侧第一个元素 // right 还需要处理的右侧第一个元素 while left >= 0 && right < n { // 判断两侧 if nums[left as usize] < nums[right] { v.push(nums[left as usize]); left -= 1; } else { v.push(nums[right]); right += 1; } } if left < 0 { while right < n { v.push(nums[right]); right += 1; } } else { while left >= 0 { v.push(nums[left as usize]); left -= 1; } } v.iter().map(|x| x**x).collect() } } }
写出来了,但是很长,确实定义的每一个变量的明确含义一定要在写之前就很清楚
学习感想
数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
我是从最小数开始构建,确实麻烦,从最大的数开始构建就是一个简单一点的从两侧开始的双指针了。
#![allow(unused)] fn main() { struct Solution {} impl Solution { pub fn sorted_squares(mut nums: Vec<i32>) -> Vec<i32> { let n = nums.len(); let mut v = Vec::with_capacity(n); let mut a = 0; let mut b = n as isize - 1; while a <= b { if nums[a as usize].abs() < nums[b as usize].abs() { v.push(nums[b as usize]); b -= 1; } else { v.push(nums[a as usize]); a += 1; } } v.iter().map(|x| x**x).rev().collect() } } }
注意是abs比较,a和b都是闭区间
#![allow(unused)] fn main() { struct Solution {} impl Solution { pub fn sorted_squares(nums: Vec<i32>) -> Vec<i32> { let mut res: Vec<i32> = vec![0i32; nums.len()]; let mut idx: usize = 0usize; let mut left: usize = 0usize; let mut right: usize = nums.len() - 1usize; while idx < res.len() { let left_square: i32 = nums[left].pow(2u32); let right_square: i32 = nums[right].pow(2u32); use std::cmp::Ordering; match left_square.cmp(&right_square) { Ordering::Less => { right -= 1usize; res[nums.len() - 1usize - idx] = right_square; } _ => { left += 1usize; res[nums.len() - 1usize - idx] = left_square; } } idx += 1; } res } } }