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

文章目录

题目

标题和出处

标题:按奇偶排序数组

出处: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,12,4,1,3 \texttt{2,4,1,3} 2,4,1,34,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 ≤ numsi ≤ 5000 \texttt{0} \le \texttt{numsi} \le \texttt{5000} 0≤numsi≤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} sortedleft,如果 num \textit{num} num 是奇数则填入 sorted right \textit{sorted}\\textit{right} sortedright,然后将相应的下标向数组中间的位置移动一位(将 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} numsleft 是偶数则将 left \textit{left} left 向右移动直到 nums left \textit{nums}\\textit{left} numsleft 是奇数,如果 nums right \textit{nums}\\textit{right} numsright 是奇数则将 right \textit{right} right 向左移动直到 nums right \textit{nums}\\textit{right} numsright 是偶数,移动两个下标的过程中如果遇到 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} numsleft 是奇数, nums right \textit{nums}\\textit{right} numsright 是偶数,因此一个奇数在一个偶数的前面,将 nums left \textit{nums}\\textit{left} numsleft 和 nums right \textit{nums}\\textit{right} numsright 交换,然后将 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)。注意返回值不计入空间复杂度。

相关推荐
j7~1 天前
【算法】专题一:双指针之移动零,复写零,快乐数
数据结构·c++·算法·双指针·快乐数·移动零·复写零
江屿风9 天前
C++OJ题经验总结(竞赛)4
开发语言·c++·笔记·算法·dp·双指针
8Qi810 天前
LeetCode 209. 长度最小的子数组(Minimum Size Subarray Sum)
java·算法·leetcode·双指针·滑动窗口
happymaker062612 天前
LeetCodeHot100——盛水最多的容器
数据结构·算法·leetcode·双指针·hot100
像素猎人15 天前
洛谷题B3882:求回文数【双指针】
算法·双指针
量子炒饭大师21 天前
【优化算法】滑动窗口的「义体化」重构 ——【滑动窗口】何为滑动窗口?滑动窗口算法的核心目的是什么?
c++·算法·重构·优化算法·双指针·滑动窗口
Tisfy22 天前
LeetCode 2540.最小公共值:双指针(O(m+n))
算法·leetcode·题解·双指针
handler0125 天前
滑动窗口(同向双指针)算法:模板与例题解析
c语言·c++·笔记·算法·蓝桥杯·双指针·滑动窗口
量子炒饭大师1 个月前
【优化算法】双指针算法的「义体化」重构 ——【双指针】双指针算法中的指针是如何定义的?如何使用它进行一些简单的算法?
c++·算法·重构·优化算法·双指针
量子炒饭大师1 个月前
【优化算法:双指针算法刷题宝典】—— 三数之和
算法·优化算法·双指针·三数之和