그리디 알고리즘: 할당 문제
스스로 문제를 푸는 과정을 기록했을 뿐이고, 답을 위해 다양한 솔루션을 참고했습니다.
틀린 부분이 있으면 수정해주시면 감사하겠습니다!
참조: LeetCode 101: LeetCode 그라인딩 가이드(C++ 버전) 저자: Gao Chang Chang Gao
질문 출처: 질문 은행 - LeetCode, 글로벌 괴짜들이 선호하는 기술 성장 플랫폼(leetcode-cn.com)
135. 사탕 나눠주기 (어려움)
어린이 그룹이 일렬로 서 있고 각 어린이는 자신의 등급이 있습니다. 이제 이 아이들에게 사탕을 주어야 합니다. 규칙은 한 아이의 점수가 옆에 있는 아이보다 높으면 이 아이가 옆에 있는 아이보다 더 많은 사탕을 받아야 한다는 것입니다. 모든 아이들이 적어도 하나는 가지고 있어야 합니다. 사탕. 필요한 사탕의 최소 수를 찾으십시오.
A. 사탕 나눠주는 욕심
-
이 질문의 각 순회 에서 인접 변의 크기 관계만 고려하고 업데이트한 다음 다른 변을 결정해야 합니다. 예를 들어 각 아이의 오른쪽을 비교한 다음 왼쪽을 비교하는 식으로 두 가지를 함께 고려하면 다른 쪽을 놓치게 됩니다 .
-
지역 최적값은 ① 왼쪽에서 오른쪽으로 1회 순회하여 오른쪽 자식이 왼쪽보다 점수가 높은 경우만 비교하고, ② 오른쪽에서 왼쪽으로 1회 순회하며 다음과 같은 경우만 비교합니다. 왼쪽 아이가 오른쪽 아이보다 점수가 높습니다. ③ 이것은 i번째 아이가 왼쪽과 오른쪽에 있는 것보다 더 많은 사탕을 가지고 있음을 보장합니다.
-
전역 최적성은 다음과 같은 경우에 반영됩니다. 점수가 높은 어린이는 더 많은 사탕을 받습니다.
나. 구체적인 시행
-
각 자식의 사탕 수를 저장할 새 배열을 만들고 각 자식이 가진 사탕 수를 1로 초기화합니다.
-
배열의 첨자 순서에 따라 두 번 순회, 첫 번째 양수 순회, 오른쪽 자식의 점수가 왼쪽보다 높으면 오른쪽 자식의 캔디 개수를 의 개수로 업데이트 왼쪽에 있는 아이의 사탕 + 1;
-
두 번째 역순회에서 왼쪽 자식의 점수가 오른쪽 자식보다 높고, 현재 왼쪽 자식의 캔디 개수가 오른쪽 자식의 캔디 개수보다 크지 않다면 , 왼쪽 자식은 오른쪽 자식의 사탕 수에 1을 더한 값으로 업데이트됩니다. max (첫 번째 탐색의 현재 캔디 수, 오른쪽 자식 캔디 수 + 1).
-
널 포인터 예외를 피하기 위해 두 번 순회할 때 배열의 시작 첨자를 신중하게 고려하십시오.
-
마지막으로 모든 사탕을 합산하십시오.
c. 생각하다
-
점수와 사탕의 수는 두 개의 독립 변수이지만 배열 인덱스 변수는 처음 두 개와 관련이 있습니다.
-
어린이 그룹에 해당하는 캔디 번호는 처음 두 숫자를 제외하고 한쪽에 인접한 숫자만 있고 나머지 중간 숫자는 양쪽에 인접한 숫자가 있습니다. 두 쌍을 비교할 때 먼저 한쪽의 크기를 고려하고(예: 오른쪽을 먼저 고려) 이 쪽(오른쪽)에 대한 모든 판단이 완료된 후 다른 쪽(왼쪽)을 고려합니다.
-
처음으로 오른쪽 자식이 왼쪽 자식보다 나이가 많다고 판단했을 때 역순 순회가 아닌 정순 순회를 채택한 이유는? 첫 번째 그룹의 rvalue B[왼쪽 값 A, rvalue B]를 증가시킨 후, 두 번째 그룹[rvalue B의 첫 번째 그룹, 새로운 rvalue C]는 크다 판단 시 B를 기준으로 증가시킬 수 있기 때문에, 누락 없음. 오른쪽 자식이 왼쪽 자식보다 나이가 많다고 오른쪽에서 왼쪽으로(플래시백) 판단되면 이전 . (두 번째 순회도 마찬가지입니다.)
-
for() 루프의 사용은 주로 각 배열의 첨자에 해당하는 번호를 사용하는 것으로 순회 후 자동으로 멈추므로 while()을 통해 종료 조건을 직접 설정할 필요가 없습니다.
-
앞선 질문에서 아이의 요구량 과 비스킷 알고 있는데, 이는 비스킷의 특정 수량을 알려주는 것과 같고(주된 조건을 알고 있음) 기존 비스킷을 사용하여 비교 및 판단하기만 하면 됩니다(수요 <= 비스킷 크기? )를 아이에게 맞추면 만족하는 아이의 최대 수를 얻을 수 있습니다. (자식과 쿠키의 수와 속성을 알고 있으며, 관계를 찾습니다.)
-
이 질문은 아이의 뿐 사탕의 구체적인 양은 없고(주요 조건은 알 수 없음) 다른 부차적인 조건만 주어집니다. (아이들은 수량과 속성을 알고, 사탕은 속성은 알지만 수량은 모르고, 둘 사이의 관계도 알고, 사탕의 수를 찾습니다)
D. 코드 구현
public int candy(int[] ratings) {
int[] suger = new int[ratings.length];
suger[0] = 1;
// 如果孩子没有或只有一位,则不需要进行分配,直接返回孩子个数即可。
if (ratings.length < 2) {
return ratings.length;
}
// 顺序遍历
for (int i = 1; i < ratings.length; i++) {
if ( ratings[i] > ratings[i - 1]) { //右大于左
suger[i] = suger[i - 1] + 1;
} else {
suger[i] = 1; //初始化其他为1
}
}
// 倒序遍历
for (int i = ratings.length - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1]) { //左大于右
suger[i] = Math.max(suger[i], suger[i + 1] + 1); //取【左孩子本身,(右孩子+1)】的糖果最大值
}
}
int count = 0;
for (int i : suger) {
count += i;
}
return count;
}