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

文章目录

题目

标题和出处

标题:按奇偶排序数组

出处: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)。注意返回值不计入空间复杂度。

相关推荐
苏纪云2 天前
算法<C++>——双指针 | 滑动窗口
数据结构·c++·算法·双指针·滑动窗口
苏纪云7 天前
算法<C++>——双指针操作链表
c++·算法·链表·双指针
以己之10 天前
11.盛最多水的容器
java·算法·双指针·1024程序员节
伟大的车尔尼11 天前
双指针的概念
数据结构·算法·双指针
gsfl15 天前
双指针算法
算法·双指针
老四啊laosi18 天前
[双指针] 1. 力扣283.移动零
算法·leetcode·双指针·移动零
Tisfy1 个月前
LeetCode 0611.有效三角形的个数:双指针
算法·leetcode·题解·双指针
递归尽头是星辰2 个月前
双指针与滑动窗口算法精讲:从原理到高频面试题实战
算法·双指针·滑动窗口·子串/子数组问题