leetcode
leetcode 2501 ~ 2550
最小数字游戏

最小数字游戏

难度:

标签:

题目描述

You are given a 0-indexed integer array nums of even length and there is also an empty array arr. Alice and Bob decided to play a game where in every round Alice and Bob will do one move. The rules of the game are as follows:

  • Every round, first Alice will remove the minimum element from nums, and then Bob does the same.
  • Now, first Bob will append the removed element in the array arr, and then Alice does the same.
  • The game continues until nums becomes empty.

Return the resulting array arr.

 

Example 1:

Input: nums = [5,4,2,3]
Output: [3,2,5,4]
Explanation: In round one, first Alice removes 2 and then Bob removes 3. Then in arr firstly Bob appends 3 and then Alice appends 2. So arr = [3,2].
At the begining of round two, nums = [5,4]. Now, first Alice removes 4 and then Bob removes 5. Then both append in arr which becomes [3,2,5,4].

Example 2:

Input: nums = [2,5]
Output: [5,2]
Explanation: In round one, first Alice removes 2 and then Bob removes 5. Then in arr firstly Bob appends and then Alice appends. So arr = [5,2].

 

Constraints:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 100
  • nums.length % 2 == 0

代码结果

运行时间: 20 ms, 内存: 16.0 MB


/* 
 * 思路:
 * 1. 将 nums 数组排序。
 * 2. 使用 Stream API 将数组前半部分倒序添加到 arr,然后将后半部分按顺序添加到 arr。 
 */
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class GameSolutionStream {
    public static List<Integer> playGame(int[] nums) {
        return IntStream.concat(
                    Arrays.stream(nums).sorted().skip(nums.length / 2).boxed(), // Bob 添加
                    Arrays.stream(nums).sorted().limit(nums.length / 2).boxed().sorted((a, b) -> b - a) // Alice 添加
                ).collect(Collectors.toList());
    }

    public static void main(String[] args) {
        int[] nums = {5, 4, 2, 3};
        System.out.println(playGame(nums)); // 输出: [3, 2, 5, 4]
    }
}

解释

方法:

题解首先对输入数组 nums 进行逆序排序,即从大到小排序。这样,每次通过 nums.pop() 取出的将是数组中当前的最小值。由于 Alice 先移除最小元素,随后 Bob 移除次小元素,这两个元素被加入到结果数组 result 中时,Bob 加入的元素应该在 Alice 加入的元素之前。因此,每次迭代中,先从逆序排序的 nums 中 pop 出两个元素(首先是最小的,然后是次小的),然后先将次小的元素(Bob 移除的)加入到 result,再加入最小的元素(Alice 移除的)。整个过程重复进行,直到 nums 为空。

时间复杂度:

O(n log n)

空间复杂度:

O(n)

代码细节讲解

🦆
题解中提到,对数组进行逆序排序以使得pop()操作能取出最小值,这种操作是否考虑了pop()默认从数组尾部移除元素的行为?
是的,题解中的逆序排序确实考虑到了pop()操作默认从数组的尾部移除元素的行为。通过将数组逆序排序(从大到小),数组的尾部就变成了最小的元素。因此,每次使用pop()移除尾部元素时,实际上是移除了当前数组中的最小值。这种方法有效地利用了pop()的默认行为,简化了代码逻辑,使得每次操作直接获得最小值,无需额外的操作或计算。
🦆
在题解描述的排序和pop操作中,为什么选择先让Bob添加次小元素,随后Alice添加最小元素,这样的顺序是否与题目中Alice先操作的描述相符?
这个问题指出了题解中的一个潜在错误。根据题目的描述,Alice应该是先操作的,然后是Bob。但在题解中的实现中,Bob先添加次小元素,Alice再添加最小元素,这与题目描述的顺序相反。这可能是解题思路或描述中的一个误区,应该调整实现以确保Alice先添加她移除的最小元素,然后Bob添加次小元素,以符合题目的原始意图。
🦆
在题解中使用了数组的pop()操作,这种方法是否适用于所有编程语言中的数组实现?如果不是,应该如何调整?
数组的pop()操作在多数编程语言如Python、JavaScript、Java中通常是可用的,但其行为和效率可能略有不同。例如,在Java中,数组没有内置的pop()方法,通常需要使用ArrayList或其他动态数据结构来实现类似的功能。如果在不支持pop()操作的语言中实现这种逻辑,可以使用动态数组或链表,并手动实现移除最后一个元素的功能,或者直接操作索引来模拟pop()操作。
🦆
对于数组的初始条件是偶数长度,题解中的逻辑是否有处理奇数长度数组的情况或进行了必要的假设?
题解中的逻辑假设了数组长度是偶数,因为它每次迭代中都从数组中移除两个元素。如果数组长度是奇数,当前的实现可能会在最后一次迭代时遇到问题,因为最后只剩一个元素而代码尝试移除两个。这种情况需要额外的处理:例如,可以在迭代之前检查数组长度,如果是奇数,则先处理最后一个元素,或者在迭代中加入条件检查确保不会尝试从只含一个元素的数组中再次pop()。

相关问题