简体   繁体   中英

How to find the longest alternating increasing subsequence by alternating between two arrays

Given two arrays of numbers, how do I find the longest increasing subsequence by alternating between the elements of the two arrays? for example

A = [4, 1, 10, 5, 9]
B = [4, 5, 7, 14]
so the output must be [1,4,5,7,9,14]

It HAS to be in the format of element of a, element of b, element of a, element of b... so on.

I tried finding a solution but I couldn't think of anything, I tried the LIS approach but since that code requires one array only that didnt make sense to me either sorry

(just in case, to make it more clear = [ 1(A), 4(B), 5(A), 7(B), 9(A), 14(B)] also, note how the order cannot be changed) Thanks and sorry if I've not phrased it properly

The simplest way would just be to do:

# lias: Longest Increasing Alternating Subsequence
def lias(curr, next, seq):
    good, elem = False, None
    while not good:
        if not curr: return seq
        elem = min(curr); curr.remove(elem)
        good = False if elem in seq or elem < max(seq, default=0) else True
    seq.append(elem)
    return lias(next, curr, seq)


if __name__ == '__main__':
    A = [4, 1, 10, 5, 9]
    B = [4, 5, 7, 14]
    print(lias(A,B, []))
    

You can define a recursive solution that builds the sequence one element at a time based on the previous element and the remaining elements of the list it came from. Each recursion can swap the parameter order so that the logic only needs to care about one of the lists.

This can be further optimized by carrying a length target based on the longest sequence found so far.

For example:

def longAltSeq(A,B,prev=None,minLen=0):
    result = longAltSeq(B,A,min(B)-1) if prev is None else [] # inverted params
    for i,a in enumerate(A): # Start with an item from A
        if prev is not None and a<=prev: continue     # increasing from previous
        if 2*min(len(A)-i,len(B)+1)<minLen: break     # not enough items left
        seq = [a]+longAltSeq(B,A[i+1:],a,len(result)) # alternate A<->B
        if len(seq)>len(result): result = seq         # track longest
    return result

ouput:

A = [4, 1, 10, 5, 9]
B = [4, 5, 7, 14]
print(longAltSeq(A,B))
[1, 4, 5, 7, 9, 14]

The solution starts with the inverted parameters so that the initial order of the lists doesn't matter

Here's a solution in JavaScript that'll work. You should be able to replicate that logic in Python or whatever language you need. Cheers, and welcome to the community!

var A = [4, 1, 10, 5, 9];
var B = [4, 5, 7, 14];

run(A,B);

function getSmallest(list, limit){
    var results = [];
    list.forEach(number => {
    if (number > limit)
        results.push(number);
    });
    results.sort(function(a, b) {
        return a - b;
    });
  return results[0];
}

function run(list_a,list_b){
    var result = [];
    var current_list = 1;
    var current_limit = Number.NEGATIVE_INFINITY;
    
    while (current_limit != undefined) {
        current_limit = getSmallest((current_list) ? list_a : list_b, current_limit);
        current_list = !current_list;
        result.push(current_limit);
    }

    result.pop();
    console.log(result);
}

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