How can I determine all possible ways a subsequence can be removed from a sequence?

前端 未结 6 2077
执念已碎
执念已碎 2021-01-31 08:29

Given two sequences, A and B, how can I generate a list of all the possible ways that B can be removed from A?

For example, In JavaSc

6条回答
  •  猫巷女王i
    2021-01-31 08:55

    You can use recursion. Build a new subsequence C by walking through A and pushing elements in order. Whenever you encounter an element that matches the head of B, you will fork the recursion into two paths: one in which you remove (i.e. skip) the element from A and B, and another in which you ignore it and continue business as usual.

    If you exhaust all of B (meaning that you "removed" all elements in B from A), then appending the rest of A to C will produce a valid subsequence. Otherwise, if you reach the end of A without exhausting all of B, C is not a valid subsequence and should be discarded.

    function removeSubSeq(a, b) {
        function* remove(i, j, c) {
            if (j >= b.length) {
                yield c.concat(a.slice(i));
            } else if (i >= a.length) {
                return;
            } else if (a[i] === b[j]) {
                yield* remove(i + 1, j + 1, c);
                yield* remove(i + 1, j, c.concat(a.slice(i, i + 1)));
            } else {
                yield* remove(i + 1, j, c.concat(a.slice(i, i + 1)));
            }
        }
    
        if (a.length < b.length) {
            return [];   
        }
    
        return Array.from(remove(0, 0, []));
    }
    

    The inner helper function can be made slightly more efficient by replacing the use of Array.concat in each recursive branch with a simple push()/pop() pair, although, this makes the control flow a little harder to grok.

    function* remove(i, j, c) {
        if (j >= b.length) {
            yield c.concat(a.slice(i));
        } else if (i >= a.length) {
            return;
        } else {
            if (a[i] === b[j]) {
                yield* remove(i + 1, j + 1, c);
            }
    
            c.push(a[i]);
            yield* remove(i + 1, j, c);
            c.pop();
        }
    }
    

提交回复
热议问题