[路飞]_leetcode刷题_调整数组顺序使奇数位于偶数前面

122 阅读1分钟

「这是我参与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个数

解法二

思路

单指针,在原数组上处理,通过交换元素实现。

  1. 定义一个尾指针pr,标识数组的尾部。
  2. 遍历数组,若当前元素是奇数,则跳过
  3. 若当前元素是偶数,则与pr项交换,且pr--。
  4. 由于从末尾交换过来的元素,我们不知道是什么情况,所以需要查看一下,由于接着会i++,所以我们提前i--
  5. 如果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),无需额外申请空间存放元素

解法三

思路

双指针,夹逼。

  1. 定义两个指针pl=0和pr=len-1。
  2. 先从左往右找偶数,如果遇到奇数则跳过,遇到偶数则停下
  3. 再从右往左找奇数,如果遇到偶数则跳过,遇到奇数则停下
  4. 这时候pl位置是偶数,pr位置是奇数,交换两者位置
  5. 循环跳出的条件是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),无需额外申请空间存放元素