【问题标题】:Sorting odd in descending and even in ascending order奇数降序和偶数升序排序
【发布时间】:2010-05-23 02:41:38
【问题描述】:

给定一个随机整数数组,奇数元素降序排列,偶数元素升序排列。

示例输入:(1,4,5,2,3,6,7)
输出:(7,5,3,1,2,4,6)

针对时间复杂度进行优化。

【问题讨论】:

  • 那你在问什么?如何优化它?人们通常会在愿意帮助您之前欣赏某种尝试。 (即发布一些代码,人们会很乐意帮助您优化它)
  • 一道“微软面试题”geeksforgeeks.org/forum/topic/…
  • 你试过什么?你为什么不喜欢你的第一个解决方案?您认为优化是什么?您对此考虑的具体问题是什么?
  • O(n) 做一个基数排序,你可以免费得到偶数/奇数分裂。

标签: c# c++ c


【解决方案1】:

它是哪种语言,C 或 C++(我看到两个标签)

在 C++ 中,您可以使用 std::sort() 和适当的排序函数。在 C 中,qsort() 的工作方式类似:

#include <iostream>
#include <algorithm>
bool Order(int a, int b)
{
        if (a%2 != b%2) return a%2;
        else return a%2 ? b<a : a<b;
}
int main()
{
        int a[] = {1,4,5,2,3,6,7};
        size_t N = sizeof(a) / sizeof(a[0]);

        std::sort(a, a+N, Order);

        for(size_t i=0; i<N; ++i)
                std::cout << a[i] << ' ';
        std::cout << std::endl;

}

【讨论】:

  • 当我看到有符号整数与模运算符结合时,我总是很怀疑。您的解决方案是否适用于负数?
  • 在我可以测试它的编译器上,但你是对的,当然,它是在 C++ 中定义的 5.6/4 [expr.mul] 的实现,并带有一个脚注,即舍入为零是首选..
【解决方案2】:

这是一个 c# 单行代码:

int[] x = { 1,4,5,2,3,6,7 };
Array.Sort(x, (a, b) => a % 2 == 0 ? b % 2 == 0 ? a.CompareTo(b) : 1 : b % 2 == 0 ? -1 : -1 * a.CompareTo(b));

不要把它交给你的老师。您的老师希望看到您自己实现排序算法,因此他知道您可以做到并且知道您了解所涉及的内容。

在实践中,您(几乎)永远不会在工作中这样做。您的平台已经具有高度优化的排序方法,并且您希望利用这些方法,无论是 C# 的 Array.Sort().OrderBy() 还是 C++ stl 算法。这段代码是为了向你展示如何在现实世界中解决这个问题,尽管如果我想让它通过代码审查,我可能不会把它全部压缩在一行中。

