找出最长的神奇数列

76 阅读4分钟

题目描述

小F是一个好学的中学生,今天他学习了数列的概念。他在纸上写下了一个由0和1组成的正整数序列,长度为n。这个序列中的1和0交替出现,且至少由3个连续的0和1组成的部分数列称为“神奇数列”。例如,10101是一个神奇数列,而1011不是。现在,小F想知道在这个序列中,最长的“神奇数列”是哪一个。你能帮他找到吗?

如果有多个神奇数列,那么输出最先出现的一个。

解决方案

我们需要找到一个序列中符合“神奇数列”定义的最长子序列。可以通过遍历序列来检查每个可能的子序列,判断其是否符合条件,并记录最长的符合条件的子序列。

分析思路

  1. 初始化变量

    • 记录当前最长的“神奇数列”的起始位置和长度。
    • 临时变量用于记录当前正在检查的子序列的长度和起始位置。
  2. 遍历序列

    • 从头到尾遍历序列,检查每一对相邻字符,判断是否满足交替出现的条件。
    • 如果满足条件,则更新当前子序列的长度。
    • 如果不满足条件,则检查当前子序列的长度是否符合“神奇数列”的定义(即长度至少为5)。如果符合,则更新最长的“神奇数列”的起始位置和长度。
  3. 处理尾部的情况

    • 在遍历完成后,检查最后一个子序列是否符合“神奇数列”的定义。
  4. 输出结果

    • 根据最长的“神奇数列”的起始位置和长度,输出该子序列。如果没有符合条件的子序列,则输出空字符串。

代码实现

java

public class MagicSubsequence {
    public static void main(String[] args) {
        String sequence = "1001011001010101";
        System.out.println("最长的神奇数列是: " + findLongestMagicSequence(sequence));
    }

    public static String findLongestMagicSequence(String s) {
        int n = s.length();
        int maxLength = 0;
        int start = -1;
        int currentLength = 0;
        int currentStart = -1;

        for (int i = 1; i < n; i++) {
            if ((s.charAt(i - 1) == '0' && s.charAt(i) == '1') || (s.charAt(i - 1) == '1' && s.charAt(i) == '0')) {
                if (currentLength == 0) {
                    currentStart = i - 1;
                }
                currentLength++;
            } else {
                if (currentLength >= 4) {
                    if (currentLength > maxLength) {
                        maxLength = currentLength;
                        start = currentStart;
                    }
                }
                currentLength = 0;
            }
        }

        // 处理尾部情况
        if (currentLength >= 4) {
            if (currentLength > maxLength) {
                maxLength = currentLength;
                start = currentStart;
            }
        }

        return start == -1 ? "" : s.substring(start, start + maxLength + 1);
    }
}

代码解释

  1. 初始化变量

    • maxLength 用于记录当前最长“神奇数列”的长度,初始值为0。
    • start 用于记录当前最长“神奇数列”的起始位置,初始值为-1。
    • currentLength 用于记录当前正在检查的子序列的长度,初始值为0。
    • currentStart 用于记录当前正在检查的子序列的起始位置,初始值为-1。
  2. 遍历序列

    • 使用for循环从序列的第二个字符开始遍历,检查每对相邻字符。
    • 如果两个字符交替出现,则更新当前子序列的长度和起始位置。
    • 如果两个字符不交替出现,则检查当前子序列的长度是否为“神奇数列”,如果是,则更新最长的“神奇数列”的长度和起始位置。
  3. 处理尾部情况

    • 在遍历结束后,检查最后一个子序列是否为“神奇数列”,如果是,则更新最长的“神奇数列”的长度和起始位置。
  4. 输出结果

    • 根据maxLengthstart,返回最长的“神奇数列”。如果没有符合条件的子序列,则返回空字符串。

复杂度分析

  • 时间复杂度:因为我们需要遍历整个字符串,每个字符只处理一次,因此时间复杂度为O(n),其中n是字符串的长度。
  • 空间复杂度:我们只使用了常数级别的额外空间(用于存储索引和长度),因此空间复杂度为O(1)。

总结

通过以上步骤和实现,我们可以在给定的字符串中高效地找到最长的“神奇数列”。这个方法利用了线性扫描和条件判断,能够在一次遍历中解决问题。