28 调整数组顺序使奇数位于偶数前面--剑指offer--python实现

1. 题目描述

  描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
  如输入[1,2,3,4,5],则输出应该是[1,3,5,2,4]

2. 题目解析

2.1 考察问题

  本问题考察的是数组遍历和交换问题

2.2 解决方法

  1. 新建数组,两次遍历添加
      新建数组,第一次遍历取奇数放到前半部分,第二次遍历取偶数放到后半部分,然后返回新建数组即可。
    时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)
  2. 目标数组原地遍历和交换
      (1) 遍历目标数组,遇到奇数就尝试向前交换。
      (2) 如果前面是奇数则不交换(保证相对顺序)或者前面没有元素则不交换(保证不超出数组范围)
      (3) 全部遍历完成,返回目标数组
  3. 使用python函数
      这种方法简单明了,但是从时间复杂度来看并不好。

2.3 优化分析

  1. 此问题最容易想到的方法,就是新建一个数组,然后两次遍历目标数组第一次取出奇数放置到新数组前半部分,第二次取出偶数放到后半部分,时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)
  2. 考虑优化从何处入手,时间复杂度方面量级没法优化了,而空间复杂度 O ( n ) O(n) O(n)比较高,可以尝试优化。
  3. 替代新建数组,只能考虑原数组通过交换方式来解决这个问题,所以就需要考虑如何交换。

3. 代码实现

3.1 新建数组,两次遍历添加

class Solution:
    def reOrderArray(self, array):
        # write code here
        arr_new = []
        for num in array:
            if self.isOdd(num):
                arr_new.append(num)
        for num in array:
            if not self.isOdd(num):
                arr_new.append(num)
        return arr_new
        
    def isOdd(self, num):
        return num % 2 != 0

3.2 目标数组原地遍历交换

class Solution:
    def reOrderArray(self, array):
        # write code here
        for i,num in enumerate(array):
            if self.isOdd(num):
                temp = i
                while temp >= 1 and (not self.isOdd(array[temp-1])): ## 考察当前元素和前一个元素,如果不越界且是偶数则交换
                    array[temp], array[temp - 1] = array[temp - 1], array[temp] ## python特有的交换方式
                    temp -= 1
        return array
    
    def isOdd(self, num):
        return num % 2 != 0

3.3 python函数

class Solution:
    def reOrderArray(self, array):
        # write code here
        return sorted(array, key=lambda c: c % 2, reverse=True)## 最简洁,但是时间复杂度至少是(nlogn)

4. 心得

  类似交换,判断奇数偶数,判断素数等都可以作为实用的小程序保存下来。
  这些组件程序可以看作是我们解决问题的“中台”,将算法问题最终归于组件化,而不是每次都重复实现这些小程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值