首页 > 试题广场 >

最大的leftMax与rightMax之差的绝对值

[编程题]最大的leftMax与rightMax之差的绝对值
  • 热度指数:838 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个长度为N(N>1)的整形数组arr, 可以划分成左右两个部分,左部分为arr[0…K],右部分为arr[K+1…N-1], K可以取值的范围是[0,N-2]。求这么多划分方案中,左部分中的最大值减去右部分最大值的绝对值中,最大是多少
[要求]
时间复杂度为O(n), 空间复杂度为O(n)

输入描述:
第一行一个整数N,表示数组长度。
接下来一行N个整数,表示数组内的数。


输出描述:
输出一个整数表示最优答案
示例1

输入

5
2 7 3 1 1

输出

6

说明

当左部分为[2, 7],右部分为[3, 1, 1]时,左部分中的最大值减去右部分的最大值的绝对值为4,。当左部分为[2, 7, 3],右部分为[1, 1]时,左部分中的最大值减去右部分最大值的绝对值为6。还有很多划分方案,但最终返回6.

备注:

首先这个题我们可以用预处理的技巧。构建一个前缀和数组leftMax,数组中的i位置表示从0到当前位置的最大值;再构建一个后缀数组rightMax,数组中的位置i表示从下一个位置到数组末尾的最大值,这样空间复杂度为O(N)。然后我们只需要求得这两个数组对应位置差的绝对值最大值就可以了,一共遍历三遍数组,时间复杂度为O(N)。
import scala.io.StdIn

object Main {
    def main(args: Array[String]): Unit = {
        val in = StdIn
        val n = in.readInt()
        val arr = in.readLine().split(" ").map(_.toInt)
        if(n == 2){
            println(math.abs(arr(0) - arr(1)))
        }else{
            val leftMax = Array.ofDim[Int](n)      // 前缀最大值
            val rightMax = Array.ofDim[Int](n)     // 后缀最大值
            leftMax(0) = arr(0)
            rightMax(n - 2) = arr(n - 1)
            for(i <- 1 until n - 1)
                leftMax(i) = math.max(arr(i), leftMax(i - 1))
            for(i <- n - 3 to 0 by -1)
                rightMax(i) = math.max(arr(i + 1), rightMax(i + 1))
            var max = 0
            for(i <- 0 until n - 1)
                max = math.max(max, math.abs(leftMax(i) - rightMax(i)))
            println(max)
        }
    }
}
但其实我们还可以把O(N)的空间省掉,并且在常数层面优化O(N)的时间复杂度。由题意可以知道,leftMaxrightMax中一定有个全局最大值max,分如下的两种情况:
  1. 全局最大值被分到了左边的数组,由于被划分的两部分数组都不能是空,因此右边的数组一定包括数组的最后一个值arr[n-1]。如果我们扩大右边的子数组,就会增加arr[n-1]之外的数,如果新增的数比它大,那么就会增加右边数组的最大值,从而减小右边数组最大值和左边数组最大值的绝对差;如果新增的数比它小,由于不会改变右边的最大值,所以并不会改变这个绝对差。因此,绝对差最大的情况与右边的数组只有arr[n-1]一个数的情况是等效的。
  2. 同理可得,当全局最大值被分配到右边数组的时候,绝对差取得最大值的情况与左边的数组只有arr[0]一个数的情况是等效的。
综上,leftMaxrightMax绝对差的最大值就是上面两种情况中大的那个。这种方法不仅省去了O(N)的空间,而且只需要遍历一遍数组求全局最大值。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] strArr = br.readLine().split(" ");
        int[] arr = new int[n];
        int max = Integer.MIN_VALUE;
        for(int i = 0; i < n; i++) {
            arr[i] = Integer.parseInt(strArr[i]);
            max = Math.max(max, arr[i]);
        }
        System.out.println(Math.max(max - arr[0], max - arr[n - 1]));
    }
}

编辑于 2021-11-24 23:15:14 回复(0)

问题信息

上传者:小小
难度:
1条回答 4614浏览

热门推荐

通过挑战的用户

查看代码
最大的leftMax与rightMax之差的绝对值