【LeetCode 1014】最佳观光对 Best Sightseeing Pair

LeetCode 1014题,属于数组类型的题目,题意:
在这里插入图片描述
翻译成中文,就是要找数组中的两个点,满足:

  • A[i] + A[j] + i - j的值最大
  • i < j

在这里插入图片描述
在这里插入图片描述
思路:
最快速的想法,就是直接暴力求解:
因为实际上就是求符合题意的两个点能获得的最大值,直接两个循环:

    public int maxScoreSightseeingPair(int[] A) {
        if (A == null || A.length == 0) return 0;
        int max = 0;
        for (int i = 0; i < A.length; i++) {
            for (int j = i + 1; j < A.length; j++) {
                if (A[i] + A[j] + i - j > max) {
                    max = A[i] + A[j] + i - j;
                }
            }
        }
        return max;
    }

但直接暴力解复杂度 O(n²),LeetCode直接超时了,所以我们要变换思路:
我们观察:A[i] + A[j] + i - j,可以拆分为:A[i] + iA[j] - j,所以,题目相当于,找出一个点 i,且在改点之后,有一个点 j,使得A[i] + iA[j] - j的和获得最大值。
我们可以想到,先遍历一遍数组,记录在当前 i可以获得的A[i] + i的最大值temp[],再第二次遍历数组,看在哪个点,可以获得temp[i[ + A[i] - i的最大值,代码:

    public int maxScoreSightseeingPair(int[] A) {
        if (A == null || A.length == 0) return 0;
        // 用于记录每个点之前,能获取的 A[i] + i的最大值
        int[] temp = new int[A.length];
        int max = Integer.MIN_VALUE;
        // 第一次遍历,用于更新 temp[]
        for (int i = 0; i < A.length - 1; i++) {
            if (A[i] + i > temp[i]) {
                // 若当前 i点的组合大于原始组合,则更新
                temp[i + 1] = A[i] + i;
            } else {
            	// 当前 i点组合未能获得更大的组合值
                temp[i + 1] = temp[i];
            }
        }
        // 第二次遍历
        for (int i = 0; i < A.length; i++) {
            if (temp[i] + A[i] - i > max) {
                max = temp[i] + A[i] - i;
            }
        }
        return max;
    }

该解法的时间复杂度为 O(n),空间复杂度为 O(n)。但该解法遍历了两次数组,而且还有空间开销,那我们可不可以只遍历一次且常数级别的空间开销呢?
其实我们发现:上面的 temp[]用于记录在这个点之前能获取的 A[i] + i组合的最大值,其实我们可以用一个变量进行记录即可,因此,修改代码,有:

    public int maxScoreSightseeingPair(int[] A) {
        if (A == null || A.length == 0) return 0;
        int i = 0, max = Integer.MIN_VALUE;
        for (int j = 1; j < A.length; j++) {
            if (A[i] + A[j] + i - j > max) {
                max = A[i] + A[j] + i - j;
            }
            // 更新 A[i] + i组合能获得最大值的下标
            if (i + A[i] < j + A[j]) {
                i = j;
            }
        }
        return max;
    }

时间复杂度 O(n),空间复杂度 O(1)
提交结果:
在这里插入图片描述

其他 LeetCode 题目解析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值