社招遇到的面试题:比较1000个不重复字符串的相似度并输出前五个

记录一道面试题,大致意思就是,在Linux系统环境下,随机生成长度为n的1000个不重复的字符串,随机取其中一个字符串,与其它字符串进行相比较,连续相似的字符串越相似,取相似度最高的前五个并输出,请编程!

个人解题思路:先生成1000个不重复的字符串(当时考虑到两种情况,一种是通过循环和随机数,从26个英文字母中通过循环和随机数获取到不同的字母拼接再拼接4个不同的字符串,并存储到HashSet中;第二种是通过循环和随机数获取到ASCALL码对应的字符进行拼接,存储到HashSet中。在代码中将存入到HashSet省略没写了),然后通过随机数随机获取其中一个字符串和下标,再通过遍历进行相似度比较(参考NRE的编程笔记)并输出到一个HashMap中(相似度,字符串)。

代码地址:https://github.com/yuchen666/StringSimilarity

生成长度随机字符串不重复的数组:

/***
 * 定义长度为n的内容不重复的数组,
 */
public class Args {
    /***
     * 定义随机字符串
     * @param length
     * @return
     */
    public static String getRandom(int length) {
        // 定义一个字符串,随机字符串从此字符串中获取
        String str = "abcdefghijklmnopqrstuvwxyz0123456789";
        int randomNum;
        char randomChar;
        Random random = new Random();
        // 定义一个可变字符串
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i <= length; i++) {
            // 可生成[0,n)之
            randomNum = random.nextInt(str.length());
            // 获得随机位置对应的字符
            randomChar = str.charAt(randomNum);
            // 组成一个随机字符串
            stringBuffer.append(randomChar);
        }
        return stringBuffer.toString();
    }

    /***
     * 定义大小为index的数组
     * @param index
     * @return
     */
    public String[] getRandomArray(int index) {
        String[] str = new String[index];
        Random random = new Random();
        for (int i = 0; i < index; i++) {
            str[i]=getRandom(random.nextInt(36))+getRandom(random.nextInt(2));
        }
        return str;
    }
}

相似度比较:

/***
 * 计算相似度
 */
public class Like {
    public static int compare(String str1, String str2) {
        // 定义一个矩阵,用于存放字符串
        int args[][];
        // 获取字符串的长度,用于存储矩阵中的数据
        int n = str1.length();
        int m = str2.length();
        // i为遍历str1的数据,j为遍历str2的数据
        int i;
        int j;
        // c1为str1中的字符,c2为str2中的字符
        char c1;
        char c2;
        // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
        int temp;
        if (n == 0) {
            return m;
        }
        if (m == 0) {
            return n;
        }
        // 初始化矩阵
        args = new int[n + 1][m + 1];
        // 初始化行
        for (i = 0; i <= n; i++) {
            args[i][0] = i;
        }
        // 初始化列
        for (j = 0; j <= m; j++) {
            args[0][j] = j;
        }
        for (i = 1; i <= n; i++) {
            // 遍历str1
            c1 = str1.charAt(i - 1);
            // 匹配str2
            for (j = 1; j <= m; j++) {
                c2 = str2.charAt(j - 1);
                // 两个字符相同
                if (c1 == c2) {
                    // 则计算值为0
                    temp = 0;
                } else {
                    // 若不同,则计算值为1
                    temp = 1;
                }
                // 左边+1,上边+1, 左上角+temp取最小
                args[i][j] = min(args[i - 1][j] + 1, args[i][j - 1] + 1, args[i - 1][j - 1] + temp);
            }
        }
        // 返回矩阵
        return args[n][m];
    }

    /**
     * 获取最小的值
     */
    private static int min(int one, int two, int three) {
       int min = one;
       if(two<min){
            min = two;
       }
       if(three < min){
            min = three;
       }
       return min;
    }

    /**
     * 获取两字符串的相似度
     */
    public double getSimilarity(String str1, String str2) {
        int max = Math.max(str1.length(), str2.length());
        if (max == 0) {
            return 0f;
        } else {
            return 1 - (double) compare(str1, str2) / max;
        }
    }
}

通过比较返回结果:

public class Test {
    public static void main(String[] args) {
        // 用于排序,中间变量
        // double temp = 0.00;
        Like like = new Like();
        Args args1 = new Args();
        double d;
        // 定义一个长度为1000的内容不重复的字符串数组
        String[] randomArray = args1.getRandomArray(1000);
        Map<String, Double> percent = new HashMap<>();
        // 定义一个长度相同的数组,将相似度值放入数组中,根据值去获取下标,根据下标获取具体的 字符串
        // Double[] doubles = new Double[randomArray.length];
        Random random = new Random();
        // 随机从数组中获取一个1000以内的值
        int index = random.nextInt(1000);
        // 从数组中获取到值,然后与数组中每一个数据进行比较,比较后获得相似度值存储到doubles数组中
        String str = randomArray[index];
        for (int i = 0; i < randomArray.length; i++) {
            if (i == index) {
                percent.put(str, 0.00);
                //doubles[i] = 0.00;
            } else {
                percent.put(randomArray[i], like.getSimilarity(str, randomArray[i]));
                //doubles[i] = like.getSimilarity(str, randomArray[i]);
            }
        }

        // 根据HashMap中的 value值进行排序 排序后的结果放入 list集合中
        Set<Map.Entry<String, Double>> entrySet = percent.entrySet();
        List<Map.Entry<String, Double>> list = new ArrayList<>(percent.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, Double>>() {
            @Override
            public int compare(Map.Entry<String, Double> o1, Map.Entry<String, Double> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });
        // 输出当前值
        System.out.println("当前值为:" + str);
        // 输出与其相似的五个字符串

        for (int i = 0; i < 5; i++) {
            System.out.println(" 与 " + list.get(i).toString().substring(0, list.get(i).toString().indexOf("=")) +
                    " 较为相似,相似度为:" +
                    list.get(i).toString().substring((list.get(i).toString().indexOf("=") + 1), list.get(i).toString().length()));
        }
    }
}

如有更好的办法请私聊或者评论给我,感激不尽!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值