【讨论】:

    【解决方案3】:

    使用整数作为排序目标,您可以使用计数排序将其变为 O(n) 排序并稍加注意。

    【讨论】:

    • 计数排序?!?是的,O(n)...如果您不介意 2^32 左右的隐含常数。
    • 好的,让我将其更改为字节而不是整数 - 我读取了他的范围并假定了字节。我的错。顺便说一句,4n 如果你在 4 遍中完成...
    • 问题:我正在查看一个版本的 OP(是的,一个二手转给我的面试问题),其中所需的数据结构是一个链表。在这种情况下,计数排序似乎适用吗?我也在阅读这个相关的答案 (stackoverflow.com/questions/14368392/…)。
    • 只要在通过链表读取值时将值放入数组存储桶中,应该仍然可以。 “从链表中读取所有值,进行排序,用新值重建链表。”效率不高,因为这不是链表的本意,但可能。
    【解决方案4】:

    只是提供一个替代解决方案:

    #include <algorithm>
    #include <functional>
    
    bool is_odd(int x)
    {
        return x & 1;
    }
    
    int* rushakoff(int* begin, int* end)
    {
        int* middle = std::partition(begin, end, is_odd);
        std::sort(begin, middle, std::greater<int>());
        std::sort(middle, end, std::less<int>());
        return middle;
    }
    
    int main()
    {
        int array[] = {1,4,5,2,3,6,7};
        rushakoff(array, array + 7);
    }
    

    也许不是那么理想,但可读性很强。这也很重要;-)

    【讨论】:

      【解决方案5】:

      曾几何时,此代码将被添加到 SO 文档项目中。那时还没有文档项目,所以现在可以放在这里了。这是不悔改的 C 代码。

      关于将奇数和偶数分开排序的主题有很多变体:

      1. 奇数先升后降
      2. 奇数降序偶数升序
      3. 偶数先升后降
      4. 偶数下降前奇数上升
      5. 奇数先升后升
      6. 奇数降序先于偶数降序
      7. 偶数先升后升
      8. 奇数下降前偶数下降

      下面的代码显示了选项 1-4 - 选项 5-8 很容易从中创建(不要对奇数与偶数进行最终测试;选择正确的升序或降序比较):

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      
      /* odd numbers in ascending order before even numbers in descending order */
      static int oddasc_evendesc(const void *vp1, const void *vp2)
      {
          int v1 = *(int *)vp1;
          int v2 = *(int *)vp2;
          if ((v1 & 1) != (v2 & 1))
          {
              /* One odd, one even */
              if (v1 & 1)
                  return -1;      /* Odd is smaller */
              return +1;
          }
          /* Both odd or both even */
          if ((v1 & 1) == 1)
              return (v1 < v2) ? -1 : (v1 > v2) ? +1 : 0;     /* Ascending */
          return (v1 < v2) ? +1 : (v1 > v2) ? -1 : 0;         /* Descending */
      }
      
      /* even numbers descending before odd numbers ascending */
      static int evendesc_oddasc(const void *vp1, const void *vp2)
      {
          int v1 = *(int *)vp1;
          int v2 = *(int *)vp2;
          if ((v1 & 1) != (v2 & 1))
          {
              /* One odd, one even */
              if (v1 & 1)
                  return +1;      /* Odd is larger */
              return -1;
          }
          /* Both odd or both even */
          if ((v1 & 1) == 1)
              return (v1 > v2) - (v1 < v2);     /* Ascending */
          return (v1 < v2) - (v1 > v2);         /* Descending */
      }
      
      /* odd numbers in descending order before even numbers in ascending order */
      static int odddesc_evenasc(const void *vp1, const void *vp2)
      {
          int v1 = *(int *)vp1;
          int v2 = *(int *)vp2;
          if ((v1 & 1) != (v2 & 1))
          {
              /* One odd, one even */
              if (v1 & 1)
                  return -1;      /* Odd is smaller */
              return +1;
          }
          /* Both odd or both even */
          if ((v1 & 1) == 1)
              return (v1 < v2) ? +1 : (v1 > v2) ? -1 : 0;     /* Descending */
          return (v1 < v2) ? -1 : (v1 > v2) ? +1 : 0;         /* Ascending */
      }
      
      /* even numbers ascending before odd numbers descending */
      static int evenasc_odddesc(const void *vp1, const void *vp2)
      {
          int v1 = *(int *)vp1;
          int v2 = *(int *)vp2;
          if ((v1 & 1) != (v2 & 1))
          {
              /* One odd, one even */
              if (v1 & 1)
                  return +1;      /* Odd is larger */
              return -1;
          }
          /* Both odd or both even */
          if ((v1 & 1) == 1)
              return (v1 < v2) - (v1 > v2);     /* Descending */
          return (v1 > v2) - (v1 < v2);         /* Ascending */
      }
      
      static void dump_array(const char *tag, int num, int *data)
      {
          printf("%s:\n", tag);
          int i;
          const char *pad = "";
          for (i = 0; i < num; i++)
          {
              printf("%s%+3d", pad, data[i]);
              pad = " ";
              if (i % 10 == 9)
              {
                  putchar('\n');
                  pad = "";
              }
          }
          if (i % 10 != 0)
              putchar('\n');      /* End partial line */
          putchar('\n');          /* Blank line */
      }
      
      int main(void)
      {
          int data1[] =
          {
              /* random -n 80 -- -99 99 | commalist -b '        ' -n 10 */
              +39, +36, +78, -92, +63, -21, -51, +49,   0, -77,
              -10, -49, -98, -17, +60, +83, +30, -97, -68, +86,
              +70, +84, -56,  +3, +33, -34, +14, -40, -72, -86,
              -95, -87, -73, -20, -72, -86,  -3, -71, -55, -80,
              -60,  -4, -26, -64, -31, -84, -79, +25, +41, +80,
              -54, -51, +24, -48, +13, +61, -99, +60,  -2, +16,
              -66, -30, +24, +88,  +5, -77, +13,  +3, +16, -69,
              -60, +26, +51, +16, -13, +71,  -9,  -2, +51, +72,
          };
          enum { NUM_DATA = sizeof(data1) / sizeof(data1[0]) };
          int data2[NUM_DATA];
          int data3[NUM_DATA];
          int data4[NUM_DATA];
      
          memmove(data2, data1, sizeof(data1));
          memmove(data3, data1, sizeof(data1));
          memmove(data4, data1, sizeof(data1));
      
          printf("Sort odd numbers ascending before even numbers descending\n");
          dump_array("Before", NUM_DATA, data1);
          qsort(data1, NUM_DATA, sizeof(data1[0]), oddasc_evendesc);
          dump_array("After", NUM_DATA, data1);
      
          printf("Sort even numbers descending before odd numbers ascending\n");
          dump_array("Before", NUM_DATA, data2);
          qsort(data2, NUM_DATA, sizeof(data2[0]), evendesc_oddasc);
          dump_array("After", NUM_DATA, data2);
      
          printf("Sort odd numbers descending before even numbers ascending\n");
          dump_array("Before", NUM_DATA, data3);
          qsort(data3, NUM_DATA, sizeof(data3[0]), odddesc_evenasc);
          dump_array("After", NUM_DATA, data3);
      
          printf("Sort even numbers ascending before odd numbers descending\n");
          dump_array("Before", NUM_DATA, data4);
          qsort(data4, NUM_DATA, sizeof(data4[0]), evenasc_odddesc);
          dump_array("After", NUM_DATA, data4);
      
          return 0;
      }
      

      输出:

      Sort odd numbers ascending before even numbers descending
      Before:
      +39 +36 +78 -92 +63 -21 -51 +49  +0 -77
      -10 -49 -98 -17 +60 +83 +30 -97 -68 +86
      +70 +84 -56  +3 +33 -34 +14 -40 -72 -86
      -95 -87 -73 -20 -72 -86  -3 -71 -55 -80
      -60  -4 -26 -64 -31 -84 -79 +25 +41 +80
      -54 -51 +24 -48 +13 +61 -99 +60  -2 +16
      -66 -30 +24 +88  +5 -77 +13  +3 +16 -69
      -60 +26 +51 +16 -13 +71  -9  -2 +51 +72
      
      After:
      -99 -97 -95 -87 -79 -77 -77 -73 -71 -69
      -55 -51 -51 -49 -31 -21 -17 -13  -9  -3
       +3  +3  +5 +13 +13 +25 +33 +39 +41 +49
      +51 +51 +61 +63 +71 +83 +88 +86 +84 +80
      +78 +72 +70 +60 +60 +36 +30 +26 +24 +24
      +16 +16 +16 +14  +0  -2  -2  -4 -10 -20
      -26 -30 -34 -40 -48 -54 -56 -60 -60 -64
      -66 -68 -72 -72 -80 -84 -86 -86 -92 -98
      
      Sort even numbers descending before odd numbers ascending
      Before:
      +39 +36 +78 -92 +63 -21 -51 +49  +0 -77
      -10 -49 -98 -17 +60 +83 +30 -97 -68 +86
      +70 +84 -56  +3 +33 -34 +14 -40 -72 -86
      -95 -87 -73 -20 -72 -86  -3 -71 -55 -80
      -60  -4 -26 -64 -31 -84 -79 +25 +41 +80
      -54 -51 +24 -48 +13 +61 -99 +60  -2 +16
      -66 -30 +24 +88  +5 -77 +13  +3 +16 -69
      -60 +26 +51 +16 -13 +71  -9  -2 +51 +72
      
      After:
      +88 +86 +84 +80 +78 +72 +70 +60 +60 +36
      +30 +26 +24 +24 +16 +16 +16 +14  +0  -2
       -2  -4 -10 -20 -26 -30 -34 -40 -48 -54
      -56 -60 -60 -64 -66 -68 -72 -72 -80 -84
      -86 -86 -92 -98 -99 -97 -95 -87 -79 -77
      -77 -73 -71 -69 -55 -51 -51 -49 -31 -21
      -17 -13  -9  -3  +3  +3  +5 +13 +13 +25
      +33 +39 +41 +49 +51 +51 +61 +63 +71 +83
      
      Sort odd numbers descending before even numbers ascending
      Before:
      +39 +36 +78 -92 +63 -21 -51 +49  +0 -77
      -10 -49 -98 -17 +60 +83 +30 -97 -68 +86
      +70 +84 -56  +3 +33 -34 +14 -40 -72 -86
      -95 -87 -73 -20 -72 -86  -3 -71 -55 -80
      -60  -4 -26 -64 -31 -84 -79 +25 +41 +80
      -54 -51 +24 -48 +13 +61 -99 +60  -2 +16
      -66 -30 +24 +88  +5 -77 +13  +3 +16 -69
      -60 +26 +51 +16 -13 +71  -9  -2 +51 +72
      
      After:
      +83 +71 +63 +61 +51 +51 +49 +41 +39 +33
      +25 +13 +13  +5  +3  +3  -3  -9 -13 -17
      -21 -31 -49 -51 -51 -55 -69 -71 -73 -77
      -77 -79 -87 -95 -97 -99 -98 -92 -86 -86
      -84 -80 -72 -72 -68 -66 -64 -60 -60 -56
      -54 -48 -40 -34 -30 -26 -20 -10  -4  -2
       -2  +0 +14 +16 +16 +16 +24 +24 +26 +30
      +36 +60 +60 +70 +72 +78 +80 +84 +86 +88
      
      Sort even numbers ascending before odd numbers descending
      Before:
      +39 +36 +78 -92 +63 -21 -51 +49  +0 -77
      -10 -49 -98 -17 +60 +83 +30 -97 -68 +86
      +70 +84 -56  +3 +33 -34 +14 -40 -72 -86
      -95 -87 -73 -20 -72 -86  -3 -71 -55 -80
      -60  -4 -26 -64 -31 -84 -79 +25 +41 +80
      -54 -51 +24 -48 +13 +61 -99 +60  -2 +16
      -66 -30 +24 +88  +5 -77 +13  +3 +16 -69
      -60 +26 +51 +16 -13 +71  -9  -2 +51 +72
      
      After:
      -98 -92 -86 -86 -84 -80 -72 -72 -68 -66
      -64 -60 -60 -56 -54 -48 -40 -34 -30 -26
      -20 -10  -4  -2  -2  +0 +14 +16 +16 +16
      +24 +24 +26 +30 +36 +60 +60 +70 +72 +78
      +80 +84 +86 +88 +83 +71 +63 +61 +51 +51
      +49 +41 +39 +33 +25 +13 +13  +5  +3  +3
       -3  -9 -13 -17 -21 -31 -49 -51 -51 -55
      -69 -71 -73 -77 -77 -79 -87 -95 -97 -99
      

      此代码在 GitHub 上我的 SOQ(堆栈溢出问题)存储库中作为文件 oddascevendesc.c(现在用词不当)在 doc/qsort 子目录。

      【讨论】:

        【解决方案6】:
        // Sort with a custom comparison function
        // returns -1 if a before b, 0 if a==b, 1 if a after b
        int _cmp(a,b) {
          if (a % 2) == 0 {
            if (b % 2) == 0 {
              return (a>b) ? 1 : (a==b) 0 : -1; # Even(a) vs Even(b)
            } else {
              return 1; # Even(a) vs Odd(b) all evens are after all odds
            }
          } else {
            if (b % 2) == 0 {
              return -1; # Odd(a) vs Even(b) all odds are before all evens
            } else {
              return (b>a) ? 1 : (a==b) 0 : -1; # Odd(a) vs Odd(b) has reverse order
            }
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-09-08
          • 2022-12-13
          • 1970-01-01
          • 2022-01-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多