【算法学习】求字符串中第一个出现最少的字符(java)

最近参加某公司二面,出了个算法题“求字符串中第一个出现最少的字符”,一时蒙了,,居然木有想出来,再加上没有熟悉的IDE没手感(真心感觉,敲java需要手感,哈哈可能我还很水)


【方案1】原始方法

(1)申请一个数组,与字符串等长
(2)循环字符串,对每个字符串进行(3)操作
(3)将字符与字符串中的所有字符进行比对(是否包含自身无所谓),并记录出现个数
(4)遍历统计统计结果,求得最少出现的(第一个很简单,使用打擂法很容易排除后面与之相等的情况。)

参考代码如下:

   /**
     * 原始办法,逐个匹配
     *
     * @param chars
     * @return
     */
    private static char function0(char[] chars) {
        int arrayResult[] = new int[chars.length];//某个字符出现重复数。默认为0
        for (int i = 0; i < chars.length; i++)
            for (int j = 0; j < chars.length; j++)
                if (chars[j] == chars[i]) arrayResult[i]++;
        int num = 0;
        for (int i = 1; i < chars.length; i++)
            if (arrayResult[num] > arrayResult[i]) {
                num = i;
            }
        return chars[num];
    }

看似代码量比较少,,实际运行效率很差的。


【方案2】备忘录法

在原始方法基础上添加备忘录,
(1),申请一个数组,与字符串等长
(2),循环字符串,对每个字符串进行(3)操作
(3),从当前位置的下一个开始,向后匹配,当遇到相同数时停下,将当前字符出现次数加1赋值给改字符(相当于做了一个备忘录),并对当前字符做特殊标记,表示后面还有出现。

参考代码:

   /**
     * 【1】,申请一个长度为chars.length,用来记录每个字符出现的次数
     * 【2】,对chars进行遍历,比对每个字符,统计其出现个数
     * 【3】,从当前位置的下一个开始,向后匹配,当遇到相同数时停下,
     * 将当前字符出现次数加1赋值给改字符(相当于做了一个备忘录),
     * 并对当前字符做特殊标记,表示后面还有出现。
     *
     * @param chars
     * @return
     */
    private static char function1(char[] chars) {
        int arrayResult[] = new int[chars.length];
        for (int i = 0; i < chars.length; i++) {
            if (arrayResult[i] < 1) arrayResult[i] = 1;//置为1,,某个字符至少一个
            for (int j = i + 1; j < chars.length; j++)
                if (chars[j] == chars[i]) {
                    arrayResult[j] = arrayResult[i] + 1;
                    arrayResult[i] = -1;//-1标记代表改字符后面还有字符
                    break;
                }
        }
        int num = 0;
        for (int i = 1; i < chars.length; i++)
            if (arrayResult[i] > 0 && arrayResult[num] > arrayResult[i]) {
                num = i;
            }
        return chars[num];
    }

去掉注释,,代码量也比较少(浓缩就是精华。)


【方案3】

利用hashmap,,把字符依次放入hash表中,如果存在该字符的key,则value++

   /**
     * 利用hashmap,,把字符依次放入hash表中,如果存在该字符的key,则value++
     *
     * @param chars
     * @return
     */
    private static char function2(char[] chars) {
        //创建hashmap
        Map<Character, Integer> charMap = new HashMap<>();
        for (int i = 0; i < chars.length; i++) {
            if (charMap.containsKey(chars[i]))
                charMap.put(chars[i], charMap.get(chars[i]) + 1);
            else
                charMap.put(chars[i], 1);
        }
        int num = 0;
        for (int i = 1; i < chars.length; i++)
            if (charMap.get(chars[num]) > charMap.get(chars[i])) {
                num = i;
            }
        return chars[num];
    }

这个方法,,,算是最容易实现的,,不过借助了库函数(不是很好哦),,玩的是算法。


三种方案对比

【方案1】
比较低端,,几乎没有使用任何优化手段,只是做了简单的匹配。

【方案2】
中高端,使用到了备忘录的方法(类似动态规划),对检索进行优化,很适用于重复率较高的串

