给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。

如果不存在满足条件的子数组,则返回 0 。

示例 1:

输入:nums = [8,2,4,7], limit = 4
输出:2 
解释:所有子数组如下:
[8] 最大绝对差 |8-8| = 0 <= 4.
[8,2] 最大绝对差 |8-2| = 6 > 4. 
[8,2,4] 最大绝对差 |8-2| = 6 > 4.
[8,2,4,7] 最大绝对差 |8-2| = 6 > 4.
[2] 最大绝对差 |2-2| = 0 <= 4.
[2,4] 最大绝对差 |2-4| = 2 <= 4.
[2,4,7] 最大绝对差 |2-7| = 5 > 4.
[4] 最大绝对差 |4-4| = 0 <= 4.
[4,7] 最大绝对差 |4-7| = 3 <= 4.
[7] 最大绝对差 |7-7| = 0 <= 4. 
因此,满足题意的最长子数组的长度为 2

 

比赛时这破题真就卡了一个小时= = 然后第四题没来记得看= = 我好菜啊

 

解法1、树状数组/线段树 求区间极值 + 二分

树状数组求区间最大最小值 logn 二分长度然后枚举起点 时间复杂度 O(logn * logn * n)

 

线段树 太久没写了 练下手。不过这题比较简单,没有更新,没有什么pushup pushdown的操作

#define lson (o<<1)
#define rson (o<<1|1)
#define mid ((l+r)>>1)

const int N = 100005;
int max_tr[N * 3], min_tr[N * 3];

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        int n = nums.size();
        build(1, 1, n, nums);        
        int l = 1, r = n;
        int ans = 0;
        // 二分长度
        while (l <= r) {
            int m = (l + r) >> 1;
            bool f = false;
            for (int i = 0, j; (j = i + m - 1) < n; i++) {
                int maxv = query_max(1, 1, n, i + 1, j + 1);
                int minv = query_min(1, 1, n, i + 1, j + 1);
                if (maxv - minv <= limit) {
                    f = true;
                    break;
                }
            }
            if (f) ans = m, l = m + 1;
            else r = m - 1;
        }
        return ans;
    }
    void build(int o, int l, int r, vector<int>& nums) {
        if (l == r) {
            max_tr[o] = min_tr[o] = nums[l - 1];
            return ;
        }
        build(lson, l, mid, nums);
        build(rson, mid + 1, r, nums);
        pushup(o);
    }
    void pushup(int o) {
        max_tr[o] = max(max_tr[lson], max_tr[rson]);
        min_tr[o] = min(min_tr[lson], min_tr[rson]);
    }
    int query_min(int o, int l, int r, int L, int R) {
        if (l >= L && r <= R) return min_tr[o];
        int res = INT_MAX;
        if (L <= mid) res = min(res, query_min(lson, l, mid, L, R));
        if (R > mid) res = min(res, query_min(rson, mid + 1, r, L, R));
        return res;
    }
    int query_max(int o, int l, int r, int L, int R) {
        if (l >= L && r <= R) return max_tr[o];
        int res = 0;
        if (L <= mid) res = max(res, query_max(lson, l, mid, L, R));
        if (R > mid) res = max(res, query_max(rson, mid + 1, r, L, R));
        return res;
    }
};
View Code

相关文章:

  • 2021-07-25
  • 2022-12-23
  • 2022-01-20
  • 2022-12-23
  • 2022-12-23
  • 2021-08-03
  • 2021-09-07
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-12-29
  • 2021-07-27
  • 2022-01-19
  • 2022-12-23
  • 2021-12-26
  • 2021-05-23
相关资源
相似解决方案