[C#] 腾讯面试题(除掉N个整数中重复数)解题(线性时间,原地置换排序算法)(C#) →→→→→进入此内容的聊天室

来自 , 2020-08-03, 写在 C#, 查看 142 次.
URL http://www.code666.cn/view/aee1bc7f
  1.     //下面的思路没问题,但算法有问题,修正后的算法见后面.
  2.         /// <summary>
  3.         /// 需要除掉重复的整数的数组,注意这里我没有处理负数情况,
  4.         /// 其实负数情况只要先用0快排分一下组,然后各自用以下算法进行处理即可。
  5.         /// 另外因为是整数,这里没考虑32位符号位,只考虑31位。
  6.         /// 题目分析:从要求来看,如果一个数组是排好序的,除掉重复就很简单,因此就转换成了
  7.         /// 排序算法寻找,这种算法需要满足:线性时间,常量内存,原地置换。但纵观这么多算法,比较排序肯定不行,
  8.         /// 那么就只有基数排序,桶排序和计数排序,但基数排序依赖于位排序,而且要求位排序是稳定的,
  9.         /// 且不能过多使用辅助空间,计数排序排除,因为计数排序无法原地置换,桶排序也需要辅助空间,所以最后考虑用
  10.         /// 基数排序。但问题是如何选择位排序,因为位上只有0和1,因此有其特殊性,使用快排的分组就可以达到线性,
  11.         /// 但问题是这种算法虽然是线性,原地置换,但不稳定。所以要利用一种机制来确保快排是稳定的。经过一段时间思考,
  12.         /// 发现,如果从高位开始排序,假设前K位是排好的,对K+1进行排序时,只针对前K位的相同的进行,前K位不相同,也不可
  13.         /// 能相等,第K+1位也不影响结果,而前K位相同的排序,就不怕快排的不稳定了,因为这个不稳定不会影响到最终结果。
  14.         /// 下面就是算法:
  15.         /// </summary>
  16.         /// <param name="A"></param>
  17.         private void BitSortAndDelRepeatorsA(int[] A)
  18.         {
  19.             //获取数组长度
  20.             int theN = A.Length;
  21.             //从高位到低位开始排序,这里从31位开始,32位是符号位不考虑,或者单独考虑。
  22.             for (int i = 31; i >= 1; i--)
  23.             {
  24.                 //当前排序之前的值,只有该值相同才进行快排分组,如果不相同,则重新开始另外一次快排
  25.                 //这很关键,否则快排的不稳定就会影响最后结果.
  26.                 int thePrvCB = A[0] >> (i)  ;
  27.                 //快排开始位置,会变化
  28.                 int theS = 0;
  29.                 //快排插入点
  30.                 int theI = theS;
  31.                 //整数基元,就选择快排开始位置的数.
  32.                 int theAxNum = A[theI];
  33.                 //2进制基数,用于测试某一位是否为0
  34.                 int theBase = 1 << (i-1);
  35.                 //位基元,
  36.                 int theAxBit = (theAxNum >> (i-1)) & 1;//(A[theI] & (theBase)) > 0 ? 1 : 0;
  37.                 //分段快排,但总体上时间复杂度与快排分组一样.
  38.                 for (int j = 1; j < theN; j++)
  39.                 {
  40.                     //获取当前数组值的前面已拍过序的位数值。
  41.                     int theTmpPrvCB = A[j] >> (i);
  42.                     //如果前面已排过的位不相同,则重新开始一次快排.
  43.                     if (theTmpPrvCB != thePrvCB)
  44.                     {
  45.                         A[theS] = A[theI];
  46.                         A[theI] = theAxNum;
  47.                         theS = j;
  48.                         theI = theS;
  49.                         theAxNum = A[theI];
  50.                         theAxBit = A[theI] & theBase;
  51.                         thePrvCB = theTmpPrvCB;
  52.                         continue;
  53.                     }
  54.                     //如果相同,则按快排处理
  55.                     int theAJ = (A[j] >> (i - 1)) & 1;//(A[j] & (theBase)) > 0 ? 1 : 0;
  56.                     if (theAJ <= theAxBit)
  57.                     {
  58.                         theI++;
  59.                         int theTmp = A[j];
  60.                         A[j] = A[theI];
  61.                         A[theI] = theTmp;
  62.                     }
  63.                 }
  64.                 //注意最后一次交换。
  65.                 A[theS] = A[theI];
  66.                 A[theI] = theAxNum;
  67.             }
  68.         }
  69.  
  70.  
  71. //csharp/6213

回复 "腾讯面试题(除掉N个整数中重复数)解题(线性时间,原地置换排序算法)(C#)"

这儿你可以回复上面这条便签

captcha