zoukankan      html  css  js  c++  java
  • 常用经典算法

    面试算法的复习和整理,争取每天一个算法[常更长新]

      一哥们去一著名跨国大大大的公司去面试。在很多项目经验,设计,架构,前台,后端都考察个遍后...私以为快要拿到Offer的时候... 不信的事情发生了。
    考官出了两道大二时候经常考的算法题。用惯了IDE的他居然一时蒙掉了,提笔多次却无从落笔。悲剧之余,只得铩羽而归...
      为了不和这哥们一样,我觉得好好复习复习算法相关的问题,争取每天一个算法题,以题促进。对于我个人的解决方案肯定有部分是比较粗陋的,希望各位大牛不吝赐教,留下各位的算法。当然我觉得各位在看我的算法之前自己动手写写应该也是有提高的,最好是用记事本写,然后直接Copy到IDE中测试,看看离开了Intelligence还能不能直接Run的起来...
      1: 经典的冒泡排序
      简述:给出一组乱序数组 如: int[] a = new int[10]{4,3,5,1,6,2,9,10,8,7};
      要求:写出f(n), 使得乱序数组按序排列。    
    复制代码
    1 public static void RunSnippet()
    2 {
    3 int[] a = new int[] {4, 3, 5, 1, 6, 2, 9, 10, 8, 7};
    4 //int[] a = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    5 //int[] a = new int[] {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    6   int temp = 0, count = 0;
    7 for (int i = 1; i < a.Length; i++)
    8 {
    9 for (int j = 0; j < a.Length - i; j++)
    10 {
    11 if (a[j] > a[j + 1])
    12 {
    13 temp = a[j + 1];
    14 a[j + 1] = a[j];
    15 a[j] = temp;
    16 count += 1;
    17 }
    18 }
    19 }
    20 //for (int i = 0; i < a.Length; i++)
    21 //{
    22 // for (int j = i + 1; j < a.Length; j++)
    23 // {
    24 // if (a[j] < a[i])
    25 // {
    26 // temp = a[i];
    27 // a[i] = a[j];
    28 // a[j] = temp;
    29 // count += 1;
    30 // }31 // }32 //}33   for (int i = 0; i < a.Length; i++)34 {35 Console.WriteLine(a[i].ToString());36 }37 Console.WriteLine("Count:" + count);38 Console.ReadLine();39 }
    复制代码
      解析:面试最常见的排序之一,按顺序将每一个值和后面的所有值作一次比较,符合要求(如 a[0] > a[1])则a[0]与a[1]交换,否则不变;这样一轮下来总能保证最小的冒到最上面(给出的算法一为最大的沉到最下面,两种算法稍有不同,自己体会下)。N(数组的Length-1)轮过后,对每一个数字都进行了调换,于是排序成功。
      扩展:待补充...
      2: 面试题:菲薄那题数列
      简述:给出一数字序列 {1,1,2,3,5,8...}
      要求:写出f(n), 计算第N位数字的值。
    复制代码
    1 public static void RunSnippet()
    2 {
    3 int a = 1,b = 1,total = 0;
    4 int n;
    5 n = int.Parse(Console.ReadLine());
    6 n = n -2;
    7 if(n<=0)
    8 {
    9 total = 1;
    10 }
    11 else
    12 {
    13 for(int i =0;i<n;i++)
    14 {
    15 total = a+b;
    16 a=b;
    17 b=total;
    18 }
    19 }
    20 Console.WriteLine(total);
    21 }
    复制代码
      解析:同样常见的面试题,有题可知,每个数字均为前两个数字之和,由于规定不能用递归,所以用循环的方法就是只能由小做到大。设定两个变量存储前两位值,每次循环为这两个变量重新赋值,直到循环到需求的次数为止。
      扩展:待补充...
      3: 面试题:任意插入排序
      简述:给出两数字序列 int[] a = new int[]{1,2,3,4,7,8,9,10}; 和 int[] b = new int[]{2,5,6,8};
      要求:写出f(n), 把b中的数字按顺序插入到a中,为了简便,默认a,b中数字已经排序。   
    复制代码
    1 public static void RunSnippet()
    2 {
    3 int[] a = new int[]{1,2,3,4,7,8,9,10};
    4 int[] b = new int[]{2,5,6,8};
    5 int z= 0;
    6 int[] result = new int[a.Length+b.Length];
    7 for(int i = 0;i<a.Length;i++)
    8 {
    9 for(int j=0;j<b.Length;j++)
    10 {
    11 if(a[i]>b[j])
    12 {
    13 result[z]=b[j];
    14 b[j] = int.MaxValue;
    15 z+=1;
    16 }
    17 }
    18 result[z] = a[i];
    19 z+=1;
    20 }
    21 for(int i = 0;i<result.Length;i++)
    22 {
    23 Console.WriteLine(result[i]);
    24 }
    25 }
    复制代码
        解析:典型的插值,我稍加改变,本来是插入一个数,我改成了插入一个数组。实现原理就是new新的数组result,然后按顺序把a中元素和b中的每个元素比较,符合要求的(a[i]>b[j])家,先插入b[j]到result数组,在插入a[i],否则直接插入a[i]。这里设置b[j]为int.MaxValue是为了不对b中元素重复操作。我想肯定有更好的算法,希望大家不吝赐教。
      扩展:待补充...
      4: 直接插入排序
      简述:给出一数字序列 int[] a = new int[10]{4,3,5,1,6,2,9,10,8,7};
      要求:写出f(n),使得无序数组按序排列。  
    复制代码
    1 public static void RunSnippet()
    2 {
    3 int[] a = new int[] { 4, 3, 5, 1, 6, 2, 9, 10, 8, 7 };
    4 //int[] a = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    5 //int[] a = new int[] {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    6 int count = 0,temp = 0;
    7 for (int i = 1; i < a.Length; i++)
    8 {
    9 temp = a[i];
    10 int j = i - 1;
    11 while (j >= 0 && a[j] > temp)
    12 {
    13 a[j + 1] = a[j];
    14 j--;
    15 count += 1;
    16 }
    17 a[j + 1] = temp;
    18 }
    19 // temp = 0;
    20 // for (int i = 1; i < a.Length; i++)
    21 // {
    22 // for (int j = 0; j < i; j++)
    23 // {
    24 // if (a[i] < a[j])25 // {26 // for (int k = i; k > j; k--)27 // {28 // temp = a[k];29 // a[k] = a[k - 1];30 // a[k - 1] = temp;31 // count += 1;32 // }33 // break;34 // }35 // }36 // }37 for (int i = 0; i < a.Length; i++)38 {39 Console.WriteLine(a[i].ToString());40 }41 Console.WriteLine("Count:" + count);42 Console.ReadLine();43 }
    复制代码


      解析:直接插值排序,将a[n]和a[0]比较,如果符合要求(如:a[n]<a[0]),移动数字到a[0]前,否则继续比较a[n]和a[1],共需要比较n-1次。因为每次和前面比较的数列必定是已经排好序的,所以只要命中一次符合条件的判断,就可以退出比较循环了,两种算法是一样的,写法不同,可以在VS中跟踪一下。
      扩展:待补充...

      5: 希尔排序
      简述:给出一数字序列 int[] a = new int[10]{4,3,5,1,6,2,9,10,8,7};
      要求:写出f(n),使得无序数组按序排列。  

    复制代码
    1 public static void RunSnippet()
    2 {
    3 int[] a = new int[] { 4, 3, 5, 1, 6, 2, 9, 10, 8, 7 };
    4 //int[] a = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    5 //int[] a = new int[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
    6 int count = 0, temp = 0;
    7 for (int h = a.Length/3; h > 0; h /= 2)
    8 {
    9 for (int i = h; i < a.Length; i+=h)
    10 {
    11 for (int j = 0; j < i; j += h)
    12 {
    13 if (a[i] < a[j])
    14 {
    15 for (int k = i; k > j; k -= h)
    16 {
    17 temp = a[k];
    18 a[k] = a[k - h];
    19 a[k - h] = temp;
    20 count += 1;
    21 }22 break;23 }24 }25 }26 }27 28 for (int i = 0; i < a.Length; i++)29 {30 Console.WriteLine(a[i]);31 }32 Console.WriteLine("Count:" + count);33 Console.ReadLine();34 }
    复制代码

      解析:直接排序的升级版,开始会去一个跳跃值,使得每个数字不用和相邻的比较交换,而是根据跳跃值得到不同间隔值的若干组数,并在组内采用直接插入排序,最后的一组的间隔为1。如题中,总长度为10,跳跃值为3,分成的组为{a[3],a[6],a[9]},{a[*]},间隔分别为3和1。 
      扩展:选取不同的跳跃值对排序的性能有比较大的影响,怎么选取合适的跳跃值是个问题...

      6: 面试题:数列替换
      简述:给出两字串序列 string[] a = new string[]{"a","b","c","d","e","f","a","b","c","d","e"}; string[] b = new string[]{"b","c","d"};
      要求:写出f(n), 把a串中同b的字串队列用空格代替。  

    复制代码
    1 public static void RunSnippet()
    2 {
    3 string[] a = new string[]{"a","b","c","d","e","f","a","b","c","d","e"};
    4 string[] b = new string[]{"b","c","d"};
    5 int temp;
    6 for(int i=0;i<a.Length;i++)
    7 {
    8 temp = i;
    9 for(int j=0;j<b.Length;j++)
    10 {
    11 if(a[i]==a[j])
    12 {
    13 i+=1;
    14 }
    15 else
    16 {
    17 i=temp;
    18 break;
    19 }
    20 if(j==b.Length-1)21 {22 for(int k=0;k<b.Length;k++)23 {24 a[i]="";25 i-=1;26 }27 i=temp+b.Length;28 }29 }30 }31 for(int i=0;i<a.Length;i++)32 {33 Console.WriteLine(a[i].ToString());34 }35 }
    复制代码

      解析:不知道算不算是最简陋的算法了,基本不用解释也是一看就明白了。思路是将a中的字符轮序与b中的字符比较,碰到第一个不同就退出,如果都相同倒过来全部置为空,跳过b的长度继续比较。
      扩展:待补充...

      7: 面试题:求小于某数字的所有素数
      简述:输入一个正整数。求出所有素数
      要求:写出f(n), 列出所有仅能被2和自身整除的数。  

    复制代码
    1 public static void RunSnippet()
    2 {
    3 int a = Convert.ToInt32(Console.ReadLine());
    4 if(a<3)
    5 {
    6 Console.WriteLine(2);
    7 return;
    8 }
    9 IList<int> su = new List<int>();
    10 for(int i=3;i<a;i+=2)
    11 {
    12 int j=0;
    13 for(j=2;j<=i/2;j++)
    14 {
    15 if(i%j==0)
    16 {
    17 break;
    18 }
    19 }
    20 if(j>i/2)
    21 {
    22 su.Add(i);
    23 }
    24 }
    25 foreach(int i in su)
    26 {
    27 Console.Write(i.ToString()+';');
    28 }
    29 }
    复制代码

      解析:比较简单的题目,按照题意遍历就可以了,不过个人感觉效率不行,大于100W速度就不行了。
      扩展:待补充...

      8: 面试题:求两个数字的最大公约数
      简述:输入两个正整数,求出最大公约数。
      要求:写出f(n),求出最大的能被两个数整除的数。  
    复制代码
    1 public static void RunSnippet()
    2 {
    3 int a= Convert.ToInt32(Console.ReadLine());
    4 int b= Convert.ToInt32(Console.ReadLine());
    5 int temp = 1;
    6 while(temp != 0)
    7 {
    8 if(a>b)
    9 {
    10 temp=a%b;
    11 a=b;
    12 b=temp;
    13 }
    14 else
    15 {
    16 temp=b%a;
    17 b=temp;
    18 }
    19 }
    20 Console.WriteLine(a);
    21 }
    复制代码

      解析:根据最大公约数的定义来编程,大数整除小数取余;然后小数作为大数,余数作为小数继续上一步骤,直到余数为0,则最后那个小数为最大公约数。
      扩展:待补充...

      9: 面试题:产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复。
      简述:生成一个数组,长度为100,用1-100的随机数填充此数组,数组中的数字不能重复。
      要求:写出f(n),完成需求,不能使用hashtable等集合类型。 

    复制代码
    1 public static void RunSnippet()
    2 {
    3 int[] all = new int[100];
    4 Random ro = new Random();
    5 int newInt = 0;
    6 for (int i = 0; i < 100; i++)
    7 {
    8 bool insert = false;
    9 while (insert == false)
    10 {
    11 insert = true;
    12 newInt = ro.Next(1, 101);
    13 for (int j = 0; j < i; j++)
    14 {
    15 if (all[j] == newInt)
    16 {
    17 insert = false;
    18 break;
    19 }
    20 }
    21 }
    22 all[i] = newInt;
    23 }
    24
    25 for (int i = 0; i < 100; i++)26 {27 Console.WriteLine(all[i]);28 }29 Console.ReadLine();30 }
    复制代码

      解析:题目不难,就是取随机数插入数组,每次取得随机数都和数组中现有数字比较,如果已经存在那就重新取随机数,当然我提供的算法只是简单的提供一下思路,还有很大的优化空间。
      扩展:待补充...

    分类: Asp.Net(C#)
    标签: C#基础
  • 相关阅读:
    Pika的设计及实现
    高性能网络编程
    C语言的结构体
    消息队列库——ZeroMQ
    Diffie-Hellman密钥交换算法
    mysql-proxy 读写分离
    位运算
    分布式学习之一:事务
    Redis Cluster
    SpringBoot整合ActiveMQ,看这篇就够了
  • 原文地址:https://www.cnblogs.com/bb3q/p/4490957.html
Copyright © 2011-2022 走看看