LeetCode Brush Questions: Greedy Algorithm [135. 캔디 배포하기] - 자바 버전

그리디 알고리즘: 할당 문제

스스로 문제를 푸는 과정을 기록했을 뿐이고, 답을 위해 다양한 솔루션을 참고했습니다.

틀린 부분이 있으면 수정해주시면 감사하겠습니다!

참조: 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;
}

おすすめ

転載: blog.csdn.net/weixin_51909882/article/details/122139597