「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」
题目
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。
解法一
思路
用两个新数组分别来存放奇数和偶数 。
遍历数组,奇数放一个,偶数放一个。
然后将两者拼接返回即可
/**
* @param {number[]} nums
* @return {number[]}
*/
var exchange = function(nums) {
let odd = [], even = [];
for(let i=0;i<nums.length;i++){
if(nums[i]%2 === 0){
even.push(nums[i])
}else{
odd.push(nums[i])
}
}
return odd.concat(even)
};
复杂度分析
时间复杂度:O(n),将每个数遍历一次
空间复杂度:O(n),两个数组总共要存放n个数
解法二
思路
单指针,在原数组上处理,通过交换元素实现。
- 定义一个尾指针pr,标识数组的尾部。
- 遍历数组,若当前元素是奇数,则跳过
- 若当前元素是偶数,则与pr项交换,且pr--。
- 由于从末尾交换过来的元素,我们不知道是什么情况,所以需要查看一下,由于接着会i++,所以我们提前i--
- 如果i>=pr了,那么循环结束
/**
* @param {number[]} nums
* @return {number[]}
*/
var exchange = function(nums) {
let len = nums.length;
let pr = len-1;
for(let i=0;i<len;i++){
if(i<pr){
if(isEven(nums[i])){
[nums[i],nums[pr]] = [nums[pr],nums[i]]
pr--;
i--;
}
}
}
return nums;
};
function isEven(num){
return num%2 === 0
}
复杂度分析
时间复杂度:O(n),将每个数遍历一次
空间复杂度:O(1),无需额外申请空间存放元素
解法三
思路
双指针,夹逼。
- 定义两个指针pl=0和pr=len-1。
- 先从左往右找偶数,如果遇到奇数则跳过,遇到偶数则停下
- 再从右往左找奇数,如果遇到偶数则跳过,遇到奇数则停下
- 这时候pl位置是偶数,pr位置是奇数,交换两者位置
- 循环跳出的条件是pl>=pr,就是两个指针重叠,那么就没什么好交换的了
/**
* @param {number[]} nums
* @return {number[]}
*/
var exchange = function(nums) {
let len = nums.length;
let pl = 0;
let pr = len-1;
while(pl<pr){
while(pl<pr && !isEven(nums[pl])){
pl++
}
while(pl<pr &&isEven(nums[pr]) ){
pr--
}
[nums[pl],nums[pr]] = [nums[pr],nums[pl]]
}
return nums;
};
function isEven(num){
return num%2 === 0
}
复杂度分析
时间复杂度:O(n),将每个数遍历一次
空间复杂度:O(1),无需额外申请空间存放元素