leetcode
leetcode 2501 ~ 2550
区分黑球与白球

区分黑球与白球

难度:

标签:

题目描述

There are n balls on a table, each ball has a color black or white.

You are given a 0-indexed binary string s of length n, where 1 and 0 represent black and white balls, respectively.

In each step, you can choose two adjacent balls and swap them.

Return the minimum number of steps to group all the black balls to the right and all the white balls to the left.

 

Example 1:

Input: s = "101"
Output: 1
Explanation: We can group all the black balls to the right in the following way:
- Swap s[0] and s[1], s = "011".
Initially, 1s are not grouped together, requiring at least 1 step to group them to the right.

Example 2:

Input: s = "100"
Output: 2
Explanation: We can group all the black balls to the right in the following way:
- Swap s[0] and s[1], s = "010".
- Swap s[1] and s[2], s = "001".
It can be proven that the minimum number of steps needed is 2.

Example 3:

Input: s = "0111"
Output: 0
Explanation: All the black balls are already grouped to the right.

 

Constraints:

  • 1 <= n == s.length <= 105
  • s[i] is either '0' or '1'.

代码结果

运行时间: 60 ms, 内存: 17.1 MB


/*
 * 题目思路:
 * 使用Java Stream实现与上述Java代码相同的逻辑。通过遍历字符数组计算黑色球的数量和需要移动的步数。
 */
import java.util.stream.IntStream;

public class Solution {
    public int minMovesToMoveBalls(String s) {
        int[] result = IntStream.range(0, s.length()).mapToObj(i -> s.charAt(i)).reduce(new int[]{0, 0}, (acc, c) -> {
            if (c == '1') {
                acc[0]++;
            } else {
                acc[1] += acc[0];
            }
            return acc;
        }, (a, b) -> new int[]{a[0] + b[0], a[1] + b[1]});
        return result[1];
    }
}

解释

方法:

题解的思路是通过一次遍历来统计将所有白球移至左侧(或黑球移至右侧)所需的最小交换次数。具体实现为:初始化两个变量,`b_cnt` 用来记录至当前位置为止遇到的黑球数量,`ans` 用来累计总的交换次数。当遇到一个白球(`'0'`)时,意味着这个白球需要通过交换越过之前已经统计过的所有黑球,因此要将`b_cnt`(当前已经遇到的黑球数量)加到`ans`上。当遇到黑球(`'1'`)时,仅将`b_cnt`加一,表示又遇到了一个黑球,不需要额外操作。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在遇到白球时,需要将之前遇到的黑球数加到总交换次数中?
在遇到白球时,需要将之前遇到的黑球数加到总交换次数中,是因为每个白球需要移动到所有先前遇到的黑球的左侧。这意味着每个白球需要越过之前统计的所有黑球,每越过一个黑球就需要进行一次交换。因此,当前白球的移动次数等于之前遇到的黑球数量。
🦆
在整个字符串s遍历的过程中,累积的黑球数量b_cnt是如何影响白球移动的交换次数的?
在字符串s遍历过程中,累积的黑球数量b_cnt直接决定了每个遇到的白球需要进行的交换次数。具体来说,每当遇到一个白球时,其需要通过的交换次数正是当时已经累积的黑球数量b_cnt。因此,b_cnt越大,任何后续遇到的白球都需要更多的交换次数来移到所有黑球的左侧。
🦆
如果输入的字符串s中全部是黑球或全部是白球,该算法的输出结果是什么?这种情况是否还需要进行交换?
如果输入的字符串s中全部是黑球,那么没有白球需要移动,所以算法的输出结果将是0,不需要任何交换。同样的,如果全部是白球,也不需要进行任何交换,因为所有白球已经位于其应在的位置,输出结果也是0。这表明在这两种情况下,算法正确地识别出不需要进行任何交换。
🦆
该算法在处理非常长的字符串时的表现如何?例如,如果s的长度达到百万级别,该算法的性能是否还能保持效率?
该算法在处理非常长的字符串时表现良好,因为它只需要进行一次遍历,即具有O(n)的时间复杂度,其中n是字符串的长度。即便字符串长度达到百万级别,该算法仍然能以线性时间完成处理,保持高效。算法的空间复杂度也很低,只需要常数级的额外空间。因此,该算法适合处理长字符串,性能保持高效。

相关问题