【方案3】
巧妙利用库函数,不过算法方面体现的不是很到位,业务代码中使用比较合适(当然自己优化更好)



三种方案运行时间对比。(博主使用 jdk1.8,IDEA2016)

这里写图片描述

这里写图片描述

这里写图片描述

很明显备忘录法优势杠杠的。(原因是测试串重复率很高)



完整测试代码如下

package algorithm_2;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by zsl on 2017/8/24.
 * 求字符串中第一个出现最少的字符
 */
public class StringFindFirstLess {

    public static void main(String[] args) {
        String str = "首aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天" +
                "aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天aabbccddacd今天尾";
        //测试本办法,花费时间
        char result = 0;
        long start = System.currentTimeMillis();
        result = function0(str.toCharArray());
        long end = System.currentTimeMillis();
        System.out.println("所求字符为:" + result);
        System.out.println("【原始方法】运行时间:" + (end - start) + "毫秒");//应该是end - start

        //加入备忘录,花费时间
        start = System.currentTimeMillis();
        result = function1(str.toCharArray());
        end = System.currentTimeMillis();
        System.out.println("所求字符为:" + result);
        System.out.println("【备忘录法】运行时间:" + (end - start) + "毫秒");//应该是end - starti

        //使用HashMap,花费时间
        start = System.currentTimeMillis();
        result = function2(str.toCharArray());
        end = System.currentTimeMillis();
        System.out.println("所求字符为:" + result);
        System.out.println("【HashMap法】运行时间:" + (end - start) + "毫秒");//应该是end - starti

    }

    /**
     * 原始办法,逐个匹配
     *
     * @param chars
     * @return
     */
    private static char function0(char[] chars) {
        int arrayResult[] = new int[chars.length];//某个字符出现重复数。默认为0
        for (int i = 0; i < chars.length; i++)
            for (int j = 0; j < chars.length; j++)
                if (chars[j] == chars[i]) arrayResult[i]++;
        int num = 0;
        for (int i = 1; i < chars.length; i++)
            if (arrayResult[num] > arrayResult[i]) {
                num = i;
            }
        return chars[num];
    }

    /**
     * 【1】,申请一个长度为chars.length,用来记录每个字符出现的次数
     * 【2】,对chars进行遍历,比对每个字符,统计其出现个数
     * 【3】,从当前位置的下一个开始,向后匹配,当遇到相同数时停下,
     * 将当前字符出现次数加1赋值给改字符(相当于做了一个备忘录),
     * 并对当前字符做特殊标记,表示后面还有出现。
     *
     * @param chars
     * @return
     */
    private static char function1(char[] chars) {
        int arrayResult[] = new int[chars.length];
        for (int i = 0; i < chars.length; i++) {
            if (arrayResult[i] < 1) arrayResult[i] = 1;//置为1,,某个字符至少一个
            for (int j = i + 1; j < chars.length; j++)
                if (chars[j] == chars[i]) {
                    arrayResult[j] = arrayResult[i] + 1;
                    arrayResult[i] = -1;//-1标记代表改字符后面还有字符
                    break;
                }
        }
        int num = 0;
        for (int i = 1; i < chars.length; i++)
            if (arrayResult[i] > 0 && arrayResult[num] > arrayResult[i]) {
                num = i;
            }
        return chars[num];
    }

    /**
     * 利用hashmap,,把字符依次放入hash表中,如果存在该字符的key,则value++
     *
     * @param chars
     * @return
     */
    private static char function2(char[] chars) {
        //创建hashmap
        Map<Character, Integer> charMap = new HashMap<>();
        for (int i = 0; i < chars.length; i++) {
            if (charMap.containsKey(chars[i]))
                charMap.put(chars[i], charMap.get(chars[i]) + 1);
            else
                charMap.put(chars[i], 1);
        }
        int num = 0;
        for (int i = 1; i < chars.length; i++)
            if (charMap.get(chars[num]) > charMap.get(chars[i])) {
                num = i;
            }
        return chars[num];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鼠晓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值