简体   繁体   English

广义缩写的算法

[英]Algorithms for generalized abbreviations

I have a question about how recursion stack works.我有一个关于递归堆栈如何工作的问题。

The problem I am stuck at now is Generalized Abbreviation from leetcode我现在遇到的问题是来自leetcode的Generalized Abbreviation

The question states that该问题指出

A word's generalized abbreviation can be constructed by taking any number of non-overlapping substrings and replacing them with their respective lengths.一个词的通用缩写可以通过取任意数量的非重叠子串并用它们各自的长度替换它们来构建。 For example, "abcde" can be abbreviated into "a3e" ("bcd" turned into "3"), "1bcd1" ("a" and "e" both turned into "1"), and "23" ("ab" turned into "2" and "cde" turned into "3").例如,“abcde”可以缩写为“a3e”(“bcd”变成“3”),“1bcd1”(“a”和“e”都变成“1”)和“23”(“ab " 变成了 "2" 和 "cde" 变成了 "3")。

Given a string word, return a list of all the possible generalized abbreviations of word.给定一个字符串单词,返回单词所有可能的广义缩写的列表。 Return the answer in any order.以任意顺序返回答案。

Input: word = "word"
Output: ["4","3d","2r1","2rd","1o2","1o1d","1or1","1ord","w3","w2d","w1r1","w1rd","wo2","wo1d","wor1","word"]
Input: word = "a"
Output: ["1","a"]

Here is the code I am struggling with这是我正在努力的代码

/* package whatever; // don't place package name! */

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    public static List<String> generateAbbreviations(String word){
        List<String> ans = new ArrayList<String>();
        backtrack(ans, new StringBuilder(), word, 0, 0);
        return ans;
    }
 
    // i is the current position
    // k is the count of consecutive abbreviated characters
    private static void backtrack(List<String> ans, StringBuilder builder, String word, int i, int k){
        int len = builder.length(); // keep the length of builder 
        if(i == word.length()){
            if (k != 0) builder.append(k); // append the last k if non zero
            ans.add(builder.toString());
        } else {
            // the branch that word.charAt(i) is abbreviated
            backtrack(ans, builder, word, i + 1, k + 1);
 
            // the branch that word.charAt(i) is kept
            if (k != 0) builder.append(k);
            builder.append(word.charAt(i));
            backtrack(ans, builder, word, i + 1, 0);
        }
 
       builder.setLength(len); // reset builder to the original state
       System.out.println("Length of Stringbuilder : " + builder.length() + ",  Current element : " + builder.toString() + " , len : " + len);
    }
    public static void main(String[] args) {
    List<String> result = Ideone.generateAbbreviations("ab");
    System.out.println("Generalized abbreviation are: " + result);
  }
}

Stdout标准输出

Length of Stringbuilder : 1,  Current element : 2, len : 0
Length of Stringbuilder : 2,  Current element : 1b, len : 2
Length of Stringbuilder : 2,  Current element : 1b, len : 0
Length of Stringbuilder : 2,  Current element : a1, len : 1
Length of Stringbuilder : 2,  Current element : ab, len : 2
Length of Stringbuilder : 2,  Current element : ab, len : 1
Length of Stringbuilder : 1,  Current element : a, len : 0

Output Output

["2","1b","a1","ab"]

From the stdout line 2 to 3, How does 'len' become 0 from what recursion stack?从 stdout 第 2 行到第 3 行, “len”如何从什么递归堆栈变为 0?

Stdout on leetcode: leetcode 上的标准输出:

Length of Stringbuilder : 0,  Current element :  , len : 0
Length of Stringbuilder : 2,  Current element : 1b , len : 2
Length of Stringbuilder : 0,  Current element :  , len : 0
Length of Stringbuilder : 1,  Current element : a , len : 1
Length of Stringbuilder : 2,  Current element : ab , len : 2
Length of Stringbuilder : 1,  Current element : a , len : 1
Length of Stringbuilder : 0,  Current element :  , len : 0

The function calls will be like this(I will denote them using (i, k, lenOfBuilder)). function 调用将是这样的(我将使用 (i, k, lenOfBuilder) 来表示它们)。 lenOfBuilder is the length calculated at the first line of each function call. lenOfBuilder 是在每个 function 调用的第一行计算的长度。

For input word = "ab"对于输入单词 = "ab"

1st call (0, 0, 0) -> called from the main method.第一次调用 (0, 0, 0) -> 从主方法调用。

2nd call (1, 1, 0) -> 1st backtrack() called from else condition of 1st call.第二次调用 (1, 1, 0) -> 1st backtrack() 从第一次调用的 else 条件调用。

3rd call (2, 2, 0) -> 1st backtrack() called from else condition of 2nd call.第三次调用 (2, 2, 0) -> 从第二次调用的 else 条件调用的第一次回溯()。

Now base condition hits as (i == 2 and k != 0). So "2" added to the answer.
Return back to 2nd call.

4th call (2, 0, 2) -> 2nd backtrack() called from else condition of 2nd call.第 4 次调用 (2, 0, 2) -> 2nd backtrack() 从第 2 次调用的 else 条件调用。 Before this call we have added "k" and charAt(i) to the builder ie "1b"在此调用之前,我们已将“k”和 charAt(i) 添加到构建器,即“1b”

Now base condition hits as (i == 2). But K is 0. So "1b" added to the answer.
Return back to 2nd call.

Else condition of 2nd call ends.第二次通话的其他条件结束。

Now following statements will be executed from the 2nd call of the function.现在将从 function 的第二次调用开始执行以下语句。

builder.setLength(len); // As the length of builder in 2nd call was 0. So this sets the length of builder to zero -> "0".
Sysout statement will print this updated length i.e 0

This is how your code has updated the length of the builder to 0. As at the very first line of your 2nd call you have calculated the original length that was 0. And after the end of else condition of your 2nd call.这就是您的代码将构建器的长度更新为 0 的方式。在第二次调用的第一行,您已经计算出原始长度为 0。并且在第二次调用的 else 条件结束之后。 You updated the length to 0 and prints 0.您将长度更新为 0 并打印 0。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM