算法数据结构面试分享(六)数组排序问题(2) - 计数排序

数组排序问题(2)

昨天我们留了一道题目“给你一个整型数组,里面出现的数在[0-100] 之间,能用最优化的方法帮我排序吗”。

1. 确保我们理解了问题,并且尝试一个例子,确认理解无误.

这是一道排序算法题,我们学过很多排序的算法。不一样的是,它给定一个额外的条件,数组里的每个数字都在1-100之间。如果我们采取传统的排序算法,这个条件我们好像用不上。大家在面试的时候如果发现有条件没有用上,基本上我们给出的算法可能不是最优的,或者我们没有解决它最原始的需求。举个例子{50, 46, 50, 0, 100,0} 这个数组中,我们一眼就能看出来 0 有两个, 46有一个,50有两个,100有一个,我们再把他们拼接起来,我们就会得到 {0,0, 46, 50, 50,100}。

2. 想想你可以用什么方法解决问题,你会选择哪一种,为什么?

在上面的分析中我们能够总结出来,我们人工去排序的时候涉及到了两个重要的步骤。1:统计0 - 100 之间每一个数出现的次数: 2: 从0 - 100 的顺序按照他们出现的次数拼接出来。所以现在我们需要解决的问题如何方便计数了。申明一个数字,长度为101,假设50出现了一次,我们就把该数组中下标为50的位置加上1. 全部计数完了,我们再扫描这个数字,将结果写回。
我们现在看一下它的复杂度,我们扫描了原数组一次,又扫描了计数数组一次,所以我们的复杂度是O(n). 这里大家也发现,我们这道题中体现了一个原则,用空间换时间。

3. 解释你的算法和实现的方法

计数部分:扫描原数组, 在index数组中找到对应的位置

int[] indexArray = new int[100];
foreach(var e in inputArray)
{
  indexArray[e] ++;
}

合并数组部分

int count = 0;

for(int index = 0; index < indexArray.Length; index++)
{
if(indexArray[index] > 0 ) //说明index的数字出现过,我们需要拼接起来,出现了几次我们就加几个数
 {
  inputArray[count] = index;
  count ++;
  }
}

4. 写代码的时候,记住,一定要解释你现在在干什么

那我们就直接上代码啦。
       /// <summary>
       /// 给数组排序,该数组里的值在0-100之间
       /// </summary>
       /// <param name="array"></param>
       public static void IndexSort(int[] array)
       {
           int[] indexArray = new int[101];  

           for (var index = 0; index < indexArray.Length; index++)
           {
               indexArray[index] = 0;
           }  

           foreach (var e in array)
           {
               indexArray[e]++;
           }  

           int count = 0;
           for (int index = 0; index < indexArray.Length; index++)
           {
               if (indexArray[index] > 0)
               {
                   for (int elementCount = 0; elementCount < indexArray[index]; elementCount++)
                   {
                       array[count++] = index;
                   }
               }
           }
       }  

大家有没有发现,上面的代码其实可以优化,会体现你的基本功哦。要装逼的话可以和面试官提出来的哦。int的默认值是0,所以我们没有必要扫描它一遍给它赋个默认值了。所以这段代码是多余的:

[csharp] view plain copy
for (var index = 0; index < indexArray.Length; index++)
{
   indexArray[index] = 0;
}  

我们来测试一下这个方法:

[csharp] view plain copy
static void Main(string[] args)
  {
      int[] array = new int[] { 100, 8, 0, 7, 0, 34 };  

      IndexSort(array);  

      foreach(var e in array)
      {
          Console.Write(e + " " );
      }
  }  

5. 我们得到的结果:

大功告成了哈。 如果大家对以上的算法有什么疑问,或者更好的解法,欢迎交流。


大家有什么更好的解法,也欢迎讨论哈。

链表、排序专题讲解了解更多资源。

关注我们的公众号,获取定期推送。关注课程,定期会有优惠哦。

原文地址:http://blog.51cto.com/8140370/2125744

时间: 2024-10-01 20:45:58

算法数据结构面试分享(六)数组排序问题(2) - 计数排序的相关文章

计数排序 - 算法数据结构面试分享(五)

