剑指offer 13.调整数组顺序使奇数位于偶数前面 & leetcode 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

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)

 

posted @ 2020-03-26 20:33  Lucky小黄人^_^  阅读(214)  评论(0编辑  收藏  举报