13.调整数组顺序使奇数位于偶数前面(维持相对顺序)
题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路一:
定义一个等长的数组,遍历两次数组,第一次存奇数,第二次存偶数,最后把临时数组的内存拷贝到数组中
1 public class Solution { 2 public void reOrderArray(int [] array) { 3 // 定义一个等长的数组, 4 int[] temp = new int[array.length]; 5 // 遍历两次数组,第一次存奇数,第二次存偶数 6 // 从前往后找出奇数,存入0 下标开始存, 7 int index = 0; // 临时数组的当前下标 8 for(int i = 0; i < array.length; i++){ 9 if((array[i] & 1) != 0){ 10 temp[index++] = array[i]; 11 } 12 } 13 14 for(int i = 0; i < array.length; i++){ 15 if((array[i] & 1) == 0){ 16 temp[index++] = array[i]; 17 } 18 } 19 // 把临时数组拷贝会原来的数组 20 for(int i = 0; i < array.length; i++){ 21 array[i] = temp[i]; 22 } 23 24 } 25 }
思路二:
遍历数组,把上一个奇数到当前奇数之间的偶数后移一位,把当前奇数填到上一个奇数后面,更新当前奇数的位置
1 public class Solution { 2 public void reOrderArray(int [] array) { 3 // 遍历数组 4 int m = -1; // 当前奇数的位置 5 for(int i = 0; i < array.length; i++){ 6 7 // 如果是奇数, 记录下这个值,将 (i + 1) - j 的元素都后移一位 8 if((array[i] & 1) != 0){ 9 int j = i; 10 int temp = array[j]; 11 while(j > m + 1){ 12 array[j] = array[j - 1]; 13 j--; 14 } 15 m = j; // 更新当前奇数的位置 16 array[j] = temp; 17 } 18 } 19 } 20 }
leetcode 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面(不需维持相对顺序)
思路一:首尾双指针
双指针,一个指针从前往后,每当碰到偶数就停下,另一个指针从后往前,每当碰到奇数就停下,然后进行奇偶交换,有点像快排的一次 partition操作
1 class Solution { 2 public int[] exchange(int[] nums) { 3 // 双指针,一个指针从前往后,每当碰到偶数就停下,另一个指针从后往前,每当碰到奇数就停下 4 // 奇偶交换 5 int left = 0, right = nums.length - 1; 6 while(left < right){ 7 while(left < right && (nums[left] & 1) != 0){ // 奇数跳过,偶数停下来 8 left++; 9 } 10 while(left < right && (nums[right] & 1) == 0){ // 偶数跳过,奇数停下来 11 right--; 12 } 13 int temp = nums[left]; 14 nums[left] = nums[right]; 15 nums[right] = temp; 16 } 17 return nums; 18 } 19 }
leetcode运行时间为2ms - 99.77%, 空间为46.8MB - 32.27%
复杂度分析:
时间复杂度:遍历整个数组,所以时间复杂度为O(n)
空间复杂度:因为是在原数组是上直接操作的,所以空间复杂度为O(1)
思路二:快慢指针
快慢指针,快指针,low在后,fast在前,low指向下个奇数应该存放的位置,fast寻找下个奇数
fast找到奇数后,与low对应的元素进行交换,随后low++, 表示下个奇数的位置应该是下个位置
如果low指向的位置刚好是奇数则交换自己
一直循环,直到fast到达尾部
1 class Solution { 2 public int[] exchange(int[] nums) { 3 4 int low = 0, fast = 0, tmp = 0; 5 while(fast < nums.length){ 6 if((nums[fast] & 1) == 1){ 7 tmp = nums[fast]; 8 nums[fast] = nums[low]; 9 nums[low] = tmp; 10 low++; // 随后low++, 表示下个奇数的位置应该是下个位置 11 } 12 fast++; // fast++表示继续寻找奇数 13 } 14 return nums; 15 } 16 }
leetcode运行时间为2ms - 99.77%, 空间为46.8MB - 32.27%
复杂度分析:
时间复杂度:fast指针遍历了整个数组,所以时间复杂度为O(n)
空间复杂度:因为是在原数组是上直接操作的,所以空间复杂度为O(1)