【问题标题】:Find the longest contiguous alternating sequence找到最长的连续交替序列
【发布时间】:2020-06-23 20:16:14
【问题描述】:

假设我们有一个数组 {1, 1, 2, 3, 6, 5, 5, 4, 6}

找出数组中最长的连续奇数/偶数或偶数/奇数子序列。

答案是 5:{1, 2, 3, 6, 5}

我的想法是找到两个子序列

  1. 起始编号为奇数
  2. 起始编号为偶数

返回两者的最大值

我写的代码找到了最长的子序列,但是不连续

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
}

【问题讨论】:

  • 编写一个方法,从一个位置开始遍历数组并返回偶数/奇数或奇数/偶数子序列的长度。编写另一个方法,为数组的每个元素调用第一个方法,当剩余元素小于找到的最长子序列时结束。
  • 我想出的代码找到了最长的子序列,但它不是连续的
  • 您正试图以一种方法完成所有工作。我最初的建议仍然有效。分而治之。使用两种或多种方法。
  • @GilbertLeBlanc 使用不止一种方法只会使事情复杂化。你只需要嵌套循环。
  • @AndyTurner 我试图降低 OP 的心理问题复杂性,而不是代码复杂性。一次只专注于问题的一小部分。此外,单独的方法更容易测试。

标签: java arrays algorithm subsequence


【解决方案1】:

我测试了几个案例,希望这对你有用:

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;
}

基本上我们在这里是跟踪以前号码的状态(奇数或偶数)并将其与当前号码进行比较。如果情况属实,我们继续用临时计数器计数。如果不是,则检查tempCount是否大于res,并重置tempCount

如果数组为空,则返回零,否则至少返回一,因为无论如何单个 oddeven 数字都符合这种情况。

最后,如果正确答案以数组的最后一个元素结束,那么else 子句无法进行最后一次检查,这就是为什么我们需要在循环后更新res

【讨论】:

    【解决方案2】:

    这只是为了好玩。如果你不喜欢它,请忽略它。

    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();
    }
    

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

    【讨论】:

      【解决方案3】:

      这个怎么样?它使用recursionmemoization。这是一种不同的方法,对于这项任务可能有点过头了,但它与for-loop-solution 的作用或多或少相同。这真的取决于你想用它做什么,以及你以后是否想进一步扩展它。

      我还在下面添加了一些测试用例,包括负整数。

      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]
      }
      

      输出: 答:0 乙:1 C:2 D:5 E:6 F:4

      【讨论】:

        【解决方案4】:

        此函数将返回所需间隔的开始和倒数第二个索引。它基于检查当前和以前的简单想法。请注意,i &lt;= arr.length 条件,因为它处理间隔运行到结束的情况。这个案例在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 };
                }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-15
          • 2013-05-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多