在Java中如何使用out参数?

3xiyfsfu  于 2023-01-01  发布在  Java
关注(0)|答案(1)|浏览(276)

我的目标是递归地迭代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中并不合适。泛型树会有这些属性是很奇怪的。
那么我该怎么办?在所有这些选项中,哪一个是最好的?哪一个比所有三个都好?我不确定哪一个是最好的传统和实用的方法,除了第一个不节省空间。

w8f9ii69

w8f9ii691#

您遇到的问题并不是因为Java是“按值传递”的。
您遇到的问题是字符串是 * 不可变的 *,当您给名为longestlocal 参数赋一个新值时,它会在超出作用域后立即消失。
通过传递长度为1的数组,可以相对容易地解决这个问题。

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[0].length()) {
                    longest[0] = new String(str);
                    timesUsed = nextNode.timesUsed;
                }
                allPrefixesUtil2(longest, timesUsed, nextNode, str);
            }
        }
    }

相关问题