2938. 区分黑球与白球
题目描述:
桌子上有 n
个球,每个球的颜色不是黑色,就是白色。
给你一个长度为 n
、下标从 0 开始的二进制字符串 s
,其中 1
和 0
分别代表黑色和白色的球。
在每一步中,你可以选择两个相邻的球并交换它们。
返回「将所有黑色球都移到右侧,所有白色球都移到左侧所需的 最小步数」。
示例 1:
输入:s = "101"
输出:1
解释:我们可以按以下方式将所有黑色球移到右侧:
- 交换 s[0] 和 s[1],s = "011"。
最开始,1 没有都在右侧,需要至少 1 步将其移到右侧。
示例 2:
输入:s = "100"
输出:2
解释:我们可以按以下方式将所有黑色球移到右侧:
- 交换 s[0] 和 s[1],s = "010"。
- 交换 s[1] 和 s[2],s = "001"。
可以证明所需的最小步数为 2 。
示例 3:
输入:s = "0111"
输出:0
解释:所有黑色球都已经在右侧。
提示:
1 <= n == s.length <= 105
s[i]
不是'0'
,就是'1'
。
解题分析及思路:
方法:双指针
思路:
不管怎样交换,最终结果就是将所有黑色球都移到右侧,所有白色球都移到左侧,所以基本可以无视题目中的相邻之间的交换。
那么可以使用双指针:
- 一个指针
left
从左往右找,找到第一个为1的数 - 一个指针
right
从右往左找,找到第一个为0的数 最后将两个数交换,交换所需要移动的步数为两个指针下标之差
然后重复次操作,直到所有的0在左侧,所有的1在右侧,即 left >= right
时,退出
func minimumSteps(s string) (result int64) {
left, right := 0, len(s)-1
for left < right {
for left < len(s) && s[left] == '0' {
left++
}
for right >= 0 && s[right] == '1' {
right--
}
if left < right {
result += int64(right - left)
}
left++
right--
}
return
}
复杂度:
- 时间复杂度:O(N)
- 空间复杂度:O(1)
执行结果:
- 执行耗时:7 ms,击败了100.00% 的Go用户
- 内存消耗:6.2 MB,击败了70.83% 的Go用户