前言:剑指offer刷题系列
问题:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。
思路:
让奇数在前面,偶数在后面,这个题也是一个可以使用双指针思想解决的题目,两个指针从数组前后分别开始移动,总共就四种情况,两个都是奇数,两个都是偶数,一奇一偶,一偶一奇,分别考虑就可以了。
两个都是奇数的时候,前面指针向后移一位,后面指针不动
两个都是偶数的时候,前面指针不动,后面指针向前移一位
一个奇数一个偶数,前面指针向后移一位,后面指针向前移一位
一个偶数一个奇数,这种情况数据交换,然后前面指针向后移一位,后面指针向前移一位
直到 i > j,结束循环
基于上述思考,代码如下:
var exchange = function(nums) {
let i = 0,j = nums.length - 1
while(i < j){
if(nums[i] % 2 == 0 && nums[j] % 2 == 0) j--
if(nums[i] % 2 == 0 && nums[j] %2 == 1){
let tmp = nums[i]
nums[i] = nums[j]
nums[j] = tmp
i++
j--
}
if(nums[i] % 2 == 1 && nums[j] % 2 == 0){
i++
j--
}
if(nums[i] % 2 == 1 && nums[j] % 2== 1){
i++
}
}
return nums
};
执行结果如下图:
简洁版代码:
var exchange = function(nums) {
let i = 0,j = nums.length - 1
while(i < j){
if(nums[i] % 2 == 0 && nums[j] %2 == 1){
let tmp = nums[i]
nums[i] = nums[j]
nums[j] = tmp
}
if(nums[i] % 2 == 1) i++
if(nums[j] % 2 == 0) j--
}
return nums
};
执行结果一样
python版本:
思路:
一开始的思路方法是声明一个新的列表,用两个for循环分别判断,先循环当nums里面的值为奇数时,append追加到新列表中,第二个循环是当nums里面的值为偶数时,append追加到列表尾部,最后返回列表即可。
后面修改了使用双指针算法,从列表前后分别向中间判断,前后分别有四种情况,奇数奇数,奇数偶数,偶数奇数,偶数偶数,分别判断对应情况,是否进行交换或者移动。
当奇数偶数时,前后指针都向中间移动即可 当偶数奇数时,需要交换数据 当奇数奇数时,后面的数据位置错误,保持不变,前面的指针后移 当偶数偶数时,前面的数据位置错误,保持不变,后面的指针前移 为了简洁代码,所以就有了下一种代码判断, 当偶数奇数时,交换数据;当前面是奇数时,前面指针后移;当后面是偶数时,后面指针后移。
代码:
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
i = 0
j = len(nums) - 1
while i < j:
if nums[i] % 2 == 0 and nums[j] % 2 == 1:
tmp = nums[i]
nums[i] = nums[j]
nums[j] = tmp
if nums[i] % 2 == 1:
i += 1
if nums[j] % 2 == 0:
j -= 1
return nums