广义缩写算法

Algorithms for generalized abbreviations

我对递归堆栈的工作原理有疑问。

我现在卡的问题是leetcode的Generalized Abbreviation

问题表明

可以通过取任意数量的非重叠子串并将它们替换为各自的长度来构造单词的广义缩写。例如,“abcde”可以缩写为“a3e”(“bcd”变成“3”)、“1bcd1”(“a”和“e”都变成“1”)、“23”(“ab” "变成了"2","cde"变成了"3")。

给定一个字符串词,return 一个词的所有可能通用缩写的列表。 Return 答案顺序不限。

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"]

这是我正在努力处理的代码

/* 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);
  }
}

标准输出

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

输出

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

从标准输出第 2 行到第 3 行, 'len'如何从什么递归栈变成0?

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

函数调用将像这样(我将使用 (i, k, lenOfBuilder) 表示它们)。 lenOfBuilder 是在每个函数调用的第一行计算的长度。

对于输入词=“ab”

第一次调用 (0, 0, 0) -> 从主方法调用。

第二次调用 (1, 1, 0) -> 从第一次调用的其他条件调用的第一次回溯 ()。

第 3 次调用 (2, 2, 0) -> 第 1 次 backtrack() 从第二次调用的 else 条件调用。

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

第 4 次调用 (2, 0, 2) -> 第 2 次 backtrack() 从第二次调用的 else 条件调用。在此调用之前,我们已将“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条件第二次调用结束

现在将从函数的第二次调用开始执行以下语句。

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

这就是您的代码将构建器的长度更新为 0 的方式。在第二次调用的第一行,您已经计算出原始长度为 0。在第二次调用的其他条件结束后称呼。您将长度更新为 0 并打印 0。