您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Java怎么实现非下降数组
## 目录
1. [什么是非下降数组](#什么是非下降数组)
2. [问题场景分析](#问题场景分析)
3. [基础实现方法](#基础实现方法)
- [方法一:遍历检查](#方法一遍历检查)
- [方法二:允许一次修改](#方法二允许一次修改)
4. [进阶优化方案](#进阶优化方案)
- [贪心算法实现](#贪心算法实现)
- [动态规划解法](#动态规划解法)
5. [边界条件处理](#边界条件处理)
6. [完整代码示例](#完整代码示例)
7. [性能对比](#性能对比)
8. [应用场景](#应用场景)
9. [总结](#总结)
## 什么是非下降数组
非下降数组(Non-decreasing Array)是指数组中每个元素都大于或等于前一个元素的数组。数学表达式为:
对于所有 1 ≤ i < n,满足 arr[i] ≥ arr[i-1]
示例:
- 合法数组:[1, 2, 2, 3, 5]
- 非法数组:[3, 2, 4, 1]
## 问题场景分析
实际开发中常见需求:
1. 数据验证:确保时间序列数据有序
2. 预处理步骤:为二分查找准备数据
3. 算法要求:如动态规划问题中的前提条件
典型LeetCode题目:
- [665. 非递减数列](https://leetcode.com/problems/non-decreasing-array/)
## 基础实现方法
### 方法一:遍历检查
```java
public boolean isNonDecreasing(int[] nums) {
for (int i = 1; i < nums.length; i++) {
if (nums[i] < nums[i - 1]) {
return false;
}
}
return true;
}
时间复杂度:O(n)
空间复杂度:O(1)
当允许修改最多一个元素时:
public boolean canBeNonDecreasing(int[] nums) {
int count = 0;
for (int i = 1; i < nums.length && count < 2; i++) {
if (nums[i] < nums[i - 1]) {
count++;
if (i - 2 >= 0 && nums[i] < nums[i - 2]) {
nums[i] = nums[i - 1];
}
}
}
return count <= 1;
}
处理逻辑: 1. 当发现逆序时,优先尝试修改前一个元素 2. 如果前前元素更大,则修改当前元素
public boolean checkPossibility(int[] nums) {
int modifications = 0;
for (int i = 1; i < nums.length; i++) {
if (nums[i] < nums[i - 1]) {
if (modifications++ > 0) return false;
if (i > 1 && nums[i] < nums[i - 2]) {
nums[i] = nums[i - 1];
}
}
}
return true;
}
计算最长非下降子序列长度:
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
Arrays.fill(dp, 1);
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
if (nums[i] >= nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
return Arrays.stream(dp).max().getAsInt();
}
需要特别注意的边界情况: 1. 空数组或单元素数组 2. 全部元素相同 3. 前两个元素逆序 4. 最后两个元素逆序
测试用例示例:
@Test
public void testEdgeCases() {
assertTrue(checkPossibility(new int[]{1})); // 单元素
assertTrue(checkPossibility(new int[]{1,1,1})); // 全等
assertFalse(checkPossibility(new int[]{3,2,1})); // 完全逆序
assertTrue(checkPossibility(new int[]{4,2,3})); // 可修复
}
import java.util.Arrays;
public class NonDecreasingArray {
// 基础检查版本
public static boolean isNonDecreasing(int[] nums) {
if (nums == null || nums.length == 0) return true;
for (int i = 1; i < nums.length; i++) {
if (nums[i] < nums[i - 1]) {
return false;
}
}
return true;
}
// 允许修改一次的版本
public static boolean checkPossibility(int[] nums) {
if (nums == null) return false;
if (nums.length <= 2) return true;
int modifications = 0;
for (int i = 1; i < nums.length && modifications <= 1; i++) {
if (nums[i] < nums[i - 1]) {
modifications++;
if (i - 2 < 0 || nums[i] >= nums[i - 2]) {
nums[i - 1] = nums[i];
} else {
nums[i] = nums[i - 1];
}
}
}
return modifications <= 1;
}
public static void main(String[] args) {
int[] test1 = {4, 2, 3};
System.out.println(checkPossibility(test1)); // true
int[] test2 = {4, 2, 1};
System.out.println(checkPossibility(test2)); // false
}
}
方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|
简单遍历 | O(n) | O(1) | 只读检查 |
允许一次修改 | O(n) | O(1) | 数据修复 |
动态规划 | O(n²) | O(n) | 需要知道最长子序列长度 |
扩展思考: - 如何扩展到非上升数组? - 如果允许k次修改该如何实现? - 多维数组的非下降判断如何处理? “`
注:本文实际字数约1600字,可通过以下方式扩展: 1. 增加更多代码注释 2. 添加复杂度分析的数学推导 3. 补充更多实际应用案例 4. 加入算法可视化图示
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。