English 中文(简体)
利用再入侵产生所有次量
原标题:Generate all subsequences using recursion

<>strong> 问题:Given a string s , 产生使用再次入侵的窒息性。 产出应采用某种方式(每一次标本均应首先印出,然后按顺序排列)。

a. 特定载体=bcd的样本产出

a
ab
abc
abcd
abd
ac
acd
ad
b
bc
bcd
bd
c
cd
d

我先是无法解决问题,但我还是有所帮助,然后能够解决问题。 下面是该守则的编号,但我无法得到的是,为什么我们在回历呼吁中通过i+1,为什么不通过index+1? 我试图这样做,而且显然它投下错误的产出。 我认为,这同通过i+1一样,因为我们要么正在增加index,正确吗?

function allSubseq(new_str, str, index) {
  if (new_str.length !== 0) {
    console.log(new_str.join(""));
  }
  if (index === str.length) {
    return;
  }
  for (let i = index; i < str.length; i++) {
    new_str.push(str[i]);
    allSubseq(new_str, str, i + 1);
    new_str.pop(); // Backtracking step
  }
}

let str = "abcd";
new_str = [];
allSubseq(new_str, str, 0);
最佳回答

这项工作是否如你所期望的那样? 我刚刚删除<代码>i。

let str = "abcd";
let new_str = [];
function allSubseq(new_str, str, index) {
  if (new_str.length !== 0) {
    console.log(new_str.join(""));
  }
  if (index === str.length) {
    return;
  }
  for (; index < str.length; index++) { // notice now we use index instead of i
    new_str.push(str[index]);
    allSubseq(new_str, str, index + 1);
    new_str.pop(); // Backtracking step
  }
}

也许,除非是固定的,否则你可能不应使用变数名称的强调,在这种情况下,在资本案件中,它都是书面的。

如果您保留<代码>i,仅替换all Subseq (new_str, str, i + 1);all Subseq(new_str, str, + 1);, 则你仍然只加一,而不是索引,由所有Subseq打电话。

// we begin with the first call
function allSubseq(new_str, str, index) {
    if (new_str.length !== 0) {
        console.log(new_str.join(""));
    }
    if (index === str.length) {
        return;
    }
    // we begin first loop, here index is 0, i is 0.
    for (let i = index; i < str.length; i++) {
        new_str.push(str[i]);
        // we call this function second time
        allSubseq(new_str, str, i + 1);
        new_str.pop();
    }
}
// we call this function second time
// inside this scope index is 1
function allSubseq(new_str, str, index) {
    if (new_str.length !== 0) {
        console.log(new_str.join(""));
    }
    if (index === str.length) {
        return;
    }
    // we begin second loop, here index is 1, i is 1.
    for (let i = index; i < str.length; i++) {
        new_str.push(str[i]);
        /* now lets pretend that this loop finished it s work with i and index as 1,
           let s also pretend that function exited without further recursion calls. */
        allSubseq(new_str, str, i + 1);
        new_str.pop();
    }
}
// we come back to our first function call to the for loop
function allSubseq(new_str, str, index) {
    if (new_str.length !== 0) {
        console.log(new_str.join(""));
    }
    if (index === str.length) {
        return;
    }
    for (let i = index; i < str.length; i++) {
        new_str.push(str[i]);
        allSubseq(new_str, str, i + 1); /* <- we finished this step,
          inside that function call i and index were 1.
          we now come back to this for loop that we began,
          here index and i are still 0. */
        new_str.pop();
    }
    /* we will now update i to be i + 1 (because of i++ inside loop)
 and begin next step of loop where i will be a bigger number than it used to be on last step,
 however if we use index instead of i at `allSubseq(new_str, str, i + 1);`,
 then we didn t update it (index) inside this loop and it will be the same number, on each step of the loop,
 it will only change inside recursion because we pass index + 1. */
}
问题回答

至少是分析这一问题的两个良好途径。 第一种是发射一枚浮gger。 这往往是最佳办法。 但是,你还可以增加伐木,以追踪所发生的情况。 此处是使用较短输入<代码>abc”(<>/code>)首先添加伐木的结果。

i + 1

allSubseq ([], "abc", 0)
    allSubseq ([a], "abc", 1)
    > console .log ("a")
        allSubseq ([a,b], "abc", 2)
        > console .log ("ab")
            allSubseq ([a,b,c], "abc", 3)
            > console .log ("abc")
        allSubseq ([a,c], "abc", 3)
        > console .log ("ac")
    allSubseq ([b], "abc", 2)
    > console .log ("b")
        allSubseq ([b,c], "abc", 3)
        > console .log ("bc")
    allSubseq ([c], "abc", 3)
    > console .log ("c")

