贪心猫的鱼干大分配| 豆包MarsCode AI 刷题

45 阅读4分钟

问题描述

在猫星球上,小R负责给一行排队的猫分发鱼干。每只猫有一个等级,等级越高的猫应该得到更多的鱼干。规则如下:

  1. 每只猫至少得到一斤鱼干。
  2. 如果一只猫的等级高于它相邻的猫,它就应该得到比相邻的猫更多的鱼干。

小R想知道,为了公平地满足所有猫的等级差异,他至少需要准备多少斤鱼干。


测试样例

样例1:

输入:n = 3, cats_levels = [1, 2, 2]
输出:4

样例2:

输入:n = 6, cats_levels = [6, 5, 4, 3, 2, 16]
输出:17

样例3:

输入:n = 20, cats_levels = [1, 2, 2, 3, 3, 20, 1, 2, 3, 3, 2, 1, 5, 6, 6, 5, 5, 7, 7, 4]
输出:35

问题理解

题目要求我们给一排猫分发鱼干,每只猫至少得到一斤鱼干。如果一只猫的等级高于它相邻的猫,它就应该得到比相邻的猫更多的鱼干。我们需要计算出满足这些条件所需的最少鱼干总数。简单来说,就是贪心。

关键点

  1. 每只猫至少得到一斤鱼干:这意味着每只猫的鱼干数至少为1。
  2. 等级高的猫得到更多的鱼干:如果一只猫的等级高于它相邻的猫,那么它的鱼干数应该比相邻的猫多。

数据结构选择

我们可以使用一个数组 resultArr 来记录每只猫应该得到的鱼干数。数组的索引对应猫的位置,数组的值对应猫的鱼干数。

算法步骤

  1. 初始化:创建一个与 ratings 数组长度相同的 resultArr,初始值为1,因为每只猫至少得到一斤鱼干。
  2. 从左到右遍历:从左到右遍历 ratings 数组,如果当前猫的等级高于它左边的猫,那么它的鱼干数应该比左边的猫多1。
  3. 从右到左遍历:从右到左遍历 ratings 数组,如果当前猫的等级高于它右边的猫,那么它的鱼干数应该比右边的猫多1,但要确保不小于之前计算的值。
  4. 计算总数:遍历 resultArr,累加所有猫的鱼干数,得到最终结果。

复杂度分析

  • 时间复杂度:O(n),因为我们只需要遍历数组两次。
  • 空间复杂度:O(n),因为我们使用了一个额外的数组 resultArr 来存储每只猫的鱼干数。

代码

以下为golang版本的代码,暂时未通过评测(还没上线)

package main

import "fmt"
import "math"

func solution(n int, ratings []int) int {
	if len(ratings) == 1 {
		return 1
	}
	// 桶排序
	ratingsBucket := make([][]int, 20001)
	for key, value := range ratings {
		ratingsBucket[value] = append(ratingsBucket[value], key)
	}
	resultArr := make([]int, len(ratings))
	for _, value := range ratingsBucket {
		if len(value) == 0 {
			continue
		}
		tempResultArr := make([]int, len(resultArr))
		copy(tempResultArr, resultArr)
		for _, val := range value {
			if val == 0 {
				if ratings[val] > ratings[val+1] {
					resultArr[val] = tempResultArr[val+1] + 1
				} else {
					resultArr[val] = 1
				}
			} else if val == len(ratings)-1 {
				if ratings[val] > ratings[val-1] {
					resultArr[val] = tempResultArr[val-1] + 1
				} else {
					resultArr[val] = 1
				}
			} else {
				resultArr[val] = int(math.Max(float64(tempResultArr[val+1]), float64(tempResultArr[val-1])) + 1)
			}
		}
	}

	result := 0
	for _, val := range resultArr {
		result += val
	}
	return result
}

func main() {
	// You can add more test cases here
	catsLevels1 := []int{1, 2, 2}
	catsLevels2 := []int{6, 5, 4, 3, 2, 16}
	catsLevels3 := []int{1, 2, 2, 3, 3, 20, 1, 2, 3, 3, 2, 1, 5, 6, 6, 5, 5, 7, 7, 4}
	fmt.Println(solution(3, catsLevels1) == 4)
	fmt.Println(solution(6, catsLevels2) == 17)
	fmt.Println(solution(20, catsLevels3) == 35)
}

以下是使用marscode翻译而来的python代码,已通过评测

import math

def solution(n, ratings):
    if len(ratings) == 1:
        return 1
    
    # 桶排序
    ratings_bucket = [[] for _ in range(20001)]
    for key, value in enumerate(ratings):
        ratings_bucket[value].append(key)
    
    result_arr = [0] * len(ratings)
    for value in ratings_bucket:
        if len(value) == 0:
            continue
        temp_result_arr = result_arr[:]
        for val in value:
            if val == 0:
                if ratings[val] > ratings[val + 1]:
                    result_arr[val] = temp_result_arr[val + 1] + 1
                else:
                    result_arr[val] = 1
            elif val == len(ratings) - 1:
                if ratings[val] > ratings[val - 1]:
                    result_arr[val] = temp_result_arr[val - 1] + 1
                else:
                    result_arr[val] = 1
            else:
                result_arr[val] = max(temp_result_arr[val + 1], temp_result_arr[val - 1]) + 1
    
    result = sum(result_arr)
    return result

if __name__ == "__main__":
    #  You can add more test cases here
    cats_levels1 = [1, 2, 2]
    cats_levels2 = [6, 5, 4, 3, 2, 16]
    cats_levels3 = [1, 2, 2, 3, 3, 20, 1, 2, 3, 3, 2, 1, 5, 6, 6, 5, 5, 7, 7, 4]
    print(solution(3, cats_levels1) == 4)
    print(solution(6, cats_levels2) == 17)
    print(solution(20, cats_levels3) == 35)

总结

从题目名称也可以看出这是一道贪心的题目,贪心题目主要难点就是发现这是一道贪心的题目,发现之后基本就是常识模拟题了。