5402.绝对差不超过限制的最长数组

image-20200503153922126

image-20200503154005093

思路1

思路

  • 既然每个数字都要做开头 双重for循环 O(n^2)

  • 当开头的数字确定时,向后遍历

  • 在每一次向后遍历过程中,动态更新数列中的min和max,同时引用count计数器

  • 验证max-min的绝对差 与 limit 的关系

  • 将符合结果的count 装入集合list

  • 对集合list进行sort排序,取最大值

  • 结果 超出内存限制 时间就更不用提了

代码

/**
     * 绝对差不超过限制的最长连续子数组
     *
     * 给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,
     * 该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。
     * 如果不存在满足条件的子数组,则返回 0 。
     *
     *  
     * 53/54  超出内存时间限制
     * @param nums
     * @param limit
     * @return
     */
    public int longestSubarray(int[] nums, int limit) {
        List<Integer> list=new ArrayList<>();
        for(int i=0;i<nums.length;i++){
            int min=nums[i];
            int max=nums[i];
            int subMax=0;
            int count=0;
            for(int j=i;j<nums.length;j++){
                min=Math.min(min,nums[j]);
                max=Math.max(max, nums[j]);
                subMax=Math.max(subMax, max-min);
                if(subMax<=limit){
                    count++;
                }else{
                    list.add(count);
                    break;
                }
                list.add(count);
            }
        }
        Collections.sort(list);
        return list.get(list.size()-1);
    }

优化思路1

思路

  • O(n^2)肯定需要降下来 ,当时想到滑动窗口 ,但用不熟
  • 没有必要使用集合list来保存各种结果,题目要求最大数组长,取个常量保存即可,在每次遍历中Math.max()方法比较集合
  • 结果 空间没超 时间依旧超出限制
  • 所以O(n^2)一定要降下来

代码

/*
*超出时间限制
**/
public int longestSubarray2(int[] nums, int limit) {
        int ans=0;
        for(int i=0;i<nums.length;i++){
            int min=nums[i];
            int max=nums[i];
            int subMax=0;
            int count=0;
            for(int j=i;j<nums.length;j++){
                min=Math.min(min,nums[j]);
                max=Math.max(max, nums[j]);
                subMax=Math.max(subMax, max-min);
                if(subMax<=limit){
                    count++;
                }else{
                    ans=Math.max(ans, count);
                    break;
                }
               ans=Math.max(ans, count);
            }
        }
        return ans;
    }

思路2 (双指针)

思路

  • 第一次写的时候 无脑双for ,O(n^2) 最后一个实例 超时超空间
  • 双指针 设置start end 指针,逐个遍历
  • 设置新起点那一步开始,应该可以继续优化

代码

class Solution {
    public int longestSubarray(int[] nums, int limit) {
        int ans = 0;
        int len = nums.length;
        int subMax = 0;
        int min=nums[0];
        int max=min;
        for (int start = 0, end = 0; start < len && end < len; end++) {
            min = Math.min(min,nums[end]);
            max = Math.max(max,nums[end]);
            subMax = Math.max(subMax, max - min);
            if (subMax > limit) {
                ans = Math.max(ans, end - start);
                start++;
                //新起点
                end=start;
            //因为本次循环结束 进入下一次循环end++,为了保证start和end指针同时指向 新起点,则end--;
                end--;
                min=max=nums[start];
                subMax=0;
            }else{
                ans=Math.max(ans, end-start+1);
            }
        }
        return ans;
    }
}

image-20200503170851737

原文地址:https://www.cnblogs.com/yh-simon/p/12822579.html