剑指offer第二版(Python3)--面试题21:调整数组顺序使奇数位于偶数前面

第2章 面试需要的基础知识

第3章 高质量的代码

  面试题16:数值的整数次方
  面试题21:调整数组顺序使奇数位于偶数前面

第4章 解决面试题的思路

第5章 优化时间和空间效率

第6章 面试中的各项能力

第7章 两个面试案例


题目描述
  输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分。

解题思路
  维护两个指针,第一个指针初始化时指向数组第一位,它只向后移动,第二个指针初始化时指向数组最后一位,它只向前移动。如果第一个指针指向的是偶数,第二个指针指向的是奇数,则交换两个数字,因此一次遍历即可完成。

实战

def reOrderArray(array):
    # write code here
	if not array:
		return array
    while odd < even:
	    while odd < even and array[odd] % 2 == 1:
	        odd += 1
	    while odd < even and array[even] % 2 == 0:
	        even -= 1
	    if odd < even:
	        array[odd], array[even] = array[even], array[odd]

    return array

  上题是《剑指offer》书中原题,在牛客网上有一道类似题目,不过加了一个条件,就是偶数与偶数之间,奇数与奇数之间相对位置不变,在此条件下,上述解法不可行。

题目描述
牛客网
  输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

解题思路
解法一:
  最简单的就是使用辅助空间。建立两个数组,分别存放奇数和偶数,遍历一遍数组,即可区分所有奇偶数,最后合并两个数组并返回。显然这种解法并不能得到面试官的青睐

def reOrderArray(array):
    # write code here

    if not array:
        return []
    odd, even = [], []
    for num in array:
        if num % 2 == 1:
            odd.append(num)
        else:
            even.append(num)
    return odd + even

解法二:
  使用O(1)空间。第一题的解法会导致元素之间相对位置打乱,原因在于遇到偶数在奇数前时就立即交换元素。其实改进交换时间即可保持相对位置不变。
  冒泡排序中每遍历一遍都可将一个最大值或者最小值排序到位,我们可以借鉴冒泡排序思想,使用两个循环,外循环用于控制已移位的元素边界,内循环中每次都将未移位元素中最左边的奇数移位到最左边。
  举例:
      [1, 2, 8, 7, 6, 5]

  1. 初始化,指针begin,end分别指向1和5;
  2. 开始外循环,1为奇数,begin右移一位,begin指向2;
  3. 5是最右边的奇数,创建临时变量odd,指向5;
  4. 进入内循环,array[odd-1]是偶数,交换array[odd]和array[odd-1];
  5. 此时数组情况为:[1, 2, 8, 7, 5, 6],begin,end, odd分别指向2, 5, 5;
  6. 内循环中发现array[odd-1]=7是奇数,odd左移一位,end不变;
  7. array[odd-1]=8是偶数,交换array[odd]和array[odd-1],odd左移一位;
  8. array[odd-1]=2是偶数,交换array[odd]和array[odd-1],odd左移一位;
  9. 此时数组情况为:[1, 7, 2, 8, 5, 6],odd < begin,结束内循环;
  10. 继续下一次外循环。

  上述过程中,第一次遇到偶数在奇数前面是array[begin]=2, array[end]=5,此时并没有立即交换元素,而是利用临时变量odd去寻找最左边的奇数,找到最左边奇数7,然后执行交换。

实战

class Solution:
    def reOrderArray(self, array):
        # write code here
        if not array:
            return[]

        left, right = 0, len(array)-1
        while left < right:
            while array[left] % 2 == 1:
                left += 1
            while array[right] % 2 == 0:
                right -= 1
            if left < right:
                odd = right
                while odd > left:
                    if array[odd-1] % 2 == 0:
                        array[odd], array[odd-1] = array[odd-1], array[odd]
                    odd -= 1
                    
        return array
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值