调整数组顺序使奇数位于偶数前面

Posted 三颗心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调整数组顺序使奇数位于偶数前面相关的知识,希望对你有一定的参考价值。

题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)。

分析:如果不考虑时间复杂度,最简单的思路应该是从头扫描这个数组,每碰到一个偶数时,拿出这个数字,并把位于这个数字后面的所有数字往前挪动一位。挪完之后在数组的末尾有一个空位,这时把该偶数放入这个空位。由于碰到一个偶数,需要移动O(n)个数字,因此总的时间复杂度是O(n)。

要求的是把奇数放在数组的前半部分,偶数放在数组的后半部分,因此所有的奇数应该位于偶数的前面。也就是说我们在扫描这个数组的时候,如果发现有偶数出现在奇数的前面,我们可以交换他们的顺序,交换之后就符合要求了。

因此我们可以维护两个指针,第一个指针初始化为数组的第一个数字,它只向后移动;第二个指针初始化为数组的最后一个数字,它只向前移动。在两个指针相遇之前,第一个指针总是位于第二个指针的前面。如果第一个指针指向的数字是偶数而第二个指针指向的数字是奇数,我们就交换这两个数字。

  1 #include<stdio.h>
  2 #include<tchar.h>
  3 
  4 void Reorder(int *pData, unsigned int length, bool (*func)(int));
  5 bool isEven(int n);
  6 
  7 /*思路:使用两个指针,一个指向数组的一个数字,只向后移动,
  8 一个指向数组的最后一个数字, 只向前移动,再两个指针相遇前,
  9 如果第一个指针指向的是偶数,第二个指向的是奇数,就交换这两个数字
 10 */ 
 11 void ReorderOddEven_1(int *pData, unsigned int length)
 12 {
 13     if(pData == NULL || length == 0)
 14         return;
 15     
 16     int *pBegin = pData;
 17     int *pEnd = pData + length - 1;
 18     
 19     while(pBegin < pEnd)
 20     {
 21         while(pBegin < pEnd && (*pBegin & 0x1) != 0)
 22             pBegin ++;
 23         while(pBegin < pEnd && (*pEnd & 0x1) == 0)
 24             pEnd --;
 25         
 26         if(pBegin < pEnd)
 27         {
 28             int temp = *pBegin;
 29             *pBegin = *pEnd;
 30             *pEnd = temp;
 31         }
 32     }
 33 }
 34 
 35 //方法2和方法1思路是一样的,只是将方法1的函数给解耦成两部分,提高了代码的复用性。 
 36 void ReorderOddEven_2(int *pData, unsigned int length)
 37 {
 38     Reorder(pData, length, isEven);
 39 }
 40 
 41 void Reorder(int *pData, unsigned int length, bool (*func)(int))
 42 {
 43     if(pData == NULL || length == 0) 
 44         return;
 45     
 46     int *pBegin = pData;
 47     int *pEnd = pData + length - 1;
 48     
 49     while(pBegin < pEnd)
 50     {
 51         while(pBegin < pEnd && !func(*pBegin))
 52             pBegin ++;
 53         
 54         while(pBegin < pEnd && func(*pEnd))
 55             pEnd --;
 56         
 57         if(pBegin < pEnd)
 58         {
 59             int temp = *pBegin;
 60             *pBegin = *pEnd;
 61             *pEnd = temp;
 62         }
 63     }
 64 }
 65 
 66 bool isEven(int n)
 67 {
 68     return (n & 1) == 0;
 69 }
 70 
 71 void PrintArray(int numbers[], int length)
 72 {
 73     if(length < 0)
 74         return;
 75     for(int i = 0 ; i < length ; ++i)
 76         printf("%d\\t", numbers[i]);
 77     
 78     printf("\\n");
 79 }
 80 
 81 int main()
 82 {
 83     //使用方法1测试 
 84     int numbersOne[] = {1, 2, 3, 4, 5, 6, 7};
 85     int lengthOne = sizeof(numbersOne) / sizeof(int);
 86     printf("Test for solution 1:\\n");
 87     PrintArray(numbersOne, lengthOne);
 88     ReorderOddEven_1(numbersOne,lengthOne);
 89     PrintArray(numbersOne, lengthOne);
 90     printf("\\n");
 91     
 92     //使用方法2测试 
 93     int numbersTwo[] = {2, 4, 6, 1, 3, 5, 7};
 94     int lengthTwo = sizeof(numbersTwo) / sizeof(int);
 95     printf("Test for solution 2:\\n");
 96     PrintArray(numbersTwo,lengthTwo);
 97     ReorderOddEven_2(numbersTwo,lengthTwo);
 98     PrintArray(numbersTwo, lengthTwo);
 99     
100     return 0 ;
101 }

 

 

还有一种思路,使用两个指针,一个在前一个在后,当在前的遇到奇数时,就和在后的数进行交换。有一个细节是,若数组一开始就是奇数,则在前的和在和的指向的是同一个数,交换后数组不变,直到遇到第一个偶数时,在前的指针超过在后的指针。

 1 #include<iostream>
 2 //#include<algorithm>    可省略swap 
 3 using namespace std;
 4 
 5 void swap(int* num1, int* num2) 
 6 {
 7     int temp = *num1;
 8     *num1 = *num2;
 9     *num2 = temp;
10 }
11 bool isEven(int n)
12 {
13     return (n & 1)==0;
14 }
15 
16 void Reorder(int *pData, unsigned int length, bool (*func)(int))
17 {
18     if(length < 0 || pData == NULL)
19         return; 
20     else{
21         int i = -1;
22         for(int j =0 ; j < length; j++)
23         {
24             /*当数组中的数字为奇数时,交换i,j指向的两个数字
25             当起始数字为奇数时,此时交换的数字是相同的,
26             当中间有偶数时,条件语句不满足,跳过,此时j继续增加,i不变,
27              然后遇到奇数时,j指向奇数,满足条件,i指向前一个奇数,i++后,
28              此时i指向此奇数后面的偶数,交换两数。 
29              */ 
30             if(!func(*(pData+j))) 
31             {
32                 i++;
33                 swap(*(pData+i), *(pData+j));
34             }
35         }
36     }
37 }
38 
39 void PrintArray(int numbers[], int length)
40 {
41     if(length < 0)
42         return;
43     for(int i = 0 ; i < length ; ++i)
44         printf("%d\\t", numbers[i]);
45     
46     printf("\\n");
47 }
48 
49 int main()
50 {
51     int numbers[] = {3,4,5,6,7,8,9,10,1,2};
52     int length = sizeof(numbers) / sizeof(int);
53     
54     PrintArray(numbers, length) ;
55 
56     Reorder(numbers, length, isEven);
57 
58     PrintArray(numbers, length);
59     
60     return 0;
61 }

以上是关于调整数组顺序使奇数位于偶数前面的主要内容,如果未能解决你的问题,请参考以下文章

《剑指Offer》题目:调整数组顺序使奇数位于偶数前面

代码的完整性:调整数组顺序使奇数位于偶数前面

数组:调整数组顺序使奇数位于偶数前面

调整数组顺序使奇数位于偶数前面

求调整数组顺序使奇数位于偶数前面

剑指Offer调整数组顺序使奇数位于偶数前面