您的位置:首页 > 编程语言 > C#

常用算法和排序

2015-12-15 14:07 253 查看

常用算法和排序

 

题目一:简述单向链表,双向链表;谈谈你对栈的理解;简述C#中的队列;简述C#中的树形结构.

参考:额...这种概念性的东西也只有中国的面试官会问,但是没办法,就像高考一样,明知道学的那些东西没用,可是还是得硬着头皮学,但是!本吊认为,理解比记忆重要.所以这种概念性的东西我不会从网上把答案粘贴下来,我只是想告诉各位,这些东西需要你理解.就说这么多.

 

题目二:请简单编写一段判断素数的算法

参考:如果你办婚宴订酒店会不会先尝一尝大厨做的饭?如果是我,我肯定会去上几次,每次都点不同的菜尝尝看.所以说,既然是面试程序员,如果面试官在正常面试下来没让你写一行代码,这个公司的水平可想而知,是去是留自己好好想想.

public static bool Isprime(int input)
{
bool b = false;
for (int i = 2; i < input / 2; i++)
{
if (input % i == 0)
b = true;
}
return b;
}


题目三:简述什么是百钱百鸡算法

参考:这个题目我觉得是个”啊哈”类型的,你知道就能马上说出来,没听过就死活不会.这个题目的意思是说100元钱要买100只鸡,公鸡5元1只,母鸡3元1只,小鸡3只1元.

static void Main(string[] args)
{
//百钱百鸡问题:
// 公鸡5元钱一只,母鸡3元钱一只,小鸡1元钱三只.现在有一百块钱,正好买一百只鸡有多少种情况?

////方法1:按钱数考虑
////考虑公鸡5元一只,可以把其设为X,母鸡3元一只,可以把其设为Y,小鸡一元3只,把其设为Z,则可以得出:5X+3Y+Z/3=100;
////满足的情况:1、X+Y+Z==100; 2、5X+3Y+Z/3==100; 3、Z%3==0//Z必须为3的整数倍
int X;
int Y;
int Z;
//公鸡的变化:应该从0到100,公鸡所用的钱数:可能买0只,用到0元;可能买20只,用了100元
for (X = 0; X <= 100; X++)
{
//母鸡的变化:从0到100
for (Y = 0; Y <= 100; Y++)
{
//小鸡的变化:从0到100
for (Z = 0; Z <= 100; Z++)
{
if ((X + Y + Z == 100) && (5 * X + 3 * Y + Z / 3 == 100) && (Z % 3 == 0))
{
Console.WriteLine("买了公鸡{0}只,母鸡{1}只,小鸡{2}只", X, Y, Z);
}
}
}
}
Console.ReadKey();
}

还有第二种解法,可以想一想,我用的知识是小学的知识.你可以用用初中高中的知识.

 

题目四:什么是韩信点兵算法.

参考:还是”啊哈”类型的题目.韩信带兵不足百人,3人一行排列多1人,7人一行排列少2人,5人一行排列正好.写出代码:

static void Main(string[] args)
{
int a = 0, b = 0, c = 0;
for (int i = 0; i < 100; i++)
{
Math.DivRem(i, 3, out a);
Math.DivRem(i, 5, out b);
Math.DivRem(i, 7, out c);
if (a == 1 && b == 0 && c == 5)
{
Console.WriteLine("韩信的兵有: "+i);
}
}
Console.ReadKey();
}

额...这里用到了一个函数:Math.DivRem(),你如果不明白,没见过,建议自己去查.https://msdn.microsoft.com/zh-cn/library/yda5c8dx.aspx

我都给你把链接放上了,您点点鼠标就行了,还是去看看吧.

 

题目五:简述斐波那契数列

参考:应该听过这个玩意吧.斐波那契额数列的定义是:第一项和第二项都是1,以后各项都是前两项的和(这个定义是我自己造的...).

案例:斐波那契数列(1,1,2,3,5,8...)

用函数表示:f(n)=f(n-1)+f(n-2)  (n>2,f(1)=1,f(2)=1)

方法1:一般会想到使用递归

static int Fn(int n)
{
if (n <= 0)
{
throw new ArgumentOutOfRangeException();
}

if (n == 1 || n == 2)
{
return 1;
}
return checked(Fn(n - 1) + Fn(n - 2)); // when n>46 memory will overflow
}


方法2:因为递归的时间复杂度是O(n*n),空间复杂度也高,尽量不要去用.

static int Fn1(int n)
{
if (n <= 0)
{
throw new ArgumentOutOfRangeException();
}

int a = 1;
int b = 1;
int c = 1;

for (int i = 3; i <= n; i++)
{
c = checked(a + b); // when n>46 memory will overflow
a = b;
b = c;
}
return c;
}


方法3:你以为这样就算最优代码了吗?开什么玩笑!接着看:

static int Fn2(int n)
{
if (n <= 0)
{
throw new ArgumentOutOfRangeException();
}

int a = 1;
int b = 1;

for (int i = 3; i <= n; i++)
{
b = checked(a + b); // when n>46 memory will overflow
a = b - a;
}
return b;
}


