记录一道面试题,大致意思就是,在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()));
}
}
}
如有更好的办法请私聊或者评论给我,感激不尽!