您的位置:首页 > 其它

一道算法题

2013-09-03 21:33 253 查看
今天面试的一道算法题,当时解得不太好,各种被面试官问住,回家在地铁上想到了如下的解法。

问题:请设计算法查找出一个字符串中重复出现最多的字符以及次数

一开始我是这么写的,也是最普通的写法,两个循环,设两个临时变量就输出结果

static private void method_derectLoop(String s)
{
Char[] c_s = s.ToCharArray();
Int32 i_Count = 0;
Char c_Char = ' ';
//i_hasCounted是数过的相同字符数的总的个数,
for (Int32 i = 0; i < c_s.Length; i ++)
{
//i_tempCount是一个临时的变量,包含了c_s[i]在字符串中出现的个数
Int32 i_tempCount = 0;
for (Int32 j = i; j < c_s.Length; j++)
{
if (c_s[i] == c_s[j])
{
i_tempCount++;
}
}
if (i_tempCount > i_Count)
{
i_Count = i_tempCount;
c_Char = c_s[i];
}
}
Console.WriteLine("Count="+i_Count);
Console.WriteLine("Char=" + c_Char);
//Console.WriteLine(new String(c_s));
}


这个解法面试官不是很满意,因为已经计算过次数的元素还是需要继续遍历一遍,这个时候我说那建立一个数组去存储已经计算过次数的元素,但是这种方法会多一个循环,在元素过多的情况下效率也不高,当时确实没有什么好的解法,就只好作罢,此时镜头一转,来到了地铁10号线上一个低头思考的同学身上,我终于想到了一个办法可以跳过已经计算的元素,那就是每计算一次交换一下元素的位置,计算完一次之后将所有相同的元素放在数组的开头,然后跳过这些元素从下一个开始,代码如下

static private void method_skipLoop(String s)
{
Char[] c_s = s.ToCharArray();
Int32 i_Count = 0;
Int32 i_hasCounted = 0;
Int32 i_loopCount = 0;
Char c_Char = ' ';
//i_hasCounted是数过的字符数的总的个数,这些字符已经在数组的开头,可以直接跳过
for (Int32 i = 0; i < c_s.Length; i = i_hasCounted)
{
//i_tempCount是一个临时的变量,包含了c_s[i]在字符串中出现的个数
Int32 i_tempCount = 0;
for (Int32 j = i; j < c_s.Length; j++)
{
i_loopCount++;
if (c_s[i] == c_s[j])
{
//如果出现相同,不是同一个元素或者不是相邻元素,交换位置
i_tempCount++;
if (i != j && j != i + i_tempCount - 1)
{
Char c_tempChar = c_s[i + i_tempCount - 1];
c_s[i + i_tempCount - 1] = c_s[j];
c_s[j] = c_tempChar;
}
}
}
if (i_tempCount > i_Count)
{
i_Count = i_tempCount;
c_Char = c_s[i];
}
i_hasCounted += i_tempCount;
}
Console.WriteLine("Count="+i_Count);
Console.WriteLine("Char=" + c_Char);
//Console.WriteLine(new String(c_s));
}


第二种方法在s的比较短的时候执行的时间是会慢的,以为这个时候方法一和方法二的循环次数差不多,而方法二还需要多执行其他的操作。

不过当s的长度大于1000时区别就会出现(我的机器比较挫),当s十分长的时候方法二的优势就会显现出来了。

我们科以简单来分析一下方法二循环执行的次数,假设每个字母在s中出现的概率是相同的,有k个不同字母,s的长度为n

那么第一次循环遍历的元素为:n

第二次为:(1-1/k)n

第三次为:(1-2/k)n

...

最后一次为n/k

然后将这些加起来有

遍历次数=(((1+k-1)(k-1))\2))*n=((k(k-1))/2)*n

而k<=26,所以((k(k-1))/2)可以近似为一个常数c,

所以方法二的遍历次数=cn

时间复杂度为O(n)

而方法一的时间复杂度是n^2。

后来也上网查了一下其他的解法,正在研究中...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: