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

文章目录

题目

标题和出处

标题:按奇偶排序数组

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

相关推荐
yi01116 小时前
DAY24: LeetCode 167:两数之和 II|从暴力枚举到左右双指针
笔记·python·算法·leetcode·二分查找·双指针
yi01117 小时前
LeetCode 15:三数之和|排序 + 双指针,如何避免重复答案?
笔记·python·算法·leetcode·双指针
yi0112 天前
DAY23: LeetCode 27 → 283:从移除元素到移动零,理解快慢指针的两种思路
人工智能·笔记·python·算法·leetcode·排序算法·双指针
兔小盈8 天前
有效三角形个数与和为s的两个数字
算法·双指针
a1879272183125 天前
【算法】双指针与滑动窗口(三):相向双指针——比较、排除、收缩
算法·leetcode·双指针·滑动窗口·原理·相向双指针·算法讲解
a187927218311 个月前
【算法】双指针与滑动窗口(二):滑动窗口——吃进、判定、吐出
算法·leetcode·双指针·滑动窗口·原理·模板·算法讲解
elseif1231 个月前
【双指针/二分】P1102 A-B 数对
c++·算法·二分·双指针
a187927218311 个月前
【算法】双指针与滑动窗口(一):框架总纲——三类问题、一个原理与判决书
算法·leetcode·区间·双指针·滑动窗口·原理·算法讲解
Tisfy2 个月前
LeetCode 3090.每个字符最多出现两次的最长子字符串:二重循环 / 滑动窗口
算法·leetcode·字符串·题解·模拟·双指针·滑动窗口
琥珀色糖2 个月前
leetcode hot100题(持续更新)移动零(双指针)
算法·leetcode·职场和发展·双指针·移动零