2

I'm looking for an algorithm that given a list like:

[1, 1, 2, 1, 1, 5, 1, 1, 1, 1, 2, 1]

can find and return all subsequences of a given value. For example, if given the value 1, the function would return [[1, 1], [1, 1], [1, 1, 1, 1], [1]].

I believe this is similar to problems such as summing up all subsequences of an array or finding all the subsequences of a given string but algorithms was never my strong suit. The answer can be psuedo-code or language agnostic. And if you wouldn't mind, could you explain the complexity of the solution?

I can explain what I need this for if that helps. Comment if you want that.

barndog
  • 6,975
  • 8
  • 53
  • 105
  • can you explain how all of your sub-lists are supposed to have the `value 1`? ... What is the property here? (My best guess: you want all subsequences where all values in it are at most 1) – Random Dev Apr 20 '16 at 04:20
  • also: last time I checked `[1,1,1,1,1,1,1,1,1]` would be a subsequence too [see the definition](https://en.wikipedia.org/wiki/Subsequence) – Random Dev Apr 20 '16 at 04:22
  • True yes, it would be a subsequence, but all the solutions I was looking at were about either summing up a subsequence or finding the longest subsequence, not returning the actually sequences themselves. And no, 1 was just an arbitrary example I chose. – barndog Apr 20 '16 at 04:28
  • so you just want to split the list as soon as there is an element `neq 1`? – Random Dev Apr 20 '16 at 04:29
  • No I'm doing something much more complex than that, having to do with CoreVideo and AVFoundation in iOS, I was just wondering about how I'd accomplish this on a high level. – barndog Apr 20 '16 at 04:30
  • it's just a matter of going along the input (for example taking an accumulator with you) and put the element into the accumulator as long as they true for your property) - once it is not you push the accumulator to the output and and start a new one – Random Dev Apr 20 '16 at 04:30
  • Sounds like a problem that a `reduce` function could possibly solve? – barndog Apr 20 '16 at 04:32
  • sure - but if you program in a language where you have `reduce` you probably have said `splitBy` already as well – Random Dev Apr 20 '16 at 04:35
  • I wish but `splitBy` won't work for me, I just used integers to simply y example down. – barndog Apr 20 '16 at 04:40

3 Answers3

1

We can do this in O(n) time complexity by scanning the array twice. Pseudocode:

//use an array list so we can access element at an index in O(1) time
outputArrays = new ArrayList<int[]> //list of arrays

//loop to declare arrays of outputs - this scans each element once
int currLen = 0;
for (item in inputArray) {
 if (item = itemToLookFor) {
  currLen++;
 }else if (currLen > 0) {
  currLen = 0;
  outputArrays.add(new int[currLen]);
 }
}

//loop to actually populate the output - this scans each element once
currLen = 0;
currIndex = 0;
for (item in inputArray) {
 if (item = itemToLookFor) {
  outputArrays.getElement(currIndex)[currLen] = item;
  currLen++;
 }else if (currLen > 0) {
  currLen = 0;
  currIndex++;
 }
}

Let me know if there is anything i can clarify.

nhouser9
  • 6,730
  • 3
  • 21
  • 42
  • So first you build up the output arrays and then you populate the arrays. Is there any reason that can't be done within one loop? And perchance, is there a more functional way to approach the problem? – barndog Apr 20 '16 at 04:26
  • @startupthekid none - and of course there is a functional way - once you actually said what you want it's gonna by a one-liner in any reasonable FP language - the question is only if you want `filter (all (== 0)) . subsequences` or a simple `splitBy` – Random Dev Apr 20 '16 at 04:28
  • Well I guess what I really want is all subsequences that pass a filter condition. So say for example the filter is `{ x % 2 == 0 }` and the input array was `[1, 2, 2, 3, 4, 4]`, the output would be `[[2, 2], [4, 4]]` if that makes sense. – barndog Apr 20 '16 at 04:30
  • @startupthekid I'm sure there are many ways to do this natively, probably with a single call. I answered like this because I thought you wanted to see an algorithm (as the question is tagged), not a library call. And if you don't need your output as arrays, you can do this in a single pass. – nhouser9 Apr 20 '16 at 04:30
  • @startupthekid meeting a condition is no problem - just make a helper method that checks that condition given an input and replace the line `if (item = itemToLookFor)` with your helper method. – nhouser9 Apr 20 '16 at 04:31
  • I do need the output as arrays and the library calls are semantics, that's just the boolean condition. I'll try out your solution and modify it to my needs; I'll accept your answer once I've done that. – barndog Apr 20 '16 at 04:32
  • @startupthekid yeah if you need arrays, you will need to do this in two passes (as far as I can see) because the first pass gets the length of the arrays. Let me know if you run into issues - i will be happy to help. – nhouser9 Apr 20 '16 at 04:34
0

Let a be initial array, res - resulting array of sequences, curSeq - a current sequence, given_value - a given value.

res = []
curSeq = []
for i = 1..length(a)
    if a[i] != given_value
        if curSeq has at least one item
            append curSeq to res
        end if
        curSeq = []
    else
        append given_value to curSeq
    end if
end for
if curSeq has at least one item
    append curSeq to res
end if

As you can see the time complexity is O(n) where n is the length of initial array.

Ivan Gritsenko
  • 4,166
  • 2
  • 20
  • 34
0

Here is the O(n) solution. Here arr is input array of sequence and sequence is array for sub-sequence. You can save sequence another array for your answer.

arr = [1, 1, 2, 1, 1, 5, 1, 1, 1, 1, 2, 1]; // here is your
selectNumber = 1 //take input for selected input
sequence = [];
for (i: 0 to arr.length) {
  if (arr[i] == selectNumber) {
    sequence.push(selectNumber);
  } else {
    if(sequence.length > 0) {
      print sequence;
      sequence = [] // empty sequence array as it is already printed or saved
    }
  }
}

if (sequence > 0) {
  print sequence; // last sequence if exist
}
Abu Hanifa
  • 2,857
  • 2
  • 22
  • 38