剑指Offer_#21_调整数组顺序使奇数位于偶数前面
剑指Offer_#21_调整数组顺序使奇数位于偶数前面
Contents
题目
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。提示:
1 <= nums.length <= 50000
1 <= nums[i] <= 10000思路分析
1.暴力循环
最简单的思路是从前往后遍历数组,每次遇到一个偶数,就把这个偶数放到最后一位,把偶数后面的元素逐个向前移动一位。每次挪动数字的时间复杂度是O(n),整体的时间复杂度是O(n2),不推荐。
2.左右双指针
设置前后两个指针left和right,分别向后和向前遍历,left指针寻找位于数组前半部分的偶数,right指针寻找位于数组后半部分的奇数,然后将这两个数字交换。
3.左右双指针+临时数组
申请一个临时数组temp,左右指针left和right分别指向临时数组temp的左右两侧。然后从前到后遍历原数组nums,遇到奇数则放到temp的left位置,遇到偶数则放到temp的right位置。
4.快慢双指针
设置一个快指针fast和一个慢指针slow。fast逐个遍历数组,寻找下一个奇数,slow遍历的是待交换的数组元素。每次fast搜索到奇数,就和slow交换。
解答
1.左右双指针
class Solution {
public int[] exchange(int[] nums) {
int left = 0,right = nums.length - 1;
while(left < right){
while(left < right && nums[left] % 2 != 0){//右移左指针直到遇到偶数
left++;
}
while(left < right && nums[right] % 2 !=1){//左移右指针直到遇到奇数
right--;
}
if(left < right){//left和right分别指向偶数和奇数,将他们交换位置
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
}
return nums;
}
}修改循环条件
left<right这个条件感觉很模糊,其实也属于没有显式定义出所有条件,而是一个隐含了left,right不越界的信息,可以把left,right不越界的条件显式写出。
class Solution {
public int[] exchange(int[] nums) {
int left = 0, right = nums.length - 1;
while(left < right){
//左指针不越界,并且指向奇数,就继续右移
while(left <= nums.length - 1 && nums[left] % 2 == 1) left++;
//右指针不越界,并且指向偶数,就继续左移
while(right >= 0 && nums[right] % 2 == 0) right--;
//指针不越界,并且left < right,就交换left和right指针指向的值
if(left <= nums.length - 1 && right >= 0 && left < right){
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
}
}
return nums;
}
}
浙公网安备 33010602011771号