N trẻ đứng hàng, mỗi trẻ có rating. Phân kẹo thoả mãn:
- Mỗi trẻ ≥ 1 viên.
- Trẻ rating cao hơn hàng xóm → kẹo nhiều hơn hàng xóm đó.
Tìm tổng kẹo tối thiểu.
Ví dụ
ratings = [1,1,3] → Phân: [1, 1, 2] → Tổng = 4.
Thuật toán: 2 lần duyệt (Two-pass Greedy)
- Khởi tạo
dp[i] = 1cho tất cả. - Duyệt trái→phải: nếu
ratings[i-1]→dp[i] = dp[i-1] + 1. - Duyệt phải→trái: nếu
ratings[i+1]→dp[i] = max(dp[i], dp[i+1] + 1). - Tổng = sum(dp).
Tại sao 2 lần duyệt?
- Lần 1 đảm bảo điều kiện với hàng xóm trái.
- Lần 2 đảm bảo điều kiện với hàng xóm phải, đồng thời giữ điều kiện trái (dùng max).
Cài đặt C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int candy(vector<int>& ratings) {
int n = ratings.size();
vector<int> dp(n, 1);
for (int i = 1; i < n; i++)
if (ratings[i] > ratings[i-1]) dp[i] = dp[i-1] + 1;
for (int i = n-2; i >= 0; i--)
if (ratings[i] > ratings[i+1]) dp[i] = max(dp[i], dp[i+1] + 1);
int ret = 0;
for (int x : dp) ret += x;
return ret;
}
};
int main() {
Solution ob;
vector<int> v = {1, 1, 3};
cout << ob.candy(v);
return 0;
}
Độ phức tạp
- Thời gian:
O(n). - Không gian:
O(n)(có thể tối ưu O(1) nhưng phức tạp hơn).
Input / Output
Input: [1,1,3] Output: 4