Cover image for leetcode每日一题 P3350 检测相邻递增子数组 II

leetcode每日一题 P3350 检测相邻递增子数组 II

字数 681
阅读
访客

时间轴

时间轴

2025-10-15

init

数组,从O(n3)优化到O(n2)再优化到O(n)

题目:

$$ O(n^3)$$ 穷举

直接穷举,没啥好说的,超时

12345678910111213141516171819202122232425262728293031323334353637383940414243
#include <vector>using std::vector;class Solution {public:  int maxIncreasingSubarrays(vector<int> &nums) {    int n = nums.size();    // n从2开始    int k = n / 2;    int a, b, i;    int flag = true;    while (k > 0) {      a = 0;     // 0..k-1      b = a + k; // a+k.. b+k-1      while (b + k - 1 < n) {        flag = true;        for (i = 1; i < k; i++) {          if (nums[a + i] > nums[a + i - 1] && nums[b + i] > nums[b + i - 1]) {            continue;          } else {            a++;            b = a + k;            flag = false;            break;          }        }        if (flag) {          return k;        }      }      k--;    }    return 0;  }};#include <stdio.h>int main() {  vector<int> vec = {19, -14, 0, 9};  Solution s;  printf("%d\n", s.maxIncreasingSubarrays(vec));}

$$O(n^2)$$ 预处理优化

我们定义一个数组 inc, inc[i]表示以 nums[i] 结尾的最长递增子数组的长度。a,b 开始的两个数据段相邻且递增必定满足 inc[a + k - 1] >= k && inc[b + k - 1] >= k。这个也超时了呜呜。

1234567891011121314151617181920212223242526272829303132333435363738
#include <vector>using std::vector;class Solution {public:  int maxIncreasingSubarrays(vector<int> &nums) {    int n = nums.size();    int i;    // n从2开始    int k = n / 2;    int a, b;    vector<int> inc(n, 1);    for (i = 1; i < n; i++) {      if (nums[i] > nums[i - 1]) {        inc[i] = inc[i - 1] + 1;      }    }    while (k > 0) {      a = 0;      b = a + k;      while (b + k - 1 < n) {        if (inc[a + k - 1] >= k && inc[b + k - 1] >= k) {          return k;        } else {          a++;          b = a + k;        }      }      k--;      if (k == 1) {        return 1;      }    }    return 1;  }};

$$O(n)$$

如果我们知道所有严格递增的两个相邻数据段,那么 k 为这两个段的最小值。我们遍历一遍数组,找到 k 的最大值即可。但要注意,我们还需要记录单个严格递增段的长度,因为它也可以拆成两个严格递增的两个相邻数据段。

12345678910111213141516171819202122232425262728293031323334353637383940
// #include <limits.h>#include <vector>using std::vector;class Solution {public:  // 遍历数组,计算所有连续递增段的长度。  int maxIncreasingSubarrays(vector<int> &nums) {    int n = nums.size();    int i;    int curr_len = 1;    // prev_len取0,否则第一次判断时会更新max,即使前面没有数据段    int prev_len = 0;    int max_val = 0;    int len_max = 0;    if (n <= 1) {      return 0;    }    for (i = 1; i < n; i++) {      if (nums[i] > nums[i - 1]) {        curr_len++;      } else {        max_val = std::max(max_val, std::min(curr_len, prev_len));        len_max = std::max(curr_len, len_max);        prev_len = curr_len;        curr_len = 1;      }    }    // 最后不要忘了更新len_max    len_max = std::max(len_max, curr_len);    max_val = std::max(max_val, std::min(curr_len, prev_len));    max_val = std::max(len_max / 2, max_val);    return max_val;  }};
评论加载中…