leetcode
leetcode 2351 ~ 2400
使所有字符相等的最小成本

使所有字符相等的最小成本

难度:

标签:

题目描述

You are given a 0-indexed binary string s of length n on which you can apply two types of operations:

  • Choose an index i and invert all characters from index 0 to index i (both inclusive), with a cost of i + 1
  • Choose an index i and invert all characters from index i to index n - 1 (both inclusive), with a cost of n - i

Return the minimum cost to make all characters of the string equal.

Invert a character means if its value is '0' it becomes '1' and vice-versa.

 

Example 1:

Input: s = "0011"
Output: 2
Explanation: Apply the second operation with i = 2 to obtain s = "0000" for a cost of 2. It can be shown that 2 is the minimum cost to make all characters equal.

Example 2:

Input: s = "010101"
Output: 9
Explanation: Apply the first operation with i = 2 to obtain s = "101101" for a cost of 3.
Apply the first operation with i = 1 to obtain s = "011101" for a cost of 2. 
Apply the first operation with i = 0 to obtain s = "111101" for a cost of 1. 
Apply the second operation with i = 4 to obtain s = "111110" for a cost of 2.
Apply the second operation with i = 5 to obtain s = "111111" for a cost of 1. 
The total cost to make all characters equal is 9. It can be shown that 9 is the minimum cost to make all characters equal.

 

Constraints:

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

代码结果

运行时间: 94 ms, 内存: 16.5 MB


/*
 * 思路:
 * 使用Java Stream API,我们可以简化代码。通过流的操作来计算不同的反转成本。
 * 我们仍然需要计算将所有字符变为 '0' 或 '1' 的最小成本。
 */
import java.util.stream.IntStream;

public class MinCostStream { 
    public int minCost(String s) { 
        int n = s.length(); 
        int[] costsForZero = new int[n]; 
        int[] costsForOne = new int[n]; 
        IntStream.range(0, n).forEach(i -> { 
            costsForZero[i] = s.charAt(i) == '1' ? i : 0; 
            costsForOne[i] = s.charAt(i) == '0' ? i : 0; 
        }); 
        int totalCostForAllToZero = IntStream.of(costsForZero).sum(); 
        int totalCostForAllToOne = IntStream.of(costsForOne).sum(); 
        return Math.min(totalCostForAllToZero, totalCostForAllToOne); 
    } 
}

解释

方法:

此题解的思路是将字符串分为左右两部分进行处理。对于每一部分,遍历字符串,比较相邻字符是否相等。如果不相等,就累加当前下标作为成本。对于长度为奇数的字符串,中间的字符需要特殊处理。最后将所有成本累加得到最小成本。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在处理长度为奇数的字符串时,中间的字符需要特殊处理?
在处理长度为奇数的字符串时,中间的字符没有对称的字符与之匹配,因此它的处理不能简单地归入左半部分或右半部分。这个字符可能需要与它前后的字符进行比较来确定是否需要改变以达到最终目标,即所有字符相等。因此,中间的字符成为了一个特殊的分界点,需要独立考虑它与左右相邻字符的关系来计算额外的成本。
🦆
题解中提到的将字符串分为左右两部分处理,具体是如何定义这两部分的?
题解中的处理方式是将字符串从中间分割开,如果字符串长度为偶数,则可以平均分为两部分。如果长度为奇数,则中间的字符单独处理,左半部分包含从开始到中间字符前的部分,右半部分则是从字符串末尾到中间字符后的部分。这种分法允许在遍历时同时从头部和尾部向中间进行,简化了比较和成本计算的过程。
🦆
在计算成本时,累加当前下标的方式是否确实能代表实际操作的成本?
累加当前下标作为成本的方式是一种简化的方法,实际上它假设了每一步操作的成本与当前位置的下标成正比。这种设定主要是为了反映越靠近字符串中心的改变成本可能越高的假设。虽然这不完全准确地反映了所有可能的场景,但它提供了一种计算上的便利和直观的理解方式,特别是在没有具体每步操作成本的详细信息时。
🦆
为什么在遍历字符串比较相邻字符的时候,仅通过增加下标值来计算成本?
在遍历字符串并比较相邻字符时,通过增加下标值来计算成本是一种抽象的模拟方式。这种计算方法假设修改字符的成本与其在字符串中的位置有关,即位置越靠近中心,修改的成本越高。这样的设定可能是为了模拟实际情况中,修改靠近中心的字符可能会影响更多的其他操作或者需要更多的步骤来保持整体的平衡。

相关问题