คำอธิบายปัญหา
ได้รับอาร์เรย์ arr[] ขนาด n ต้องการหา ค่าสูงสุดของ Sum(i × arr[i]) โดยอนุญาตให้ หมุนอาร์เรย์ (Rotate) ได้ไม่จำกัดจำนวนครั้ง
ตัวอย่าง
Input: arr[] = {4, 1, 3, 7, 2}
Output: 43
คำอธิบาย: หมุนอาร์เรย์ 1 ครั้ง → {2, 4, 1, 3, 7}
Sum = 0×2 + 1×4 + 2×1 + 3×3 + 4×7 = 0 + 4 + 2 + 9 + 28 = 43
แนวทางแก้ปัญหา
วิธีที่ 1: Brute Force (หมุน n ครั้ง, คำนวณทุกครั้ง)
Time: O(n²) - ช้า
วิธีที่ 2: สูตรทางคณิตศาสตร์ (O(n))
ให้ sum(k) เป็นผลรวมหลังหมุน k ครั้ง
การนำสูตร:
sum(0) = 0*arr[0] + 1*arr[1] + ... + (n-1)*arr[n-1]
sum(1) = 0*arr[n-1] + 1*arr[0] + ... + (n-1)*arr[n-2]
sum(1) - sum(0) = arr[0] + arr[1] + ... + arr[n-2] - (n-1)*arr[n-1]
= (Sum of all elements) - n*arr[n-1]
โดยทั่วไป: sum(k) - sum(k-1) = arrSum - n * arr[n-k]
ดังนั้น สามารถคำนวณ sum(k) จาก sum(k-1) ได้ใน O(1)
อัลกอริทึม
- คำนวณ
arrSum= ผลรวมสมาชิกทั้งหมด - คำนวณ
currSum = sum(0) - ตั้ง
maxSum = currSum - ลูป
j = 1 ถึง n-1:currSum = currSum + arrSum - n * arr[n-j]- อัปเดต
maxSum
- คืนค่า
maxSum
โค้ดตัวอย่าง C++
#include <iostream>
using namespace std;
int findMaxSumRotation(int arr[], int n) {
int arrSum = 0;
int currSum = 0;
for (int i = 0; i < n; i++) {
arrSum += arr[i];
currSum += i * arr[i];
}
int maxSum = currSum;
for (int j = 1; j < n; j++) {
currSum = currSum + arrSum - n * arr[n - j];
if (currSum > maxSum)
maxSum = currSum;
}
return maxSum;
}
int main() {
int arr[] = {4, 1, 3, 7, 2};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "The maximum value of sum(i*arr[i]) using rotations is " << findMaxSumRotation(arr, n);
return 0;
}
ผลลัพธ์
The maximum value of sum(i*arr[i]) using rotations is 43