【简单】最大整合子数组问题(概念转换)

317 阅读2分钟

题目

可整合数组:如果一个数组在排序之后,相邻的两个数的差值的觉得值为 1 ,则认为该数组为可整合数组。

如 [1,5,4,2,3] 排序后为 [1,2,3,4,5] 则该数组即符合为可整合数组

给定一个整形数组 arr ,返回其中最大可整合子数组长度。

如 [9,20,1,5,4,2,3] 最大可整合子数组为 [1,5,4,2,3] 则返回 5

暴力求解思路

遍历所有子数组,计算排序每个子数组是否符合可整合数组。

这个复杂度会很高,遍历所有子数组 O(n^2) ,排序子数组 O(n * log n)

时间复杂度为 O(n^3 * log n) 且无法原地排序

优化思路

在考虑这种问题的时候我们要有意锻炼自己思维的敏感度,【可整合数组】这个概念能否进行一些转换,变得使我们程序更好求解呢?

转换之后可以得到这样一组条件:

  1. 无重复数字

  2. 数组长度为 数组最大值 - 数组最小值 + 1

经过概念的优化,时间复杂的可以优化到 O(n^2) 最优解,来看代码

题解


package algorithmic.total.solution.common;

import java.util.HashSet;

import java.util.Set;

/**

* @program: algorithmic-total-solution

* @description: 可整合数组:如果一个数组在排序之后,相邻的两个数的差值的觉得值为 1 ,则认为该数组为可整合数组。

* 如 [1,5,4,2,3] 排序后为 [1,2,3,4,5] 则该数组即符合为可整合数组

* <p>

* 给定一个整形数组 arr ,返回其中最大可整合子数组长度。

* 如 [9,20,1,5,4,2,3] 最大可整合子数组为 [1,5,4,2,3] 则返回 5

* @author: wangzibin

**/

public class Question2 {

public static void main(String[] args) {

int[] arr = new int[]{9, 20, 1, 5, 4, 2, 3};

System.out.println(getMaxSubIntegrationArray(arr));

}

private static int getMaxSubIntegrationArray(int[] arr) {

if (arr == null || arr.length < 1) {

return 0;

}

int num = 1;

// 计算子数组是否有重复元素

Set<Integer> numSet = new HashSet<Integer>();

for (int i = 0; i < arr.length; i++) {

// 每次更换开头清空

int max = arr[i];

int min = arr[i];

numSet.clear();

for (int j = i; j < arr.length; j++) {

int currValue = arr[j];

if (numSet.contains(currValue)) {

break;

}

max = Math.max(currValue, max);

min = Math.min(currValue, min);

int distance = max - min;

int length = j - i + 1;

if ((j - i) == distance && num < length) {

num = length;

}

numSet.add(currValue);

}

}

return num;

}

}