zoukankan      html  css  js  c++  java
  • 调整数组顺序使奇数位于偶数前面

    题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为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	", numbers[i]);
     77     
     78     printf("
    ");
     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:
    ");
     87     PrintArray(numbersOne, lengthOne);
     88     ReorderOddEven_1(numbersOne,lengthOne);
     89     PrintArray(numbersOne, lengthOne);
     90     printf("
    ");
     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:
    ");
     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	", numbers[i]);
    45     
    46     printf("
    ");
    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 }

  • 相关阅读:
    SQL——模糊查询LIKE
    SQL——表连接JOIN
    【转】Java MySQL数据类型对照
    Java精确计算小数
    zTree 勾选checkbox
    【转】Freemarker输出$和html标签等特殊符号
    freemarker(FTL)常见语法大全
    【转载】浏览器与服务器通信的过程
    python基础 常见用法
    360浏览器兼容性问题
  • 原文地址:https://www.cnblogs.com/sankexin/p/5616185.html
Copyright © 2011-2022 走看看