您的位置:首页 > 健康 > 美食 > 2972.力扣每日一题7/11 Java(击败100%)

2972.力扣每日一题7/11 Java(击败100%)

2024/12/23 12:54:42 来源:https://blog.csdn.net/Rangsh/article/details/140363442  浏览:    关键词:2972.力扣每日一题7/11 Java(击败100%)
  • 博客主页:音符犹如代码
  • 系列专栏:算法练习
  • 关注博主,后期持续更新系列文章
  • 如果有错误感谢请大家批评指出,及时修改
  • 感谢大家点赞👍收藏⭐评论✍

 

 

目录

解题思路

解题方法

时间复杂度

空间复杂度

Code 


解题思路

该问题的目标是计算给定数组中,可以移除的递增子数组的数量。一个子数组如果可以移除,意味着它在原数组中是递增的。为了解决这个问题,我采用了以下策略:

  1. 寻找最长递增前缀:首先,我寻找数组中从第一个元素开始的最长递增子序列(前缀)。这是因为任何包含这个前缀的子数组都是递增的,因此可以移除。

  2. 处理特殊情况:如果整个数组(除了最后一个元素外)都是递增的,那么任何非空子数组都可以移除。在这种情况下,直接返回所有可能的子数组数量,即 n*(n+1)/2

  3. 枚举递增后缀:如果数组不是整体递增的,那么我从数组的末尾开始,尝试找到可以与前面找到的最长递增前缀相结合的递增后缀。对于每个这样的后缀,我计算可以与它结合的最长递增前缀的长度。

  4. 累加可移除子数组数量:对于每个找到的递增后缀,我将其与兼容的前缀组合,形成可以移除的递增子数组,并累加这些组合的数量。

解题方法

  1. 使用findLongestIncreasingPrefix方法找到最长递增前缀

  2. 检查是否整个数组(除最后一个元素外)都是递增的。如果是,直接返回所有可能的子数组数量

  3. 如果不是整体递增,使用循环从数组末尾开始查找递增后缀

  4. 对于每个递增后缀,使用findCompatiblePrefixLength方法找到可以与它结合的最长递增前缀

  5. 累加可以与当前后缀组成递增子数组的前缀数量

  6. 返回累加的数量作为结果

时间复杂度

  • findLongestIncreasingPrefix方法遍历数组一次,时间复杂度为O(n)
  • 主循环从数组末尾开始,最多遍历数组一次,对于每个位置,findCompatiblePrefixLength可能再次遍历数组,因此总的时间复杂度为O(n^2)

空间复杂度

该算法只使用了几个变量来存储中间结果,没有使用额外的数据结构来存储大量数据,因此空间复杂度为O(1)

Code

class Solution {  public long incremovableSubarrayCount(int[] a) {  int n = a.length;  // 找到最长递增前缀的长度  int prefixLength = findLongestIncreasingPrefix(a);  // 如果整个数组都是递增的,则任何非空子数组都可以移除  if (prefixLength == n - 1) {  // 返回所有可能的非空子数组的数量(使用等差数列求和公式)  return (long)n * (n + 1) / 2;  }  long count = prefixLength + 2; // 初始化计数为整个前缀和整个数组本身  // 枚举所有可能的递增后缀  for (int suffixStart = n - 1;   suffixStart >= 0 && a[suffixStart] < (suffixStart + 1 < n ? a[suffixStart + 1] : Integer.MAX_VALUE);   suffixStart--) {  // 找到能与当前后缀组成递增序列的最长前缀的长度  int compatiblePrefixLength = findCompatiblePrefixLength(a, prefixLength, suffixStart);  count += compatiblePrefixLength + 1; // 累加可以组成的递增子数组数量  }  return count;  }  // 辅助方法:找到最长递增前缀的长度  private int findLongestIncreasingPrefix(int[] a) {  int n = a.length;  int i = 0;  while (i < n - 1 && a[i] < a[i + 1]) {  i++;  }  return i;  }  // 辅助方法:找到与给定后缀兼容的最长前缀的长度  private int findCompatiblePrefixLength(int[] a, int initialPrefixLength, int suffixStart) {  int prefixLength = initialPrefixLength;  // 从之前找到的最长递增前缀开始向前查找,直到找到可以与后缀组成递增序列的前缀  while (prefixLength >= 0 && a[prefixLength] >= a[suffixStart]) {  prefixLength--;  }  return prefixLength + 1; // 返回兼容前缀的长度(包括prefixLength指向的元素)  }  
}

 

  A miss is as good as a mile

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com