前几天,同学问了我一道程序员的面试题,题目是 “统计用户输入的一串数字中每个数字出现的次数”。
当时看到这个题目,我的第一想法就是:
1.先判断用户输入的是否是数字,用if-else语句来判断;
2.将用户输入的数字字符串转换成char数组;
3.用for循环遍历每个字符,根据switch-case语句来逐一判断。
4.再建立一个int数组来接收判断后的结果,最后for循环输出。
该方法的解题代码如下:
{
static void Main(string[] args)
{
//计算用户输入的一串数字中每个数字出现的次数
Console.WriteLine("请输入一串数字");
string str = Console.ReadLine();
//将字符串转换为字符数组
char[] chnum = str.ToCharArray();
#region 判断用户输入的是否是数字
for (int i = 0; i < chnum.Length; i++)
{//判断每一个字符是否是数字 通过char的方法来判断
if (!char.IsNumber(chnum[i]))
{
Console.WriteLine("您的输入有误,请输入数字");
Console.ReadKey();
return;
}
}
#endregion
//定义一个新的数组来保存计数
int[] count=new int[9];
#region for循环遍历
//for循环遍历
for (int i = 0; i < chnum.Length; i++)
{
switch (chnum[i])
{
case '1':
count[0]++;
break;
case '2':
count[1]++;
break;
case '3':
count[2]++;
break;
case '4':
count[3]++;
break;
case '5':
count[4]++;
break;
case '6':
count[5]++;
break;
case '7':
count[6]++;
break;
case '8':
count[7]++;
break;
case '9':
count[8]++;
break;
}
}
#endregion
#region 循环输出
for (int i = 0; i < count.Length; i++)
{
Console.WriteLine("含有的数字 {0} 的个数是:{1}", i + 1, count[i]);
}
#endregion
Console.ReadKey();
}
}
运行效果如下:
不过,这种方法有两个缺点就是,如果用户输入的不是数字(如字母或符号等),程序会提示错误,并退出;再者,也会统计出用户没有输入过的数字的个数为0个,如果某些时候不想知道没有输入的数字的个数,这种解法很不合适,而且代码修改起来也很复杂。
新解法: 泛型集合
碰巧这几天接触了泛型集合,没想到用Dictionary来解这道题是那么的简单。
代码如下:
{
static void Main(string[] args)
{
Console.WriteLine("请输入数字");
string numbers = Console.ReadLine();
//创建集合 键 为数字 char类型 值为每个数字出现的次数 int类型
Dictionary<char, int> dict = new Dictionary<char, int>();
//将数字字符串转换为单个字符数组
char[] chs = numbers.ToCharArray();
for (int i = 0; i < chs.Length; i++)
{
//判断是否是数字 用到char的isnumber方法
if (char.IsNumber(chs[i]))
{
//如果键中已含有该数字,则将其对应的值+1,否则不存在,加入键中 值为1
if (!dict.ContainsKey(chs[i]))
{
//将每个数字字符作为键 存入 键值对中, 值初始为1
dict.Add(chs[i], 1);
}
else
{
//值+1
dict[chs[i]]++;
}
}
}
//循环遍历键值对输出
foreach (KeyValuePair<char,int> item in dict)
{
Console.WriteLine("数字:{0}出现了{1}次。",item.Key,item.Value);
}
Console.ReadKey();
可见,简单的几行代码就解决了。
而且,这种解法完全解决了上面遇到的两个问题。
我觉得这个应该就是面试官想要的效果吧。(汗。。。不知道我那位同学的面试情况怎么样。。。)
写到这里,我又想到了见过的另一道面试题:“计算字符串中每种字符出现的次数”。
这要用我开始想到的那种思路来解得话,我岂不是要写26个case语句来判断吗,汗。。。。不知道面试官要是看到这么多代码岂不是会当场走人。。。显然这不是最好的解题办法。
还是用泛型集合来解:
{
static void Main(string[] args)
{
//计算字符串中每种字符出现的次数(面试题)。
//“Welcome to China , beijing”,
//不区分大小写,打印“W2”“e 2”“o 3”……
/*思路:1 将字符串都转换为小写形式,否则 大小写会算各一个
* 2 以字符为键 每个字符出现的次数为值 建立 Dictionary<char,int>泛型集合
* 3 将字符串转换为字符数组
* 4 循环遍历每个字符,加入集合中作为键,其对应的值初始为1
* 5 在加入键之前做一个判断,由于集合中的键不能重复,所以判断如果键中已经还有该字符
* 则不再加入该键,只把他的值+1
* 6 去除字符串中的空格 char.isLetter() 如果是字母,进行操作5
* 7 总结:主要是泛型集合的应用
*/
//例句:
//string sentences="Welcome to China , beijing";
Console.WriteLine("请输入一段字母");
string sentences = Console.ReadLine();
//将字符串都转换为小写形式
sentences = sentences.ToLower();
//建立泛型集合
Dictionary<char,int> dict=new Dictionary<char,int>();
//将字符串变成字符数组
char[] chs=sentences.ToCharArray();
//遍历每一个字符
for (int i = 0; i < chs.Length; i++)
{
//通过char的方法判断是否为字母,如果为字母,则进行下面的操作,
//否则不操作
if (char.IsLetter(chs[i]))
{
//如果不包含该键,则加入集合中
if (!dict.ContainsKey(chs[i]))
{
//将每个字符加入集合中对应键,其值初始为1
dict.Add(chs[i], 1);
}
else
{
//否则,包含该键,只将其对应的值+1即可 值的类型为int
//dict[chs[i]] = dict[chs[i]] + 1;
dict[chs[i]]++;
}
}
}
//循环遍历输出集合中的键 值
foreach (KeyValuePair<char,int> kv in dict)
{
Console.WriteLine("字母:{0}出现了{1}次。",kv.Key,kv.Value);
}
Console.ReadKey();
}
}
同样,代码很简单:
这时,我又突发奇想想到了另一种情况:
用户输入一串字母和数字的混合字符串如“ddeieiei4954jjfjdji383ddjeuut3003k”
统计出每个数字或字母出现的次数,且数字在前,字母在后 ,数字和字母内没有顺序要求
如 数字 4 出现了 2次
数字 3 出现了 4次
.......
........
字母 d 出现了 5次
...........
当然,最简单的还是用泛型集合来解了。。。。
最后来个总结吧:
个人认为,遇到一个新的问题的时候,关键是思路,把思路一步一步理顺了,就像我们老师说的那样,知道你要干什么,想好怎样去做,最后再去写代码。不要一上来就敲代码,思路都没搞清楚呢,最后肯定是问题多多。
希望这篇文章可以给像我这样正在找工作的应届生一些小小的帮助吧!
(突然觉得在大学里学的那些知识都太简单了,而且太深了也不讲。找工作时真的很无奈啊!!!)
如有写的不好的地方还请各位多多指教啊!