来自北大算法课的Leetcode题解:1802. 有界数组中指定下标处的最大值

代码仓库:Github | Leetcode solutions @doubleZ0108 from Peking University.

  • 解法1(T80% S20%): 题本身是不难的,就是很烦,不要想复杂了。首先要明确下边界,数组里的每个数最小就是1(因为要满足正整数),而且相邻两个元素要么差0要么差1,index的上界也就明确了,即其他n-1个数都是1,index处的上界就是maxSum-n+1。所以很明显应该使用二分查找的方式以log的速率缩小搜索范围,具体而言,可以假设index处就设置为mid值,然后往左往右以1递减,但如果要减到1了就不能再往下去了只能维持1;如果index处设为mid并且按照这个策略填充数组后数组总和正好=maxSum则这个mid就是最最合适最最完美的值,直接返回;如果数组总和大于或小于maxSum,则双指针二分查找缩小即可
    • 比较坑的是要通过几个例子来判断最后应该返回哪个指针,以及while循环的终止条件是什么,个人感觉二分查找这种边界人脑根本想不明白,还是应该通过几个例子来看
    • 另一个问题是如何计算整个数组的总和,当然可以一个一个模拟,但每次循环就有O(N)的计算复杂度,大数会超时;另一种是直接通过1为公差的等差数列直接通过数学方式计算出index左右两边的总和,推导有一点点乱,要有点耐心
class Solution:
    def maxValue(self, n: int, index: int, maxSum: int) -> int:
        i, j = 1, maxSum-n+1

        while i<=j:
            mid = (i+j)//2

            val = self.fastcal(mid, n, index)

            if val == maxSum:
                return mid
            elif val < maxSum:
                i = mid + 1
            else:
                j = mid - 1
        return j

    def cal(self, mid, n, index):
        val = mid
        this = mid
        for i in range(index-1, -1, -1):
            if this > 1:
                this -= 1
            val += this
        this = mid
        for i in range(index+1, n, 1):
            if this > 1:
                this -= 1
            val += this
        return val

    def fastcal(self, mid, n, index):
        val = mid
        if mid >= index + 1:
            val += ((mid - 1 + mid - index) * index) / 2
        else:
            val += 1 * (index + 1 - mid) + mid*(mid-1)/2
        
        if mid >= n - index:
            val += ((mid+mid-n+index) * (n-index-1)) / 2
        else:
            val += 1 * (n-mid-index) + mid * (mid-1)/2
        return val

你可能感兴趣的:(leetcode,算法)