• 一道算法题


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

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

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

    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。

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

  • 相关阅读:
    下巴肉和脖子肉怎么减肥
    java中compareTo和compare方法之比较,集合中对象的比较
    easyui中combotree只能选子选项,父级不被选中
    java线程总结(2/5)
    流行的框架与新技术
    Spring官网改版后下载
    prepareStatement与Statement的区别
    jQuery li click失效问题
    Flask 启动报错 error: [Errno 10053]
    [linux]CentOS 7 下安装 RabbitMQ
  • 原文地址:https://www.cnblogs.com/iiaijimaai/p/3299771.html
Copyright © 2020-2023  润新知