📌  相关文章
📜  Python程序查找 Sum(i*arr[i]) 的最大值,仅允许在给定数组上进行旋转(1)

📅  最后修改于: 2023-12-03 15:04:41.122000             🧑  作者: Mango

Python程序查找 Sum(i*arr[i]) 的最大值,仅允许在给定数组上进行旋转

简介

题目描述:给定一个数组,只能通过旋转数组(即将数组的某些元素移动到末尾)来寻找新的 nums[]。求数组 nums[] 的 Sum(i*arr[i]) 的最大值。其中,i表示数组下标。

比如,对于数组nums=[1,2,3,4],共有4种旋转方式:

1 2 3 4           4 1 2 3           3 4 1 2           2 3 4 1
▲ ▲ ▲ ▲           ▲                 ▲                 ▲

对于每一个旋转后得到的数组,可以求得其 Sum(i*arr[i]) 的值:

i   |   0   1   2   3
-------------------- 
原始 |   0 + 2 + 6 + 12 = 20
第一 |   0 + 2 + 6 + 12 = 20
第二 |   0 + 4 + 6 + 8  = 18
第三 |   0 + 6 + 4 + 2  = 12
第四 |   0 + 8 + 2 + 6  = 16

因此,最大的 Sum(i*arr[i]) 值为20。

思路

对于 Sum(i*arr[i]),如果我们把 i 固定在某一个位置上,那么对于其他位置 j,它们的贡献就分别是 arr[j] 和 j。所以先求出所有的 arr[j] 的和,设为 sum。然后,从数组的第二位开始,依次把 arr[j] - arr[0] 赋值给 i。此时,i 为固定值,整个数组的贡献也就可以求出来了。

对于如何旋转数组,则可以采用三次翻转,具体步骤如下:

  1. 先将整个数组翻转
  2. 再将前 k 个元素翻转
  3. 最后将后 n-k 个元素翻转

其中 k 为旋转的位置。

代码
def find_max_sum(arr: List[int]) -> int:
    sum_arr = sum(arr)
    n = len(arr)
    max_sum = float('-inf')
    cur_sum = 0
    for i in range(1, n):
        cur_sum += (i * arr[i]) - sum_arr + arr[0]
        max_sum = max(max_sum, cur_sum)
    return max_sum

def rotate_array(arr: List[int], k: int) -> None:
    n = len(arr)
    k = k % n
    arr.reverse()
    reverse_array(arr, 0, k-1)
    reverse_array(arr, k, n-1)

def reverse_array(arr: List[int], begin: int, end: int) -> None:
    while begin < end:
        arr[begin], arr[end] = arr[end], arr[begin]
        begin += 1
        end -= 1
测试
nums = [1,2,3,4]
k = 1

rotate_array(nums, k)
print(find_max_sum(nums))  # 输出20