调整数组顺序使奇数位于偶数前面
Posted 三颗心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调整数组顺序使奇数位于偶数前面相关的知识,希望对你有一定的参考价值。
题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
分析:如果不考虑时间复杂度,最简单的思路应该是从头扫描这个数组,每碰到一个偶数时,拿出这个数字,并把位于这个数字后面的所有数字往前挪动一位。挪完之后在数组的末尾有一个空位,这时把该偶数放入这个空位。由于碰到一个偶数,需要移动O(n)个数字,因此总的时间复杂度是O(n2)。
要求的是把奇数放在数组的前半部分,偶数放在数组的后半部分,因此所有的奇数应该位于偶数的前面。也就是说我们在扫描这个数组的时候,如果发现有偶数出现在奇数的前面,我们可以交换他们的顺序,交换之后就符合要求了。
因此我们可以维护两个指针,第一个指针初始化为数组的第一个数字,它只向后移动;第二个指针初始化为数组的最后一个数字,它只向前移动。在两个指针相遇之前,第一个指针总是位于第二个指针的前面。如果第一个指针指向的数字是偶数而第二个指针指向的数字是奇数,我们就交换这两个数字。
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 }
以上是关于调整数组顺序使奇数位于偶数前面的主要内容,如果未能解决你的问题,请参考以下文章