Khởi tạo tổng biên từ phần tử thật
```python
def maxSubarray(A, left, right):
if left > right:
return None, None, float('-inf')
if left == right:
return left, right, A[left]
mid = (left + right) // 2
sumL, maxL, total = A[mid], mid, 0
for i in range(mid, left - 1, -1):
total += A[i]
if total > sumL:
sumL, maxL = total, i
sumR, maxR, total = A[mid + 1], mid + 1, 0
for j in range(mid + 1, right + 1):
total += A[j]
if total > sumR:
sumR, maxR = total, j
sumX = sumL + sumR
leftL, rightL, bestL = maxSubarray(A, left, mid)
leftR, rightR, bestR = maxSubarray(A, mid + 1, right)
if bestL >= bestR and bestL >= sumX:
return leftL, rightL, bestL
if bestR >= bestL and bestR >= sumX:
return leftR, rightR, bestR
return maxL, maxR, sumX
```
sumL ban đầu bằng A[mid], sumR bằng A[mid+1], nên đoạn chéo không lấy phía rỗng để tránh số âm. Các biến total=0 chỉ làm tổng đang cộng, không phải đáp án mặc định.
Hàm so kết quả tốt nhất bên trái, bên phải và qua giữa rồi trả (chỉ số đầu,chỉ số cuối,tổng). Cơ sở một phần tử trả chính giá trị ấy. Miền rỗng trả (None,None,−∞) như tín hiệu không có đoạn; không dùng các chỉ số None để cắt dãy.
Đọc cả đoạn và kiểm tổng
Chạy:
```text
python3 g11-cs-thuc-hanh-chia-de-tri.py tong "-4 5 -2 4 -6"
python3 g11-cs-thuc-hanh-chia-de-tri.py tong "-7 -2 -5"
```
Lệnh đầu cần trả chỉ số(1,3), tổng 7, dãy con[5,−2,4]. Lệnh sau trả chỉ số(1,1), tổng −2, dãy con[−2]. Dùng A[left:right+1] để lấy đủ biên cuối và kiểm tổng các phần tử ấy.
Thử thêm dãy rỗng, một phần tử, toàn số 0 và dãy tăng/giảm. Nếu có nhiều đoạn tối ưu, chỉ cần một đoạn liên tục hợp lệ có tổng lớn nhất; không buộc kết quả khớp một vị trí duy nhất khi đề chưa ràng buộc.
Mỗi mức giải cả hai nửa và quét qua đoạn để tính tổng chéo, nên T(n)=2T(n/2)+O(n) và bậc O(n log n). Chỉ số là vị trí, còn tổng là giá trị; cần kiểm cả hai để tránh kết quả tổng đúng nhưng đoạn bị lấy sai.
Bài luyện
Hàm trả (1,3,7) trên dãy mẫu. Lát cắt lấy đúng dãy con là gì?
Thừa phần tử ở chỉ số 0 và thiếu chỉ số 3.
Các biên bị đảo nên không lấy đoạn yêu cầu.
Lát cắt không lấy chỉ số kết thúc, nên dùng right+1=4.
Thiếu phần tử ở chỉ số 3.
Lời giải
Hai chỉ số đầu/cuối của hàm đều thuộc đoạn. Trong Python, A[left:right+1] lấy đủ1,2,3; với right=3, lát cắt đúng là A[1:4].
Bài luyện
Vì sao sumL cần khởi tạo từ A[mid] thay vì coi 0 là đáp án sẵn có?
Số âm vẫn có thể nằm trong đoạn tối ưu.
Điều đó trái với cách tạo đoạn chéo của bài.
Dữ liệu toàn âm có đáp án âm.
Đáp án chéo cần hậu tố trái không rỗng.
Lời giải
Nếu cho tổng 0 của đoạn rỗng cạnh tranh với mọi tổng âm thì có thể chọn sai. Khởi tạo từ phần tử thật bảo đảm đoạn chéo lấy dữ liệu của cả hai phía.
Bài luyện
Khi đầu vào rỗng và hàm trả (None,None,−∞), cách xử lí nào đúng?
Đây là tín hiệu cơ sở dành cho miền rỗng.
Hàm chưa tìm được đoạn có tổng 0.
None không phải chỉ số phần tử của danh sách.
Không được đổi đầu vào để tạo đáp án.
Lời giải
Không có phần tử nên không có đoạn không rỗng. Cần kiểm tín hiệu None và thông báo phù hợp;−∞chỉ giúp loại miền rỗng khi so sánh, không phải một tổng của dữ liệu.
Đang học