2

Lets say we have an array {1, 1, 2, 3, 6, 5, 5, 4, 6}

Find the longest contiguous odd/even or even/odd subsequence in the array.

Answer is 5: {1, 2, 3, 6, 5}

My idea is to find two subsequence

  1. starting number is odd
  2. starting number is even

return the max of both

The code i wrote finds the longest subsequence, but is not contiguous

public static int longestAlternativeSequence(int[] a, int n) {
    int maxOdd = 0; //Max subsequence starting with odd Number
    int maxEven = 0; //Max subsequence starting with even Number
    int odd = 0;
    int even = 0;
    
    for (int i = 0; i < n; i++) {
        if (odd == 0) { // first number has to be odd
            if (a[i] % 2 == 1) {
                odd = 1;
                maxOdd++;
            }
        }
        
        else {
            if (a[i] % 2 == 0) {
                odd = 0;
                maxOdd++;
            }
        }
    }
    
    for (int i = 0; i < n; i++) {
        if (even == 0) { //first number has to be even
            if (a[i] % 2 == 0) {
                even = 1;
                maxEven++;
            }
        }
        else {
            if (a[i] % 2 == 1) {
                even = 1;
                maxEven++;
            }
        }
    }
    return Math.max(maxOdd, maxEven);
}
public static void main(String[] args) {
    int a[] = {1, 1, 2, 3, 6, 5, 5, 4, 6};
    int n = a.length; 
    System.out.println(longestOddEven(a, n)); //returns 6
}
Sercan
  • 2,081
  • 2
  • 10
  • 23
  • Write a method that goes through the array starting at a position and returns the length of the even/odd or odd/even subsequence. Write another method that calls the first method for each element of the array, ending when the remaining elements are less than the longest subsequence found. – Gilbert Le Blanc Jun 23 '20 at 20:23
  • the code i came up with finds the longest subsequence, but its not contigous – Sharhad Bashar Jun 23 '20 at 20:30
  • You're trying to do all the work in one method. My original advice is still valid. Divide and conquer. Use two or more methods. – Gilbert Le Blanc Jun 23 '20 at 20:36
  • @GilbertLeBlanc using more than one method is just complicating things. You just need nested loops. – Andy Turner Jun 23 '20 at 20:39
  • @AndyTurner I'm trying to reduce the mental problem complexity for the OP, not the code complexity. Concentrate on one small part of the problem at a time. Besides, separate methods are easier to test. – Gilbert Le Blanc Jun 23 '20 at 20:43

4 Answers4

1

I tested for a few cases and hope this will work for you:

public static int longestAlternativeSequence(int[] a, int n){
    if (n == 0) return 0;

    boolean isOdd = a[0] % 2 == 1;
    int tempCount = 1;
    int res = 0;

    for (int i = 1; i < n; ++i){
        if ((isOdd && a[i] % 2 == 0) || (!isOdd && a[i] % 2 == 1)){
            ++tempCount;
            isOdd = a[i] % 2 == 1;
        }else{
            res = Math.max(tempCount, res);
            tempCount = 1;
        }
    }

    res = Math.max(tempCount, res);
    return res;
}

Basically what we have here is that tracking previous number's status (odd or even) and compare it with current number. If the case is true, we keep counting with temporary counter. If not, then we check whether tempCount is bigger than res or not, and reset tempCount.

If array is empty, it returns zero, otherwise it will return at least one because anyway single odd or even number complies the case.

Lastly, if correct answer ends with last element of the array, then else clause is not reachable for one last check, that is why we need to update res after looping.

Sercan
  • 2,081
  • 2
  • 10
  • 23
0

This is just for fun. If you don't like it, ignore it.

static final Pattern ZERO_ONE_SEQUENCE = Pattern.compile("1?(01)*0?");

