leetcode
leetcode 2401 ~ 2450
在传球游戏中最大化函数值

在传球游戏中最大化函数值

难度:

标签:

题目描述

You are given a 0-indexed integer array receiver of length n and an integer k.

There are n players having a unique id in the range [0, n - 1] who will play a ball passing game, and receiver[i] is the id of the player who receives passes from the player with id i. Players can pass to themselves, i.e. receiver[i] may be equal to i.

You must choose one of the n players as the starting player for the game, and the ball will be passed exactly k times starting from the chosen player.

For a chosen starting player having id x, we define a function f(x) that denotes the sum of x and the ids of all players who receive the ball during the k passes, including repetitions. In other words, f(x) = x + receiver[x] + receiver[receiver[x]] + ... + receiver(k)[x].

Your task is to choose a starting player having id x that maximizes the value of f(x).

Return an integer denoting the maximum value of the function.

Note: receiver may contain duplicates.

 

Example 1:

Pass Number Sender ID Receiver ID x + Receiver IDs
      2
1 2 1 3
2 1 0 3
3 0 2 5
4 2 1 6
Input: receiver = [2,0,1], k = 4
Output: 6
Explanation: The table above shows a simulation of the game starting with the player having id x = 2. 
From the table, f(2) is equal to 6. 
It can be shown that 6 is the maximum achievable value of the function. 
Hence, the output is 6. 

Example 2:

Pass Number Sender ID Receiver ID x + Receiver IDs
      4
1 4 3 7
2 3 2 9
3 2 1 10
Input: receiver = [1,1,1,2,3], k = 3
Output: 10
Explanation: The table above shows a simulation of the game starting with the player having id x = 4. 
From the table, f(4) is equal to 10. 
It can be shown that 10 is the maximum achievable value of the function. 
Hence, the output is 10. 

 

Constraints:

  • 1 <= receiver.length == n <= 105
  • 0 <= receiver[i] <= n - 1
  • 1 <= k <= 1010

代码结果

运行时间: 333 ms, 内存: 58.4 MB


/*
 * Problem Statement:
 * There are n players, each represented by an index from 0 to n-1. The receiver array indicates which player each player passes the ball to.
 * Starting with a chosen player x, the ball is passed k times. We need to find the maximum sum of player indices touched by the ball, starting from any player x.
 * f(x) = x + receiver[x] + receiver[receiver[x]] + ... for k passes.
 */

import java.util.stream.LongStream;

public class MaximizePassesStream {
    public static long maxSum(int[] receiver, long k) {
        return LongStream.range(0, receiver.length)
                .map(i -> {
                    long currentSum = 0;
                    int currentPlayer = (int) i;
                    for (long j = 0; j < k; j++) {
                        currentSum += currentPlayer;
                        currentPlayer = receiver[currentPlayer];
                    }
                    return currentSum;
                })
                .max()
                .orElse(0);
    }

    public static void main(String[] args) {
        int[] receiver1 = {2, 0, 1};
        long k1 = 4;
        System.out.println(maxSum(receiver1, k1)); // Output: 6

        int[] receiver2 = {1, 1, 1, 2, 3};
        long k2 = 3;
        System.out.println(maxSum(receiver2, k2)); // Output: 10
    }
}

解释

方法:

该题解采用复杂的方法处理球传递游戏问题。首先,创建一个数据结构记录每个玩家作为接球者的所有前驱,用于处理球的传递链。通过定义 FillNode 类来追踪传球过程中的累积分数以及其他元数据,然后实现一个 iterNode 函数来遍历传球链。主要的处理逻辑在 fill 函数中,该函数利用循环找到传球序列的开始和结束,并计算序列长度以及累积和,从而能够模拟整个传球过程并更新每个玩家的最终得分。最后,通过遍历所有可能的传球起始玩家来找到可以获得最大分数的起始玩家。

时间复杂度:

O(n * k)

空间复杂度:

O(n)

代码细节讲解

🦆
在算法中,为什么选择使用一个复杂的数据结构来记录每个玩家作为接球者的所有前驱而不是直接模拟传球过程?
使用复杂的数据结构记录每个玩家作为接球者的所有前驱主要是为了高效地处理问题中的循环依赖和重复计算。这种方法可以快速确定传球链中的环形结构和环外部分,从而避免在模拟传球过程中重复遍历同一路径或节点,尤其是在长传球链和环形链中更为有效。此外,这种数据结构还有助于快速更新和查询每个玩家的累积得分,尤其是在有多个前驱的情况下,可以更灵活地处理分支和合并的情况。
🦆
请问在 iterNode 函数中,yield node 的作用是什么,它如何影响传球链的遍历过程?
在 iterNode 函数中,`yield node` 的作用是创建一个生成器,它逐一返回传球链中的节点。这种方式允许函数的调用者在每次迭代时获得当前节点并对其执行操作,而不需要一次性获取全部节点。这样的延迟计算(按需计算)可以提高内存利用率,同时使得处理每个节点的逻辑更加灵活和可控。通过生成器,可以在遍历过程中更容易地插入或删除节点,或在遍历时动态调整遍历策略,这对于处理复杂的传球链尤为重要。
🦆
在 fill 函数中,circleLen 和 circleSum 分别代表什么,它们是如何计算的?
在 fill 函数中,`circleLen` 代表在传球链中检测到的环的长度,即环中包含的节点数。`circleSum` 则代表这个环中所有节点的索引值的累积和。环的检测是通过记录节点在遍历过程中的出现位置来完成的,一旦发现某个节点重新被访问,即确认存在环。此时,`circleLen` 计算为当前节点位置与该节点首次出现位置之间的差值。`circleSum` 是从环开始的位置到环结束的位置节点值的累积和。这两个参数对于计算在环中进行多圈后每个节点的累积得分非常关键,它们使得可以快速计算多次遍历环时的得分增加量。
🦆
算法在处理传球链是环形的情况时,如何确保不会出现无限循环的问题,并且如何处理环上的节点计分?
算法通过映射每个节点第一次被访问的位置来识别环,并使用环的长度和累积和来计算环上的节点得分。一旦检测到环,算法计算传球次数与环长度的商和余数,利用这些信息来确定遍历环的完整圈数和额外部分。通过这种方式,算法可以精确地计算在规定的传球次数内每个节点的得分,而无需实际模拟每一次传球,从而避免了无限循环的问题。对于环上的节点,算法计算多圈后的累积得分加上在最后一部分环内的得分,以此确保每个节点得分的正确性。

相关问题