給定一個包含正負整數的陣列,找出「連續子陣列」的最大和,並輸出該子陣列本身。經典例題:[1, -3, -5, -7, 8, 9, -11, 5] → 最大和 17,對應子陣列 [8, 9]。
維護兩個變數:
$currentSum:以當前元素結尾的最大子陣列和$maxSum:全域最大和遍歷時若 $currentSum 歸負,拋棄前綴,從下一元素重新累加。同步記錄起始/結束索引,最後用 array_slice 還原子陣列。
<?php
/**
* 最大子陣列和(含子陣列還原)
*
* @param array $nums 整數陣列
* @return array ['sum' => int, 'subarray' => array, 'start' => int, 'end' => int]
*/
function maxSubArray(array $nums): array {
if (empty($nums)) return ['sum' => 0, 'subarray' => [], 'start' => -1, 'end' => -1];
$maxSum = $nums[0];
$curSum = $nums[0];
$start = $end = $tempStart = 0;
for ($i = 1; $i < count($nums); $i++) {
// 決定:延續前綴,還是從當前元素重新開始
if ($curSum + $nums[$i] < $nums[$i]) {
$curSum = $nums[$i];
$tempStart = $i;
} else {
$curSum += $nums[$i];
}
// 更新全域最大值
if ($curSum > $maxSum) {
$maxSum = $curSum;
$start = $tempStart;
$end = $i;
}
}
return [
'sum' => $maxSum,
'subarray' => array_slice($nums, $start, $end - $start + 1),
'start' => $start,
'end' => $end,
];
}
// 測試
$data = [1, -3, -5, -7, 8, 9, -11, 5];
$result = maxSubArray($data);
echo "最大和: {$result['sum']}\n"; // 17
echo "子陣列: " . json_encode($result['subarray']) . "\n"; // [8,9]
echo "索引區間: {$result['start']} - {$result['end']}\n"; // 4 - 5
| 輸入 | 預期行為 |
|---|---|
| 空陣列 | 返回 sum=0, 空子陣列, index=-1 |
全負數 [-5, -2, -8] | 返回最大單一元素 -2,子陣列 [-2] |
單元素 [42] | 返回 42,子陣列 [42] |
含零 [-1, 0, -2] | 返回 0,子陣列 [0] |
function maxSubArraysAll(array $nums): array {
$maxSum = PHP_INT_MIN;
$curSum = 0;
$results = [];
$tempStart = 0;
foreach ($nums as $i => $v) {
if ($curSum <= 0) {
$curSum = $v;
$tempStart = $i;
} else {
$curSum += $v;
}
if ($curSum > $maxSum) {
$maxSum = $curSum;
$results = [[$tempStart, $i]];
} elseif ($curSum === $maxSum) {
$results[] = [$tempStart, $i];
}
}
return array_map(fn($range) => array_slice($nums, $range[0], $range[1] - $range[0] + 1), $results);
}
Kadane 演算法是解決最大子陣列和的標準答案。PHP 實作時善用 array_slice 還原子陣列,邊界條件處理得當,即可穩健應對面試、競賽與實際業務(如股票最大獲利區間、日誌異常峰值檢測)。