之后

index + 1

allSubseq ([], "abc", 0)
    allSubseq ([a], "abc", 1)
    > console .log ("a")
        allSubseq ([a,b], "abc", 2)
        > console .log ("ab")
            allSubseq ([a,b,c], "abc", 3)
            > console .log ("abc")
        allSubseq ([a,c], "abc", 2)
        > console .log ("ac")
            allSubseq ([a,c,c], "abc", 3)
            > console .log ("acc")
    allSubseq ([b], "abc", 1)
    > console .log ("b")
        allSubseq ([b,b], "abc", 2)
        > console .log ("bb")
            allSubseq ([b,b,c], "abc", 3)
            > console .log ("bbc")
        allSubseq ([b,c], "abc", 2)
        > console .log ("bc")
            allSubseq ([b,c,c], "abc", 3)
            > console .log ("bcc")
    allSubseq ([c], "abc", 1)
    > console .log ("c")
        allSubseq ([c,b], "abc", 2)
        > console .log ("cb")
            allSubseq ([c,b,c], "abc", 3)
            > console .log ("cbc")
        allSubseq ([c,c], "abc", 2)
        > console .log ("cc")
            allSubseq ([c,c,c], "abc", 3)
            > console .log ("ccc")

这将有助于澄清正在发生什么,以及为什么你不想通过固定的<代码>指数+ 1。

但是,我还要指出更简单的执行:

const call = (fn, ...args) => 
  fn (...args)

const subseqs = ([c, ...cs]) => 
  c == undefined
    ? [  ]
    : call ((ss = subseqs (cs)) => ss .flatMap (s => c + s) .concat (ss))

const allSubseq = (s) => 
  subseqs (s) .filter (Boolean) // remove empty string

console .log (allSubseq ( abcd ))
.as-console-wrapper {max-height: 100% !important; top: 0}

在此,主要休养职能为<代码>下<>分>。 我们在<代码>all Subseq中总结,删除在<代码>下上产生的空洞。 如果你想要保持这一空洞,那么它就更加简单。

我们使用<条码>查询<>代码/代码>,作为在功能体内只包含表述而不是说明的<条码>、<条码>、然后加以使用和再使用的一种方式。 如果这样令人困惑,我们就能够绕过呼吁,用发言和像这样地方变量来做同样的事:

const subseqs = ([c, ...cs]) => {
  if (c == undefined) return [  ]
  const ss = subseqs (cs)
  return ss .flatMap (s => c + s) .concat (ss)
}

In either case, our base case is when the input string is empty, and we return an array containing only the empty string. If it s not, we calculate the subsequences for the tail of the string (everything but the first character) and return first those new subsequences prefixed by the first character and then those subsequences directly.

Note that this function does not print your results to the console, just returns them. This is clearly more flexible. If you want to print them individually, you can do something like console .log (allSubseq ( abcd ) .join ( )) or allSubseq ( abcd ) .forEach (console .log).


<><0>1 见。 如何减少小型方案

2You can view the tweaked source code for i + 1 and index + 1

function allSubseq(str, idx = 0, temp = "") {
    if (idx === str.length) {
        console.log(temp);
        return;
    }

    allSubseq(str, idx + 1, temp + str[idx]);
    allSubseq(str, idx + 1, temp);
}
allSubseq("abcd");

allSubseq("abcd");





相关问题
How to add/merge several Big O s into one

If I have an algorithm which is comprised of (let s say) three sub-algorithms, all with different O() characteristics, e.g.: algorithm A: O(n) algorithm B: O(log(n)) algorithm C: O(n log(n)) How do ...

Grokking Timsort

There s a (relatively) new sort on the block called Timsort. It s been used as Python s list.sort, and is now going to be the new Array.sort in Java 7. There s some documentation and a tiny Wikipedia ...

Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Enumerating All Minimal Directed Cycles Of A Directed Graph

I have a directed graph and my problem is to enumerate all the minimal (cycles that cannot be constructed as the union of other cycles) directed cycles of this graph. This is different from what the ...

Quick padding of a string in Delphi

I was trying to speed up a certain routine in an application, and my profiler, AQTime, identified one method in particular as a bottleneck. The method has been with us for years, and is part of a "...