LeetCode题解——978. 最长湍流子数组

https://leetcode-cn.com/problems/longest-turbulent-subarray/

题目

当 A 的子数组 A[i], A[i+1], …, A[j] 满足下列条件时,我们称其为湍流子数组:

  • 若 i <= k < j,当 k 为奇数时, A[k] > A[k+1],且当 k 为偶数时,A[k] < A[k+1];
  • 或 若 i <= k < j,当 k 为偶数时,A[k] < A[k+1] ,且当 k 为奇数时, A[k] > A[k+1]。

也就是说,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是湍流子数组。

返回 A 的最大湍流子数组的长度。

示例 1:

输入:[9,4,2,10,7,8,8,1,9]
输出:5
解释:(A[1] > A[2] < A[3] > A[4] < A[5])
示例 2:

输入:[4,8,12,16]
输出:2
示例 3:

输入:[100]
输出:1

提示:

1 <= A.length <= 40000
0 <= A[i] <= 10^9

思路

我的想法属于变相暴力吧,题目的意思就是符号一大一小或者一小一大下去,找最长的。
在原数组的基础上,开辟一个N-1大小的数组,存储两两对应关系

  • -1:小于
  • 0:等于
  • 1:大于

然后在这个全是-1,0,1的数组里面,找到最长的一个串(1-11-1或者-11-11这样的串)。遍历一遍即可找到(其实不开数组也能找到)

代码

public class Solution_978 {
     
    public static void main(String[] args) {
     
//        System.out.println(maxTurbulenceSize(new int[]{9, 4, 2, 10, 7, 8, 8, 1, 9}));
        System.out.println(maxTurbulenceSize(new int[]{
     2, 0, 2, 4, 2, 5, 0, 1, 2, 3}));
    }

    public static int maxTurbulenceSize(int[] A) {
     
        if (A.length == 1) {
     	// 只有一个数字,那直接返回1
            return 1;
        }
        int[] help = new int[A.length - 1];
        for (int i = 0; i < A.length - 1; i++) {
     
            if (A[i] < A[i + 1]) {
     
                help[i] = -1;
            } else if (A[i] > A[i + 1]) {
     
                help[i] = 1;
            } else {
     
                help[i] = 0;    
            }
        }
        int i = 0, j;	// i是起始端点
        int max = 0;	// 最长长度
        for (j = 1; j < help.length; j++) {
     
            if (help[i] == 0) {
     
                i = j;	// 如果相等,则移动i指针到当前位置
                continue;
            }
            // help[j] 一定是1或者-1
            if (help[j] * help[j - 1] == 1 || help[j] * help[j - 1] == 0) {
     
                i = j;		// 如果相同或者是0,则把i更新到此位置
                continue;
            } else if (help[j] * help[j - 1] == -1) {
     
                max = Math.max(j - i + 1, max);	// 对比max
                continue;
            }
        }
        if (max == 0) {
     
            if (help[0] == 1 || help[0] == -1) return 2;	// 数字长度大于2,且单调,返回2
            return 1;		// 数字长度大于2,且全部相等,返回1
        }
        return max + 1;
    }
}

优化思路

其实只和上次的符号有关,这样就不用开数组了,定义一个变量保存上次的符号即可。

代码

    private static int maxTurbulenceSize(int[] A) {
     
        int pre_len = 1, ans = 1;
        char pre = '=';
        for (int i = 1; i < A.length; ++i) {
     
            if (A[i] == A[i - 1]) {
      // 相等
                pre_len = 1;        // 一旦相等就从1开始
                pre = '=';
            } else if (A[i] > A[i - 1] && pre == '<' || A[i] < A[i - 1] && pre == '>')  // 交错
                pre_len += 1;
            else {
       // 单调或上次是等号
                pre_len = 2;        // 一旦单调就从2开始
            }
            pre = A[i] > A[i - 1] ? '>' : '<';  // 更新上次符号
            ans = Math.max(ans, pre_len);       // 记录大小
        }
        return ans;
    }

其中,值得注意的是:

  • 一旦相等,长度从1开始计算
  • 一旦单调上次符号是等号且这次单调,长度从2开始计算

你可能感兴趣的:(LeetCode)