【剑指Offer刷题系列】调整数组顺序使奇数位于偶数前面



问题描述

教练使用整数数组 actions 记录一系列核心肌群训练项目编号。为增强训练趣味性,需要将所有奇数编号训练项目调整至偶数编号训练项目之前。请将调整后的训练项目编号以 数组 形式返回。

输入

  • actions:整数数组,表示不同位置的训练项目编号。
  • limit:整数,表示训练项目的视野范围,即滑动窗口的大小。

输出

  • 返回一个数组,其中所有奇数编号训练项目位于偶数编号训练项目之前,且相对顺序保持不变。

示例 1

输入

actions = [1,2,3,4,5]

输出

[1,3,5,2,4]

解释

将所有奇数编号训练项目 [1, 3, 5] 移动到偶数编号训练项目 [2, 4] 之前,保持相对顺序不变。

提示

  • 0 <= actions.length <= 50000
  • 0 <= actions[i] <= 10000

原题链接:


示例

示例 1:

输入

actions = [1,2,3,4,5]

输出

[1,3,5,2,4]

解释
在上述示例中,所有奇数编号训练项目 [1, 3, 5] 被移动到偶数编号训练项目 [2, 4] 之前,且相对顺序保持不变。


思路解析

本题要求将数组 actions 中所有奇数编号的训练项目移动到偶数编号训练项目之前,同时保持奇数和偶数各自的相对顺序。由于需要保持相对顺序,我们可以采用以下几种方法来解决该问题:

方法一:使用额外空间

核心思路

遍历原数组,将奇数编号和偶数编号分别存储到两个新的数组中,最后将奇数数组和偶数数组合并即可。该方法简单直观,能够有效地保持奇数和偶数的相对顺序。

详细步骤

  1. 初始化

    • 创建两个空的列表 oddsevens 分别用于存储奇数编号和偶数编号的训练项目。
  2. 遍历数组

    • 对于数组中的每个元素 num
      • 如果 num 是奇数,则添加到 odds 列表中。
      • 如果 num 是偶数,则添加到 evens 列表中。
  3. 合并结果

    • odds 列表和 evens 列表合并为一个新的列表 result
  4. 返回结果

    • 返回合并后的 result 列表。

示例分析

以示例 1 为例:

actions = [1,2,3,4,5]
  • 遍历数组:

    • 1 是奇数,添加到 oddsodds = [1]
    • 2 是偶数,添加到 evensevens = [2]
    • 3 是奇数,添加到 oddsodds = [1, 3]
    • 4 是偶数,添加到 evensevens = [2, 4]
    • 5 是奇数,添加到 oddsodds = [1, 3, 5]
  • 合并结果:

    • result = odds + evens = [1, 3, 5, 2, 4]

方法二:双指针法(原地交换)

核心思路

使用双指针法在原数组上进行操作,分别指向数组的起始和末尾。通过交换奇数和偶数的位置,将所有奇数移动到数组的前半部分,偶数移动到后半部分。该方法节省了空间,但可能会破坏奇数和偶数的相对顺序。

详细步骤

  1. 初始化指针

    • left 指针初始化为数组起始位置 0
    • right 指针初始化为数组末尾位置 n-1
  2. 遍历数组

    • left 小于 right 时:
      • 如果 actions[left] 是奇数,移动 left 指针向右。
      • 如果 actions[left] 是偶数,并且 actions[right] 是奇数,则交换 actions[left]actions[right],然后移动 leftright 指针。
      • 如果 actions[right] 不是奇数,则仅移动 right 指针。
  3. 终止条件

    • left 不再小于 right 时,结束遍历。
  4. 返回结果

    • 返回调整后的 actions 数组。

注意事项

  • 该方法可能会破坏奇数和偶数的相对顺序。如果题目要求保持相对顺序,应采用方法一。

示例分析

以示例 1 为例:

actions = [1,2,3,4,5]
left = 0, right = 4
  • 第一次循环:

    • actions[left] = 1 是奇数,left 移动到 1.
  • 第二次循环:

    • actions[left] = 2 是偶数,actions[right] = 5 是奇数,交换 25
    • 数组变为 [1,5,3,4,2]
    • left 移动到 2, right 移动到 3.
  • 第三次循环:

    • actions[left] = 3 是奇数,left 移动到 3.
  • 结束遍历。

  • 最终数组为 [1,5,3,4,2]

注意:该方法不保持相对顺序,但符合题意要求。


方法三:插入法(保持相对顺序)

核心思路

遍历数组,将奇数元素插入到结果数组的前面,同时保持其相对顺序。该方法需要额外的空间,但能够保持奇数和偶数的相对顺序。

详细步骤

  1. 初始化

    • 创建一个空的结果列表 result
  2. 遍历数组

    • 对于数组中的每个元素 num
      • 如果 num 是奇数,添加到 result 列表的末尾。
  3. 再次遍历数组

    • 对于数组中的每个元素 num
      • 如果 num 是偶数,添加到 result 列表的末尾。
  4. 返回结果

    • 返回合并后的 result 列表。

示例分析

以示例 1 为例:

actions = [1,2,3,4,5]
  • 遍历数组,添加奇数:

    • 1 是奇数,result = [1]
    • 2 是偶数,跳过
    • 3 是奇数,result = [1, 3]
    • 4 是偶数,跳过
    • 5 是奇数,result = [1, 3, 5]
  • 再次遍历数组,添加偶数:

    • 1 是奇数,跳过
    • 2 是偶数,result = [1, 3, 5, 2]
    • 3 是奇数,跳过
    • 4 是偶数,result = [1, 3, 5, 2, 4]
    • 5 是奇数,跳过
  • 最终结果为 [1, 3, 5, 2, 4]


代码实现

Python 实现(方法一:使用额外空间)

from typing import List

class Solution:
    def rearrangeActions(self, actions: List[int]) -> List[int]:
        """
        方法一:使用额外空间
        分别收集奇数和偶数,最后合并。
        
        :param actions: List[int] - 训练项目编号数组
        :return: List[int] - 调整后的训练项目编号数组
        """
        odds = []
        evens = []
        
        for num in actions:
            if num % 2 != 0:
                odds.append(num)
            else:
                evens.append(num)
        
        return odds + evens

Python 实现(方法二:双指针法)

from typing import List

class Solution:
    def rearrangeActions(self, actions: List[int]) -> List[int]:
        """
        方法二:双指针法(原地交换)
        将所有偶数移到数组末尾,奇数保留在前面。可能会破坏相对顺序。
        
        :param actions: List[int] - 训练项目编号数组
        :return: List[int] - 调整后的训练项目编号数组
        """
        left = 0
        right = len(actions) - 1
        
        while left < right:
            if actions[left] % 2 != 0:
                left += 1
            elif actions[right] % 2 == 0:
                right -= 1
            else:
                actions[left], actions[right] = actions[right], actions[left]
                left += 1
                right -= 1
        
        return actions

Python 实现(方法三:插入法)

from typing import List

class Solution:
    def rearrangeActions(self, actions: List[int]) -> List[int]:
        """
        方法三:插入法(保持相对顺序)
        首先收集所有奇数,然后收集所有偶数,保持相对顺序不变。
        
        :param actions: List[int] - 训练项目编号数组
        :return: List[int] - 调整后的训练项目编号数组
        """
        result = []
        for num in actions:
            if num % 2 != 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值