Problem
Bài toán yêu cầu phân phát kẹo cho các trẻ em xếp thành hàng dựa trên mảng ratings sao cho:
Approach
Giải pháp phổ biến là sử dụng hai lượt duyệt (greedy 2 chiều)
Cuối cùng, tổng số kẹo là tổng lớn nhất của hai lượt duyệt ở mỗi vị trí
Time and space complexity
Solution
1function candy(ratings: number[]): number {
2 const n = ratings.length;
3 const left = Array(n).fill(1);
4 const right = Array(n).fill(1);
5 for (let i = 1; i < n; i++) {
6 if (ratings[i] > ratings[i - 1]) {
7 left[i] = left[i - 1] + 1
8 }
9 }
10
11 for (let i = n - 2; i >= 0; i--) {
12 if (ratings[i] > ratings[i + 1]) {
13 right[i] = right[i + 1] + 1
14 }
15 }
16
17 let total = 0;
18 for (let i = 0; i < n; i++) {
19 total += Math.max(left[i], right[i])
20 }
21
22 return total
23};total += Math.max(left[i], right[i]);Điều kiện total += Math.max(left[i], right[i]); xuất hiện trong thuật toán là để đảm bảo rằng mỗi trẻ em đều thỏa mãn cả hai điều kiện so sánh với hàng xóm bên trái và bên phải
Cụ thể
left[i] đảm bảo rằng nếu rating của trẻ em hiện tại lớn hơn trẻ em bên trái thì số kẹo của nó cũng nhiều hơnright[i] đảm bảo rằng nếu rating của trẻ hiện tại lớn hơn trẻ bên phải thì số kẹo của nó cũng nhiều hơn.Tuy nhiên, có thể tại một vị trí nào đó, số kẹo cần thiết để thỏa mãn điều kiện trái khác với phải. Để đảm bảo cả hai điều kiện đúng, ta phải lấy số lớn nhất giữa hai giá trị này cho mỗi trẻ em tức là Math.max(left[i], right[i])
Nếu chỉ lấy giá trị nhỏ hơn, sẽ có trường hợp vi phạm một trong hai điều kiện so sánh với hàng xóm, việc lấy giá trị lớn nhất đảm bảo mọi quy tắc của đề bài đều được đáp ứng cho từng trẻ em, và tổng số kẹo là nhỏ nhất có thể mà không vi phạm luật phân phát kẹo nào