按奇偶排序数组

标签: 数组 双指针 排序

难度: Easy

给你一个整数数组 nums,将 nums 中的的所有偶数元素移动到数组的前面,后跟所有奇数元素。

返回满足此条件的 任一数组 作为答案。

示例 1:

输入:nums = [3,1,2,4]
输出:[2,4,3,1]
解释:[4,2,3,1]、[2,4,1,3] 和 [4,2,1,3] 也会被视作正确答案。

示例 2:

输入:nums = [0]
输出:[0]

提示:

  • 1 <= nums.length <= 5000
  • 0 <= nums[i] <= 5000

Submission

运行时间: 25 ms

内存: 16.6 MB

from collections import deque
class Solution:
    def sortArrayByParity(self, nums: List[int]) -> List[int]:
        l=0
        for r in range(len(nums)):
            if nums[r]%2==0:
                nums[r],nums[l]=nums[l],nums[r]
                l+=1
        return nums

'''
        estack = []
        for i in range(len(nums)):
            a=nums.pop(0)
            if a%2==0:
                estack.append(a)
            else:
                nums.append(a)
        return estack+nums
'''

Explain

该题解利用了双指针的策略。使用一个指针 `l` 从数组的开始位置遍历,用于指向当前偶数应该插入的位置,而另一个指针 `r` 用于遍历整个数组。遍历时,如果发现 `r` 指向的元素是偶数,则将其与 `l` 指向的元素交换,并将 `l` 指针向右移动一位。这样可以确保所有偶数都被移到数组的前部,而奇数保持在数组后部。

时间复杂度: O(n)

空间复杂度: O(1)

python
from typing import List

class Solution:
    def sortArrayByParity(self, nums: List[int]) -> List[int]:
        l = 0  # 初始化偶数应该插入的位置
        for r in range(len(nums)):  # 遍历数组
            if nums[r] % 2 == 0:  # 检查当前元素是否为偶数
                nums[r], nums[l] = nums[l], nums[r]  # 交换偶数到前部
                l += 1  # 移动指向偶数插入位置的指针
        return nums

Explore

在算法中,指针`l`的初始值为0是因为我们需要从数组的开始位置来放置偶数。这个位置表示下一个偶数应该被交换到的位置。这不意味着数组的第一个元素必须是偶数;如果第一个元素是奇数,`l`会保持在0位置直到找到第一个偶数,并将其交换到数组的开始位置。

如果数组中存在多个连续的偶数,指针`r`会依次遍历这些偶数,每次发现偶数时,它就会与指针`l`指向的位置进行交换,随后`l`和`r`都会向右移动一位。由于这些都是偶数,所以实际上`r`指向的偶数与`l`指向的偶数进行交换,这仅仅是位置上的交换,实质上数组的顺序并未改变。

如果`r`和`l`指向同一个位置,进行交换实际上没有任何效果,因为这相当于元素与自身交换。在实现中,可以添加一个条件检查来避免这种自我交换,从而略微提高效率,尽管这种情况对算法的正确性和复杂度没有实际影响。

当数组全是奇数时,指针`l`始终不会移动,因为没有偶数进行交换,但指针`r`会遍历整个数组。当数组全是偶数时,`r`和`l`会同步移动,每次都进行一次无意义的自我交换。在这种情况下,虽然算法仍然能正确排序数组,但存在一些不必要的操作。可以通过检查`l`和`r`是否相同来避免不必要的自我交换,从而优化这一点。