说明:为啥需要使用checked呢?说过,可以回忆一下,当你斐波那契数列的增长很恐怖,你输入几个数看看就明白了.

 

题目六:简述求水仙花数的算法

参考:还是”啊哈”类型的题目,这些”啊哈”的题目都是很常见的,就相当于厨师手中各种不同的锅,咱们不了解各种锅的作用,但不代表就只有一种锅,咱们应该了解几个常见的”锅”.OK?所谓的水仙花数,就是一个三位数(100-999),每一位的立方相加等于该数本身.

方法1:本屌愚钝,一种用的这个方法

int i, j, k;
for (int num = 100; num < 1000; num++)
{
i = num / 100; //百位数字
j = num % 100 / 10; //十位数字
k = num % 10; //个位数字
if (i * i * i + j * j * j + k * k * k == num)
Console.WriteLine("{0}", num);
}


方法2:大神专用方法

int a = 0, b = 0, c = 0;
for (int i = 100; i <1000; i++)
{
a = i / 100;//获取三位数中的第一个数
Math.DivRem(i, 100, out b);//获取三位数中的后两位
b = b / 10;//获取三位数中的第二位数
Math.DivRem(i, 10, out c);//获取三位数中的第三位数
a = a * a * a;
b = b * b * b;
c = c * c * c;
if ((a+b+c)==i)
{
Console.WriteLine(i);
}
}


说明:算法这个玩意往往不止一种实现方法,只不过你我这样的凡人脑海中出现的第一个解法往往是比较低效的,但是如果我们耐住性子好好想想其实也能实现一个比较高效的算法.不要相信第一直觉.

 

题目七:听过完数吗?来个算法实现它.

参考:完数就是该数的所有约数(能整除自己的自然数,但不包括本身)相加等于自己的数.例如:28=1+2+4+7+14.

static bool IsWanShu(int num)
{
int s = 0;
for (int i = 1; i < num; i++)
{
if ((num%i)==0)
{
s += i;
}
}
if (num==s)
{
string str = s.ToString() + "=";
for (int i = 1; i < s; i++)
{
if ((s%i)==0)
{
if (i!=1)
{
str = str + "+" + i.ToString();
}
else
{
str = str + i.ToString();
}
}
}
Console.Write(str);
return true;
}
return false;
}

问题八:实现冒泡排序和选择排序

参考:为什么把这两个算法放在一起呢,因为这两个算法很相似.就放在一起说说吧.等等!你知道这两个算法的描述吗?

要不我先说说这两个算法的的描述吧,不喜跳过:

冒泡排序:首先将第一个记录的关键字和第二个关键字进行比较,若为逆序,则将两个记录交换,然后比较第二个记录和第三个记录的关键字.以此类推,直至第n-1个记录和第n个记录的关键字进行过比较为止.上述过程成为第一趟冒泡排序,执行n-1次上述过程后,排序完成.

 

选择排序:选择排序的主要操作是关键字间的比较,显然从nge数据中进行简单排序的算法为:令i从1至n-1进行n-1趟选择排序.

private static void Swap(ref int aa, ref int bb)
{
int temp;
temp = bb;
bb = aa;
aa = temp;
}
/// <summary>
/// 冒泡排序
/// </summary>
/// <param name="a">要排序的数组</param>
static void BubbleSort(int[] a)
{
for (int i = 0; i < a.Length; i++)
{
for (int j = 0; j < a.Length - i - 1; j++)
{
if (a[j] < a[j + 1])
{
Swap(ref a[j], ref a[j + 1]);
}
}
}
}
/// <summary>
/// 选择排序
/// </summary>
/// <param name="a">要排序的数组</param>
static void SelectionSort(int[] a)
{
int k;
for (int i = 0; i < a.Length-1; i++)
{
k = i;
for (int j = i+1; j < a.Length; j++)
{
if (a[j]<a[k])
{
k = j;
}
}
if (k!=i)
{
Swap(ref a[i], ref a[k]);
}
}
}


问题九:实现一个插入排序

参考:直接插入排序是一种最简单的排序方法,基本操作是将一个记录插入到一个排序好的有序列表中,从而得到亿个新的,记录数增1的有序表.实现插入排序主要是先找到一个有序序列,然后将下一个关键字插入上述有序序列,然后再从剩下的关键字中选取下一个插入对象,反复执行知道整个序列有序.

/// <summary>
/// 插入排序
/// </summary>
/// <param name="list">要排序的数组</param>
static void InsertSort(int[] list)
{
for (int i = 1; i < list.Length; i++)
{
int t = list[i];
int j = i;
while ((j>0)&&(list[j-1]>t))
{
list[j] = list[j - 1];
--j;
}
list[j] = t;
}
}


 

总结

本来还想说一下希尔排序的,但是我觉得都说了就没啥意思了,如果你看到这里了,希望你能自己去看看,去研究一下那些常见的排序,比如快速排序,还有没说的希尔排序.

下一个内容就开始讲解面向对象的东西了,我看了看,貌似大部分是概念性的东西...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C# .net