双指针题目:按奇偶排序数组

文章目录

题目

标题和出处

标题:按奇偶排序数组

出处:905. 按奇偶排序数组

难度

2 级

题目描述

要求

给定一个整数数组 nums \texttt{nums} nums,将 nums \texttt{nums} nums 中的所有偶数元素移动到数组的前面,所有奇数元素移动到数组的后面。

返回满足此条件的任意数组

示例

示例 1:

输入: nums = [3,1,2,4] \texttt{nums = [3,1,2,4]} nums = [3,1,2,4]

输出: [2,4,3,1] \texttt{[2,4,3,1]} [2,4,3,1]

解释: [4,2,3,1] \texttt{[4,2,3,1]} [4,2,3,1]、 [2,4,1,3] \texttt{[2,4,1,3]} [2,4,1,3] 和 [4,2,1,3] \texttt{[4,2,1,3]} [4,2,1,3] 也是正确答案。

示例 2:

输入: nums = [0] \texttt{nums = [0]} nums = [0]

输出: [0] \texttt{[0]} [0]

数据范围

  • 1 ≤ nums.length ≤ 5000 \texttt{1} \le \texttt{nums.length} \le \texttt{5000} 1≤nums.length≤5000
  • 0 ≤ nums[i] ≤ 5000 \texttt{0} \le \texttt{nums[i]} \le \texttt{5000} 0≤nums[i]≤5000

解法一

思路和算法

最直观的做法是新建一个结果数组,将原数组中的元素依次填入结果数组,结果数组满足所有偶数元素在前面,所有奇数元素在后面。为了确保结果数组中的所有偶数在所有奇数前面,需要分别从数组的起始位置和结束位置开始填入偶数和奇数。

用 sorted \textit{sorted} sorted 表示结果数组,用 left \textit{left} left 和 right \textit{right} right 分别表示数组 sorted \textit{sorted} sorted 中填入偶数和奇数的下标,初始时 left \textit{left} left 和 right \textit{right} right 分别指向数组的起始位置和结束位置。

对于原数组中的每个元素 num \textit{num} num,如果 num \textit{num} num 是偶数则填入 sorted [ left ] \textit{sorted}[\textit{left}] sorted[left],如果 num \textit{num} num 是奇数则填入 sorted [ right ] \textit{sorted}[\textit{right}] sorted[right],然后将相应的下标向数组中间的位置移动一位(将 left \textit{left} left 向右移动一位,或将 right \textit{right} right 向左移动一位)。

遍历原数组结束之后,原数组中的所有元素都填入结果数组。由于整个过程中都有 left ≤ right \textit{left} \le \textit{right} left≤right,因此结果数组中的所有偶数在所有奇数前面。

代码

java 复制代码
class Solution {
    public int[] sortArrayByParity(int[] nums) {
        int length = nums.length;
        int[] sorted = new int[length];
        int left = 0, right = length - 1;
        for (int num : nums) {
            if (num % 2 == 0) {
                sorted[left] = num;
                left++;
            } else {
                sorted[right] = num;
                right--;
            }
        }
        return sorted;
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要遍历数组 nums \textit{nums} nums 一次将每个元素填入结果数组。

  • 空间复杂度: O ( 1 ) O(1) O(1)。注意返回值不计入空间复杂度。

解法二

思路和算法

解法一需要新建一个结果数组,也可以在原数组上修改。

用 left \textit{left} left 和 right \textit{right} right 分别表示数组 nums \textit{nums} nums 中填入偶数和奇数的下标,初始时 left \textit{left} left 和 right \textit{right} right 分别指向数组的起始位置和结束位置。

当 left < right \textit{left} < \textit{right} left<right 时,如果 nums [ left ] \textit{nums}[\textit{left}] nums[left] 是偶数则将 left \textit{left} left 向右移动直到 nums [ left ] \textit{nums}[\textit{left}] nums[left] 是奇数,如果 nums [ right ] \textit{nums}[\textit{right}] nums[right] 是奇数则将 right \textit{right} right 向左移动直到 nums [ right ] \textit{nums}[\textit{right}] nums[right] 是偶数,移动两个下标的过程中如果遇到 left = right \textit{left} = \textit{right} left=right 则停止移动下标。当停止移动下标时,可能的两种情况是 left < right \textit{left} < \textit{right} left<right 或 left = right \textit{left} = \textit{right} left=right。

  • 如果 left < right \textit{left} < \textit{right} left<right,则 nums [ left ] \textit{nums}[\textit{left}] nums[left] 是奇数, nums [ right ] \textit{nums}[\textit{right}] nums[right] 是偶数,因此一个奇数在一个偶数的前面,将 nums [ left ] \textit{nums}[\textit{left}] nums[left] 和 nums [ right ] \textit{nums}[\textit{right}] nums[right] 交换,然后将 left \textit{left} left 向右移动一位,将 right \textit{right} right 向左移动一位,并重复上述操作。

  • 如果 left = right \textit{left} = \textit{right} left=right,则当前下标的左边的元素都是偶数,当前下标的右边的元素都是奇数,无论当前下标的元素是偶数还是奇数,整个数组都已经符合所有偶数在所有奇数前面的条件,因此返回数组 nums \textit{nums} nums。

由于 left \textit{left} left 和 right \textit{right} right 相向移动,因此两个下标一定会相遇,此时的数组 nums \textit{nums} nums 即为符合所有偶数在所有奇数前面的数组。

代码

java 复制代码
class Solution {
    public int[] sortArrayByParity(int[] nums) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            while (left < right && nums[left] % 2 == 0) {
                left++;
            }
            while (left < right && nums[right] % 2 != 0) {
                right--;
            }
            if (left < right) {
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left++;
                right--;
            }
        }
        return nums;
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要遍历数组 nums \textit{nums} nums 中的每个元素一次,每次交换操作的时间是 O ( 1 ) O(1) O(1)。

  • 空间复杂度: O ( 1 ) O(1) O(1)。注意返回值不计入空间复杂度。

相关推荐
量子炒饭大师1 天前
【优化算法】滑动窗口的「义体化」重构 ——【滑动窗口】何为滑动窗口?滑动窗口算法的核心目的是什么?
c++·算法·重构·优化算法·双指针·滑动窗口
Tisfy1 天前
LeetCode 2540.最小公共值:双指针(O(m+n))
算法·leetcode·题解·双指针
handler015 天前
滑动窗口(同向双指针)算法:模板与例题解析
c语言·c++·笔记·算法·蓝桥杯·双指针·滑动窗口
量子炒饭大师12 天前
【优化算法】双指针算法的「义体化」重构 ——【双指针】双指针算法中的指针是如何定义的?如何使用它进行一些简单的算法?
c++·算法·重构·优化算法·双指针
量子炒饭大师15 天前
【优化算法:双指针算法刷题宝典】—— 三数之和
算法·优化算法·双指针·三数之和
qeen871 个月前
【算法笔记】双指针及其经典例题解析
c++·笔记·算法·双指针
李日灐1 个月前
【优选算法3】二分查找经典算法面试题
开发语言·c++·后端·算法·面试·二分查找·双指针
小肝一下1 个月前
每日两道力扣,day7
数据结构·c++·算法·leetcode·双指针·hot100·接雨水,四数之和
小肝一下1 个月前
每日两道力扣,day6
数据结构·c++·算法·leetcode·双指针·hot100
Byte不洛1 个月前
LeetCode双指针经典题
c++·算法·leetcode·双指针