static int[] longestOddEvenSubsequence(int[] input) {
    String binaryString = Arrays.stream(input)
        .mapToObj(intValue -> Integer.toString(intValue & 1))
        .collect(Collectors.joining());
    return ZERO_ONE_SEQUENCE.matcher(binaryString).results()
        .map(m -> Arrays.copyOfRange(input, m.start(), m.end()))
        .max(Comparator.comparing(intArray -> intArray.length))
        .get();
}

and

System.out.println(Arrays.toString(
    longestOddEvenSubsequence(new int[] {1, 1, 2, 3, 6, 5, 5, 4, 6})));
// -> [1, 2, 3, 6, 5]
0

How about this one here? It uses recursion and memoization. It is a different approach and might be an overkill for this task, but it does more or less the same as the for-loop-solution. It really depends on what you want to do with it and if you want to extend it further later on.

I have also added a few test cases below including negative integers.

public static int maxEvenOddContinousSequence(int[] a) {
    final int numElements = a.length;
    int result;
    if (numElements == 0) {
        result = 0;
    } else if (numElements == 1) {
        result = 1;
    } else {
        result = findEvenOddContinousSubsequence(a, numElements, 0, a[0] % 2 == 0, 0, 0);
    }
    return result;
}

private static int findEvenOddContinousSubsequence(int[] a, int numElements, int index, boolean isEven, int currentLongestSequence, int longestSequence) {
    if (index < numElements) {
        final int currentElement = Math.abs(a[index]);
        final int currentElementMod2 = currentElement % 2;
        if (currentElementMod2 == (isEven ? 0 : 1)) {
            return findEvenOddContinousSubsequence(a, numElements, ++index, !isEven, ++currentLongestSequence, longestSequence);
        } else {
            return findEvenOddContinousSubsequence(a, numElements, index, currentElementMod2 == 0, 0, Math.max(currentLongestSequence, longestSequence));
        }
    }
    return Math.max(currentLongestSequence, longestSequence);
}

public static void main(String[] args) {
    int a[] = {};
    int b[] = {1};
    int c[] = {1, 2};
    int d[] = {1, 1, 2, 3, 6, 5};
    int e[] = {1, 1, 3, 3, 6, 5, 2, 5, 2, 4, 6};
    int f[] = {0, -1, -3, -6, -5, -2};
    System.out.println("A:" + maxEvenOddContinousSequence(a)); // expected: 0 => []
    System.out.println("B:" + maxEvenOddContinousSequence(b)); // expected: 1 => [1]
    System.out.println("C:" + maxEvenOddContinousSequence(c)); // expected: 2 => [1, 2]
    System.out.println("D:" + maxEvenOddContinousSequence(d)); // expected: 5 => [1, 2, 3, 6, 5]
    System.out.println("E:" + maxEvenOddContinousSequence(e)); // expected: 6 => [3, 6, 5, 2, 5, 2]
    System.out.println("F:" + maxEvenOddContinousSequence(f)); // expected: 4 => [-3, -6, -5, -2]
}

Output: A:0 B:1 C:2 D:5 E:6 F:4

F. Müller
  • 3,969
  • 8
  • 38
  • 49
0

This function will return start and next-to-last index of required interval. It's based on simple idea of checking the current and the previous. Note, the i <= arr.length condition, as it deals with case when the interval runs till the end. This case is checked in if.

static int[] contAlternating(int[] arr) {
            if (arr == null || arr.length == 0)
                return null;
            if (arr.length == 1)
                return new int[] { 0, 1 };
            int lastStart = 0;
            int maxStart = 0;
            int maxEnd = 1;
            for (int i = 1; i <= arr.length; i++) {
                if ((i < arr.length)
                        && ((arr[i] % 2 == 0 && arr[i - 1] % 2 == 1) || (arr[i] % 2 == 1 && arr[i - 1] % 2 == 0))) {
                    continue;
                }
                if (i - lastStart > maxEnd - maxStart) {
                    maxStart = lastStart;
                    maxEnd = i;
                }
                lastStart = i;
            }
            return new int[] { maxStart, maxEnd };
        }
Leon .Leon
  • 11
  • 3