简体   繁体   中英

How can I find the number of non-decreasing subsequences in an array?

Given an array of positive integers, I want to find out the number of non-decreasing sub-sequences in the array.

For example if the array is {6,7,8,4,5,6} , non decreasing sub-sequences would be {6},{7},{8},{4},{5},{6},{6,7},{7,8},{4,5},{5,6},{6,7,8},{4,5,6} so that's 12 such sequence

This is an algorithm that will list every rising sub-sequence in a sequence of numbers:

Set a pointer to the first item, to remember where the rising sequence starts.
Iterate over every item in the array, and for each item:  
    If the current item is not greater than the previous item:  
        Set the pointer to the current item.
    For every n = 1, 2, 3... :
        Save the last n items as a sequence until you reach the pointer.

A run-through of this algorithm with your example input [6,7,8,4,5,6] would be:

step 1: start=6, current=6, store [6]
step 2: start=6, current=7, comp 7>6=true, store [7], [6,7]
step 3: start=6, current=8, comp 8>7=true, store [8], [7,8], [6,7,8]
step 4: start=6, current=4, comp 4>8=false, set start to current item, store [4]
step 5: start=4, current=5, comp 5>4=true, store [5], [4,5]
step 6: start=4, current=6, comp 6>5=true, store [6], [5,6], [4,5,6]

result: [6], [7], [6,7], [8], [7,8], [6,7,8], [4], [5], [4,5], [6], [5,6], [4,5,6]

For example in javascript: (note: the slice() function is used to create hard copies of arrays)

 function rising(array) { var sequences = [], start = 0; for (var current = 0; current < array.length; current++) { var seq = [], from = current; if (array[current] < array[current - 1]) start = current; while (from >= start) { seq.unshift(array[from--]); sequences.push(seq.slice()); } } return sequences; } var a = rising([6,7,8,4,5,6]); document.write(JSON.stringify(a)); 

If you want the results in the order you wrote them in the question: [6],[7],[8],[4],[5],[6],[6,7],[7,8],[4,5],[5,6],[4,5,6],[6,7,8] then make sequences a 2D array and store each sequence seq in sequences[seq.length] .

You can use dynamic programming approach similar to the well-known quadratic solution for the longest increasing subsequence .

Let a[i] be your input array. Let c[i] be the number of non-decreasing subsequences that end at a[i] . You can easily calculate c[i] by looking what can be the number preceding a[i] in such a subsequence. It can be any number a[j] that goes before a[i] (that is, j<i ) and that is not greater ( a[j]<=a[i] ). Do not forget the one-element subsequence {a[i]} also. This leads to the following pseudocode:

c[0] = 1
for i = 1..n-1
    c[i] = 1 // the one-element subsequence
    for j = 0..i-1 
        if a[j]<=a[i]
            c[i] += c[j]

See also Number of all longest increasing subsequences . It looks only for the longest sequences, but I guess it can be modified to count all such sequences too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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