最长湍流子数组问题
字数 3552 2025-11-01 15:29:06

最长湍流子数组问题

题目描述
给定一个整数数组 arr,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组为湍流子数组。更正式地说,对于子数组 arr[i..j]:

  • 当 i <= k < j 时:
    • 如果 k 是偶数,那么 arr[k] > arr[k+1] 当且仅当 arr[k+1] < arr[k+2](当 k+2 <= j)
    • 如果 k 是奇数,那么 arr[k] < arr[k+1] 当且仅当 arr[k+1] > arr[k+2](当 k+2 <= j)
      或者另一种等价定义是:湍流子数组中,元素的大小关系交替变化(即 >, <, >, <, ... 或 <, >, <, >, ...)。
      求 arr 中最长湍流子数组的长度。

解题过程

  1. 问题理解与重新表述
    湍流子数组要求相邻元素的大小关系必须交替变化。例如,对于子数组 [a, b, c]:

    • 如果 a > b,则必须 b < c
    • 如果 a < b,则必须 b > c
    • 如果 a = b,则这个子数组不可能是湍流的(因为大小关系没有变化)

    我们可以将问题重新表述为:找到最长的连续子数组,其中每个相邻三元组 (arr[i], arr[i+1], arr[i+2]) 都满足湍流条件。

  2. 动态规划状态定义
    我们可以定义两个状态数组:

    • up[i]:表示以位置 i 结尾,且 arr[i] > arr[i-1] 的最长湍流子数组长度
    • down[i]:表示以位置 i 结尾,且 arr[i] < arr[i-1] 的最长湍流子数组长度

    这样定义的原因是:湍流子数组的大小关系是交替的,我们需要分别跟踪当前是上升趋势还是下降趋势。

  3. 状态转移方程
    对于每个位置 i (i ≥ 1):

    • 如果 arr[i] > arr[i-1]:
      • up[i] = down[i-1] + 1(因为当前是上升,前一个应该是下降)
      • down[i] = 1(下降趋势重置为1,因为当前不符合下降条件)
    • 如果 arr[i] < arr[i-1]:
      • down[i] = up[i-1] + 1(因为当前是下降,前一个应该是上升)
      • up[i] = 1(上升趋势重置为1)
    • 如果 arr[i] == arr[i-1]:
      • up[i] = 1
      • down[i] = 1

    初始条件:对于 i = 0,up[0] = 1down[0] = 1(单个元素可以视为长度为1的湍流子数组)

  4. 计算过程示例
    假设 arr = [9, 4, 2, 10, 7, 8, 8, 1, 9]

    i=0: up=1, down=1, max_len=1
    i=1: 9>4? 否;9<4? 否;9=4? 否 → 4<9? 是 → down[1]=up[0]+1=2, up[1]=1, max_len=2
    i=2: 4>2? 是 → up[2]=down[1]+1=3, down[2]=1, max_len=3
    i=3: 2<10? 是 → down[3]=up[2]+1=4, up[3]=1, max_len=4
    i=4: 10>7? 是 → up[4]=down[3]+1=5, down[4]=1, max_len=5
    i=5: 7<8? 是 → down[5]=up[4]+1=6, up[5]=1, max_len=6
    i=6: 8=8? 是 → up[6]=1, down[6]=1, max_len=6
    i=7: 8>1? 是 → up[7]=down[6]+1=2, down[7]=1, max_len=6
    i=8: 1<9? 是 → down[8]=up[7]+1=3, up[8]=1, max_len=6

    最终结果为6,对应子数组 [4, 2, 10, 7, 8, 8] 不满足,应该是 [4, 2, 10, 7, 8] 长度为5?让我们检查:
    实际正确的最长湍流子数组是 [4, 2, 10, 7, 8] 或 [2, 10, 7, 8, 1, 9],长度应该是5?让我重新计算...

    等等,我发现了错误。让我重新分析:

    正确的计算应该是:
    arr = [9, 4, 2, 10, 7, 8, 8, 1, 9]

    i=0: up=1, down=1, max=1
    i=1: 9>4 → up[1]=down[0]+1=2, down[1]=1, max=2
    i=2: 4>2 → up[2]=down[1]+1=2, down[2]=1, max=2
    i=3: 2<10 → down[3]=up[2]+1=3, up[3]=1, max=3
    i=4: 10>7 → up[4]=down[3]+1=4, down[4]=1, max=4
    i=5: 7<8 → down[5]=up[4]+1=5, up[5]=1, max=5
    i=6: 8=8 → up[6]=1, down[6]=1, max=5
    i=7: 8>1 → up[7]=down[6]+1=2, down[7]=1, max=5
    i=8: 1<9 → down[8]=up[7]+1=3, up[8]=1, max=5

    正确结果是5,对应子数组 [4, 2, 10, 7, 8] 或 [2, 10, 7, 8, 1, 9]?等等,[2, 10, 7, 8, 1, 9] 长度是6,让我验证:
    2<10, 10>7, 7<8, 8>1, 1<9 ✓ 确实是湍流子数组,长度为6

    我意识到我的计算有误。让我重新仔细计算:

    对于 i=2: arr[2]=2, arr[1]=4 → 4>2 ✓
    但 up[2] 应该 = down[1]+1,而 down[1] 是多少?

    让我一步步来:
    i=0: up=1, down=1
    i=1: arr[1]=4, arr[0]=9 → 9>4 ✓ → up[1]=down[0]+1=2, down[1]=1
    i=2: arr[2]=2, arr[1]=4 → 4>2 ✓ → up[2]=down[1]+1=2, down[2]=1
    i=3: arr[3]=10, arr[2]=2 → 2<10 ✓ → down[3]=up[2]+1=3, up[3]=1
    i=4: arr[4]=7, arr[3]=10 → 10>7 ✓ → up[4]=down[3]+1=4, down[4]=1
    i=5: arr[5]=8, arr[4]=7 → 7<8 ✓ → down[5]=up[4]+1=5, up[5]=1
    i=6: arr[6]=8, arr[5]=8 → 相等 → up[6]=1, down[6]=1
    i=7: arr[7]=1, arr[6]=8 → 8>1 ✓ → up[7]=down[6]+1=2, down[7]=1
    i=8: arr[8]=9, arr[7]=1 → 1<9 ✓ → down[8]=up[7]+1=3, up[8]=1

    最大值出现在 i=5,值为5。但 [2,10,7,8,1,9] 长度是6,说明我的状态定义或计算有误。

  5. 修正状态定义
    我意识到问题:我的状态定义只考虑了相邻两个元素的关系,但湍流子数组需要交替变化。让我修正方法。

    更准确的方法是:定义 dp[i] 表示以 i 结尾的最长湍流子数组长度。
    我们需要比较 arr[i] 与 arr[i-1] 的关系,以及 arr[i-1] 与 arr[i-2] 的关系。

    正确的状态转移:

    • 如果 (arr[i] > arr[i-1] 且 arr[i-1] < arr[i-2]) 或 (arr[i] < arr[i-1] 且 arr[i-1] > arr[i-2]):
      • dp[i] = dp[i-1] + 1
    • 否则如果 arr[i] ≠ arr[i-1]:
      • dp[i] = 2
    • 否则:
      • dp[i] = 1
  6. 最终解决方案
    经过分析,最初的双状态方法实际上是正确的,但我的计算有误。让我给出最终正确的代码逻辑:

    def maxTurbulenceSize(arr):
        if len(arr) == 1:
            return 1
    
        up = [1] * len(arr)  # 以i结尾,且arr[i] > arr[i-1]
        down = [1] * len(arr)  # 以i结尾,且arr[i] < arr[i-1]
    
        max_len = 1
    
        for i in range(1, len(arr)):
            if arr[i] > arr[i-1]:
                up[i] = down[i-1] + 1
                down[i] = 1
            elif arr[i] < arr[i-1]:
                down[i] = up[i-1] + 1
                up[i] = 1
            else:  # arr[i] == arr[i-1]
                up[i] = 1
                down[i] = 1
    
            max_len = max(max_len, up[i], down[i])
    
        return max_len
    

    对于 arr = [9,4,2,10,7,8,8,1,9],正确结果是 5(对应子数组 [4,2,10,7,8] 或 [10,7,8,1,9] 等)。

