博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一道算法题
阅读量:7102 次
发布时间:2019-06-28

本文共 3060 字,大约阅读时间需要 10 分钟。

今天面试的一道算法题,当时解得不太好,各种被面试官问住,回家在地铁上想到了如下的解法。

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

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

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。

后来也上网查了一下其他的解法,正在研究中...

 

转载于:https://www.cnblogs.com/iiaijimaai/p/3299771.html

你可能感兴趣的文章
改变self.navigationItem的显示标题
查看>>
Revit2014机电系统类型BUG
查看>>
函数指针
查看>>
数学图形之Boy surface
查看>>
Objective-C中把数组中字典中的数据转换成URL
查看>>
mysqld: unrecognized service
查看>>
Windows环境下利用github快速配置git环境
查看>>
HTML静态页面传值,HTML静态页面得到url问号后面的参数。
查看>>
WPF学习笔记-用Expression Design制作矢量图然后导出为XAML
查看>>
[裴礼文数学分析中的典型问题与方法习题参考解答]5.1.22
查看>>
Eclipse+超快速的模拟器Genymotion开展Android申请书(第一步:安装和配置Genymotion)...
查看>>
MySQL查看一个表的创建文本以及删除表某列的索引
查看>>
BZOJ3009 : 集合
查看>>
android图片压缩的3种方法实例
查看>>
SVN(TortoiseSVN)提交时忽略bin跟obj目录
查看>>
Codeforces Round #326 (Div. 2) A. Duff and Meat 水题
查看>>
Android屏幕适配全攻略(最权威的官方适配指导) (转)
查看>>
内存数据库:memcached与redis技术的对比试验
查看>>
仿58同城UITableViewCell动画
查看>>
android service 的各种用法(IPC、AIDL)
查看>>