数组排序问题 - 计数排序 昨天我们留了一道题目"给你一个整型数组,里面出现的数在[0-100] 之间,能用最优化的方法帮我排序吗". 1. 确保我们理解了问题,并且尝试一个例子,确认理解无误. 这是一道排序算法题,我们学过很多排序的算法.不一样的是,它给定一个额外的条件,数组里的每个数字都在1-100之间.如果我们采取传统的排序算法,这个条件我们好像用不上.大家在面试的时候如果发现有条件没有用上,基本上我们给出的算法可能不是最优的,或者我们没有解决它最原始的需求.举个例子{50, 4

算法数据结构面试分享(一)- 解决算法问题的一般方法

先看一道题目: 给你一个整型数组,我想找出来最大的两个数,能帮我写一个算法吗?     拿到这个题目,大家会怎么想到用什么方法解决吗?我见过很多同学的回答是,先排序,取最大的两个数就好了.那么接下来我们的问题就变成了如何给这个整型数组排序了.我们有很多种方法,冒泡排序,快速排序等等.很有可能面试官就让你开始写具体的排序算法了.当然,有些有经验的同学可能会说了,排序我直接调用sort方法就好了哈.  其实,这两种情况都没有对错之分,只是没有敲开面试官的心扉,也没有给人眼前一亮,让自己脱颖而出. 再

十种常见的排序算法,面试算法必考

1.冒泡排序 已知一组无序数据a[1].a[2].……a[n],需将其按升序排列.首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变.再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变.再比较a[3]与a[4],以此类推,最后比较a[n-1]与a[n]的值.这样处理一轮后,a[n]的值一定是这组数据中最大的.再对a[1]~a[n-1]以相同方法处理一轮,则a[n-1]的值一定是a[1]~a[n-1]中最大的.再对a[1]~a[n-2]以相同方

用计数法解决数组排序问题

package 数组; public class 计数排序 { public static void main(String[] args) { int[] num1={10,20,80,30,5,58,95}; int len=num1.length; int []num2=new int[len]; int n; for(int i=0;i<len;i++){ n=0; for(int j=0;j<len;j++){ if (num1[i]>num1[j]){n++;} //确定该数

非基于比较的排序算法之一:计数排序

计数排序(Counting sort)是一种稳定的排序算法.计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值小于等于i的元素的个数.然后根据数组C来将A中的元素排到正确的位置. 限制:所有值得取值范围不能太大,并且需要知道确切的取值范围.本算法需要的辅助空间要求较高. 当输入的元素是 n 个 0 到 k 之间的整数时,它的运行时间是 Θ(n + k).计数排序不是比较排序,排序的速度快于任何比较排序算法. 现在给出C#实现的计数排序(counting sort) public vo

计数排序(counting-sort)&mdash;&mdash;算法导论(9)

1. 比较排序算法的下界 (1) 比较排序     到目前为止,我们已经介绍了几种能在O(nlgn)时间内排序n个数的算法:归并排序和堆排序达到了最坏情况下的上界:快速排序在平均情况下达到该上界.     如果仔细观察,我们会发现:在排序的最终结果中,各元素之间的次序依赖于它们之间的比较.我们把这类排序算法统称为比较排序.到目前为止我们介绍的排序算法都是比较排序.下面我们来论证一个事实:任何比较排序算法在最坏情况下都要经过Ω(n lgn)次比较. (2) 决策树模型     在证明之前,我们先介

C/C++ 数据结构之算法(面试)

数据结构中的排序算法. 排序算法的相关知识: (1)排序的概念:所谓排序就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来. (2)稳定的排序方法:在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的.相反,如果发生改变,这种排序方法不稳定. (3)排序算法的分类(分为5类):插入排序.选择排序.交换排序.归并排序和分配排序. (4)排序算法两个基本操作:<1>比较关键字的大小. <2>改变指向记录的

Python算法与数据结构--求所有子数组的和的最大值

Python算法与数据结构--求所有子数组的和的最大值 玄魂工作室-玄魂 玄魂工作室秘书 玄魂工作室?昨天 题目:输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 这个题目有多个解法,比如可以用一个二维数组存之前每个数据的和,然后在进行大小比较:但是这样时间负责度就是O(n2)了. 换个思路思考下,因为是要最大数,那么就不需要存储,只需要找最大值就可以了.但是为了找子序列的最大和,在遇到

2017、2018面试分享(js面试题记录)记得点赞分享哦;让更多的人看到~~

2017面试分享(js面试题记录) 1. 最简单的一道题 '11' * 2 'a8' * 3 var a = 2, b = 3; var c = a+++b; // c = 5 2. 一道this的问题 var num = 10; var obj = { num:8, inner: { num: 6, print: function () { console.log(this.num); } } } num = 888; obj.inner.print(); // 6 var fn = obj.