最长湍流子数组问题 题目描述 给定一个整数数组 arr,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组为湍流子数组。更正式地说,对于子数组 arr[ i..j ]: 当 i <= k < j 时: 如果 k 是偶数,那么 arr[ k] > arr[ k+1] 当且仅当 arr[ k+1] < arr[ k+2](当 k+2 <= j) 如果 k 是奇数,那么 arr[ k] < arr[ k+1] 当且仅当 arr[ k+1] > arr[ k+2](当 k+2 <= j) 或者另一种等价定义是:湍流子数组中,元素的大小关系交替变化(即 >, <, >, <, ... 或 <, >, <, >, ...)。 求 arr 中最长湍流子数组的长度。 解题过程 问题理解与重新表述 湍流子数组要求相邻元素的大小关系必须交替变化。例如,对于子数组 [ a, b, c ]: 如果 a > b,则必须 b < c 如果 a < b,则必须 b > c 如果 a = b,则这个子数组不可能是湍流的(因为大小关系没有变化) 我们可以将问题重新表述为:找到最长的连续子数组,其中每个相邻三元组 (arr[ i], arr[ i+1], arr[ i+2 ]) 都满足湍流条件。 动态规划状态定义 我们可以定义两个状态数组: up[i] :表示以位置 i 结尾,且 arr[ i] > arr[ i-1 ] 的最长湍流子数组长度 down[i] :表示以位置 i 结尾,且 arr[ i] < arr[ i-1 ] 的最长湍流子数组长度 这样定义的原因是:湍流子数组的大小关系是交替的,我们需要分别跟踪当前是上升趋势还是下降趋势。 状态转移方程 对于每个位置 i (i ≥ 1): 如果 arr[ i] > arr[ i-1 ]: up[i] = down[i-1] + 1 (因为当前是上升,前一个应该是下降) down[i] = 1 (下降趋势重置为1,因为当前不符合下降条件) 如果 arr[ i] < arr[ i-1 ]: down[i] = up[i-1] + 1 (因为当前是下降,前一个应该是上升) up[i] = 1 (上升趋势重置为1) 如果 arr[ i] == arr[ i-1 ]: up[i] = 1 down[i] = 1 初始条件:对于 i = 0, up[0] = 1 , down[0] = 1 (单个元素可以视为长度为1的湍流子数组) 计算过程示例 假设 arr = [ 9, 4, 2, 10, 7, 8, 8, 1, 9 ] i=0: up=1, down=1, max_ len=1 i=1: 9>4? 否;9<4? 否;9=4? 否 → 4<9? 是 → down[ 1]=up[ 0]+1=2, up[ 1]=1, max_ len=2 i=2: 4>2? 是 → up[ 2]=down[ 1]+1=3, down[ 2]=1, max_ len=3 i=3: 2<10? 是 → down[ 3]=up[ 2]+1=4, up[ 3]=1, max_ len=4 i=4: 10>7? 是 → up[ 4]=down[ 3]+1=5, down[ 4]=1, max_ len=5 i=5: 7<8? 是 → down[ 5]=up[ 4]+1=6, up[ 5]=1, max_ len=6 i=6: 8=8? 是 → up[ 6]=1, down[ 6]=1, max_ len=6 i=7: 8>1? 是 → up[ 7]=down[ 6]+1=2, down[ 7]=1, max_ len=6 i=8: 1<9? 是 → down[ 8]=up[ 7]+1=3, up[ 8]=1, max_ len=6 最终结果为6,对应子数组 [ 4, 2, 10, 7, 8, 8] 不满足,应该是 [ 4, 2, 10, 7, 8 ] 长度为5?让我们检查: 实际正确的最长湍流子数组是 [ 4, 2, 10, 7, 8] 或 [ 2, 10, 7, 8, 1, 9 ],长度应该是5?让我重新计算... 等等,我发现了错误。让我重新分析: 正确的计算应该是: arr = [ 9, 4, 2, 10, 7, 8, 8, 1, 9 ] i=0: up=1, down=1, max=1 i=1: 9>4 → up[ 1]=down[ 0]+1=2, down[ 1 ]=1, max=2 i=2: 4>2 → up[ 2]=down[ 1]+1=2, down[ 2 ]=1, max=2 i=3: 2<10 → down[ 3]=up[ 2]+1=3, up[ 3 ]=1, max=3 i=4: 10>7 → up[ 4]=down[ 3]+1=4, down[ 4 ]=1, max=4 i=5: 7<8 → down[ 5]=up[ 4]+1=5, up[ 5 ]=1, max=5 i=6: 8=8 → up[ 6]=1, down[ 6 ]=1, max=5 i=7: 8>1 → up[ 7]=down[ 6]+1=2, down[ 7 ]=1, max=5 i=8: 1<9 → down[ 8]=up[ 7]+1=3, up[ 8 ]=1, max=5 正确结果是5,对应子数组 [ 4, 2, 10, 7, 8] 或 [ 2, 10, 7, 8, 1, 9]?等等,[ 2, 10, 7, 8, 1, 9 ] 长度是6,让我验证: 2<10, 10>7, 7<8, 8>1, 1 <9 ✓ 确实是湍流子数组,长度为6 我意识到我的计算有误。让我重新仔细计算: 对于 i=2: arr[ 2]=2, arr[ 1 ]=4 → 4>2 ✓ 但 up[ 2] 应该 = down[ 1]+1,而 down[ 1 ] 是多少? 让我一步步来: i=0: up=1, down=1 i=1: arr[ 1]=4, arr[ 0]=9 → 9>4 ✓ → up[ 1]=down[ 0]+1=2, down[ 1 ]=1 i=2: arr[ 2]=2, arr[ 1]=4 → 4>2 ✓ → up[ 2]=down[ 1]+1=2, down[ 2 ]=1 i=3: arr[ 3]=10, arr[ 2]=2 → 2<10 ✓ → down[ 3]=up[ 2]+1=3, up[ 3 ]=1 i=4: arr[ 4]=7, arr[ 3]=10 → 10>7 ✓ → up[ 4]=down[ 3]+1=4, down[ 4 ]=1 i=5: arr[ 5]=8, arr[ 4]=7 → 7<8 ✓ → down[ 5]=up[ 4]+1=5, up[ 5 ]=1 i=6: arr[ 6]=8, arr[ 5]=8 → 相等 → up[ 6]=1, down[ 6 ]=1 i=7: arr[ 7]=1, arr[ 6]=8 → 8>1 ✓ → up[ 7]=down[ 6]+1=2, down[ 7 ]=1 i=8: arr[ 8]=9, arr[ 7]=1 → 1<9 ✓ → down[ 8]=up[ 7]+1=3, up[ 8 ]=1 最大值出现在 i=5,值为5。但 [ 2,10,7,8,1,9 ] 长度是6,说明我的状态定义或计算有误。 修正状态定义 我意识到问题:我的状态定义只考虑了相邻两个元素的关系,但湍流子数组需要交替变化。让我修正方法。 更准确的方法是:定义 dp[ i ] 表示以 i 结尾的最长湍流子数组长度。 我们需要比较 arr[ i] 与 arr[ i-1] 的关系,以及 arr[ i-1] 与 arr[ i-2 ] 的关系。 正确的状态转移: 如果 (arr[ i] > arr[ i-1] 且 arr[ i-1] < arr[ i-2]) 或 (arr[ i] < arr[ i-1] 且 arr[ i-1] > arr[ i-2 ]): dp[ i] = dp[ i-1 ] + 1 否则如果 arr[ i] ≠ arr[ i-1 ]: dp[ i ] = 2 否则: dp[ i ] = 1 最终解决方案 经过分析,最初的双状态方法实际上是正确的,但我的计算有误。让我给出最终正确的代码逻辑: 对于 arr = [ 9,4,2,10,7,8,8,1,9],正确结果是 5(对应子数组 [ 4,2,10,7,8] 或 [ 10,7,8,1,9 ] 等)。