我的目标是递归地迭代R路trie,找到至少两个字符串的最长公共前缀,以及它涉及多少个字符串。我已经写了各种方法来解决这个问题,但我对它们的技术方面并不满意。
输入示例:
第一个月
输出:
Longest prefix: fig
Number of Strings: 2
以下是我如何实施解决方案的:
这些节点有一个timesUsed
属性,当向trie中插入新字符串时,每次访问该节点时该属性都会递增。
public void allPrefixes() {
ArrayList<String> list = new ArrayList<>();
ArrayList<Integer> timesUsed = new ArrayList<>();
allPrefixesUtil(list, timesUsed, root, "");
int longestPrefixIndex = getLongestIndex(list);
System.out.println("Longest common prefix: " + list.get(longestPrefixIndex));
System.out.println("Number of strings: " + timesUsed.get(longestPrefixIndex));
}
public void allPrefixesUtil(ArrayList<String> list, ArrayList<Integer> timesUsed, Node x, String s) {
for (int i = 0; i < x.next.length; i++) {
if (x.next[i] != null && x.next[i].timesUsed >= 2) {
list.add(s + (char) (i + 'a'));
timesUsed.add(x.next[i].timesUsed);
allPrefixesUtil(list, timesUsed, x.next[i], s + (char) (i + 'a'));
}
}
}
此处的代码添加了出现多次的每个前缀,因此列表如下所示:e, en, f, fi, fig
。然后我找到这些字符串中最长的一个,并将其与相应的timeUsed索引一起打印出来。这种解决方案占用了大量空间,所以我决定尝试其他方法。
接下来,我试了这个:
public void allPrefixes2() {
String longest = "";
int timesUsed = 0;
allPrefixesUtil2(longest, timesUsed, root, "");
System.out.println("Longest common prefix: " + longest);
System.out.println("Number of strings: " + timesUsed);
}
public void allPrefixesUtil2(String longest, int timesUsed, Node x, String s) {
for (int i = 0; i < x.next.length; i++) {
Node nextNode = x.next[i];
if (nextNode != null && nextNode.timesUsed >= 2) {
String str = s + (char) (i + 'a');
if (str.length() > longest.length()) {
longest = new String(str);
timesUsed = nextNode.timesUsed;
}
allPrefixesUtil2(longest, timesUsed, nextNode, str);
}
}
}
我没有把每个前缀都加到列表中然后计算最长的,而是决定每当遇到更长的字符串时重新分配最长的字符串。这显然不起作用,因为Java是按值传递的。为了解决这个问题,我把字符串和整数改为单元素数组。
public void allPrefixes2() {
String[] longest = { "" };
int[] timesUsed = { 0 };
allPrefixesUtil2(longest, timesUsed, root, "");
System.out.println("Longest common prefix: " + longest[0]);
System.out.println("Number of strings: " + timesUsed[0]);
}
这是可行的,但是......我不确定这是聪明还是愚蠢。如果我想使用临时变量,我找不到更好的方法。
不过最后我还是做了一些修改,使得trie有一个longest
和一个timesUsed
属性,并且直接将这些属性传递给方法。它成功了,但是这次,将这些属性添加到trie中并不合适。泛型树会有这些属性是很奇怪的。
那么我该怎么办?在所有这些选项中,哪一个是最好的?哪一个比所有三个都好?我不确定哪一个是最好的传统和实用的方法,除了第一个不节省空间。
1条答案
按热度按时间w8f9ii691#
您遇到的问题并不是因为Java是“按值传递”的。
您遇到的问题是字符串是 * 不可变的 *,当您给名为
longest
的 local 参数赋一个新值时,它会在超出作用域后立即消失。通过传递长度为1的数组,可以相对容易地解决这个问题。