引言

​ 今天开始,打算做一个新的系列:leetcode每日一题的题解。预期每天用90分钟的时间,去写一篇当天的每日一题的题解,这个目标跟早起结合在一起,才有足够的时间完成。其实早在前几年,就开始断断续续做leetcode的每日一题,但每次连续坚持的时间都不长,可能坚持一个多月,就因为各种原因间断了。一鼓作气,再而衰,三而竭。这种需要长期坚持的事情,一旦间断,就很难再继续坚持了。今天选择再出发,先给自己定个小目标:至少坚持100天。

题目

1963. 使字符串平衡的最小交换次数

给你一个字符串 s下标从 0 开始 ,且长度为偶数 n 。字符串 恰好n / 2 个开括号 '['n / 2 个闭括号 ']' 组成。

只有能满足下述所有条件的字符串才能称为 平衡字符串

  • 字符串是一个空字符串,或者
  • 字符串可以记作 AB ,其中 AB 都是 平衡字符串 ,或者
  • 字符串可以写成 [C] ,其中 C 是一个 平衡字符串

你可以交换 任意 两个下标所对应的括号 任意 次数。

返回使 s 变成 平衡字符串 所需要的 最小 交换次数。

示例 1:

输入:s = "][]["
输出:1
解释:交换下标 0 和下标 3 对应的括号,可以使字符串变成平衡字符串。
最终字符串变成 "[[]]" 。

示例 2:

输入:s = "]]][[["
输出:2
解释:执行下述操作可以使字符串变成平衡字符串:
- 交换下标 0 和下标 4 对应的括号,s = "[]][][" 。
- 交换下标 1 和下标 5 对应的括号,s = "[[][]]" 。
最终字符串变成 "[[][]]" 。

示例 3:

输入:s = "[]"
输出:0
解释:这个字符串已经是平衡字符串。

提示:

  • n == s.length
  • 2 <= n <= 106
  • n 为偶数
  • s[i]'['']'
  • 开括号 '[' 的数目为 n / 2 ,闭括号 ']' 的数目也是 n / 2

思路

​ 题目中描述的“平衡字符串”,其实可以用一句话来概括:合法的括号。即对于每个右括号而言,都可以在它的左侧找到唯一的一个只匹配给它的左括号。

​ 提到合法的括号,很多同学第一反应就是栈。我们在判断一个字符串是否是合法的括号,就是栈的做法:

  • 遇到左括号,压栈
  • 遇到右括号,出栈,如果栈为空,那么此时肯定不是合法的括号

​ 不过本题有一些差异,并不是要判断这个字符串是不是合法的括号,而是要求出,最小交换几对,使得这个字符串变成合法的括号。所以,我们这里处理上,也有一些小差异:可以把压栈和出栈的操作看到最合法括号的对消,类似消消乐,那么当我们遇到当前是右括号且空栈的情况下,没有左侧括号可以匹配,可以把这个单独的右括号记录下来。由于整体来看,左右括号的数量必然是相等的,所以我们把合法的括号都消除后,留下来的必然是这样的形式:“]]]...[[[”,k个']'开头,后面跟着k个‘[’。不难想到,我们拿最前面的(k+1)/2个右括号‘]’去跟最后面的(k+1)/2个左括号‘[’交换后,整个字符串就是合法的括号了。

图解

代码

public int minSwaps0(String s) {
int right = 0;
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '[') {
stack.push(c);
} else if (c == ']') {
if (!stack.isEmpty()) {
stack.pop();
} else {
right++;
}
}
}
return (right + 1) >> 1;
}

注意:这里最后使用了xxx >> 1这样的位移操作来代替除以2的操作,是对于整数 乘以2 或者 除以2 运算的常见优化,提高执行效率。

耗时

优化

进一步想,我们这里其实并不需要真正操作压栈和出栈,直接用一个整形变量cnt代替,压栈操作转换为+1,出栈操作转换为-1,判断栈是否为空可以转换为cnt == 0

代码

public int minSwaps(String s) {
int right = 0;
int cnt = 0;
for (char c : s.toCharArray()) {
if (c == '[') {
cnt++;
} else if (c == ']') {
if (cnt != 0) {
cnt--;
} else {
right++;
}
}
}
return (right + 1) >> 1;
}

耗时

leetcode每日一题:使字符串平衡的最小交换次数的更多相关文章

  1. 【python】Leetcode每日一题-扰乱字符串

    [python]Leetcode每日一题-扰乱字符串 [题目描述] 使用下面描述的算法可以扰乱字符串 s 得到字符串 t : 如果字符串的长度为 1 ,算法停止 如果字符串的长度 > 1 ,执行 ...

  2. Java实现 LeetCode 801 使序列递增的最小交换次数 (DP)

    801. 使序列递增的最小交换次数 我们有两个长度相等且不为空的整型数组 A 和 B . 我们可以交换 A[i] 和 B[i] 的元素.注意这两个元素在各自的序列中应该处于相同的位置. 在交换过一些元 ...

  3. [Swift]LeetCode801. 使序列递增的最小交换次数 | Minimum Swaps To Make Sequences Increasing

    We have two integer sequences A and B of the same non-zero length. We are allowed to swap elements A ...

  4. 【python】Leetcode每日一题-最大数

    [python]Leetcode每日一题-最大数 [题目描述] 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数. 注意:输出结果可能非常大,所以你需要返回一个 ...

  5. 【js】Leetcode每日一题-完成所有工作的最短时间

    [js]Leetcode每日一题-完成所有工作的最短时间 [题目描述] 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工 ...

  6. 【JavaScript】Leetcode每日一题-递增顺序搜索树

    [JavaScript]Leetcode每日一题-递增顺序搜索树 [题目描述] 给你一棵二叉搜索树,请你 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没 ...

  7. 【JavaScript】【dp】Leetcode每日一题-解码方法

    [JavaScript]Leetcode每日一题-解码方法 [题目描述] 一条包含字母 A-Z 的消息通过以下映射进行了 编码 : 'A' -> 1 'B' -> 2 ... 'Z' -& ...

  8. 【JavaScript】【KMP】Leetcode每日一题-实现strStr()

    [JavaScript]Leetcode每日一题-实现strStr() [题目描述] 实现 strStr() 函数. 给你两个字符串 haystack 和 needle ,请你在 haystack 字 ...

  9. 【python】Leetcode每日一题-删除有序数组中的重复项

    [python]Leetcode每日一题-删除有序数组中的重复项 [题目描述] 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现一次 ,返回删除后数组的新长度. 不要 ...

  10. [LeetCode每日一题]81. 搜索旋转排序数组 II

    [LeetCode每日一题]81. 搜索旋转排序数组 II 问题 已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同. 在传递给函数之前,nums 在预先未知的某个下标 k(0 & ...

随机推荐

  1. 深入解析子查询(SUBQUERY):增强 SQL 查询灵活性的强大工具

    title: 深入解析子查询(SUBQUERY):增强 SQL 查询灵活性的强大工具 date: 2025/1/12 updated: 2025/1/12 author: cmdragon excer ...

  2. asp.net core 3.x 通用主机是如何承载asp.net core的-中

    便于理解直接录制视频了 必备知识: 依赖注入.配置系统.选项模式.推荐参考:A大博客 通用主机(参考:https://www.cnblogs.com/jionsoft/p/12154519.html) ...

  3. w3cschool-Bootstrap 教程

    Bootstrap 简介 什么是 Bootstrap? Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的 ...

  4. C# Caching---Cache 缓存

    1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 usin ...

  5. The Communication Complexity of Threshold Private Set Intersection-2019:解读

    记录阅读论文的笔记. 什么是阈值PSI? Alice和Bob当两者的交集大小不小于\(n-t\)时(两者的不同元素的数量不大于阈值\(2t\)时),才会求交集. 所以阈值PSI会分为两步: 1.检测 ...

  6. HBase多租户分组

    一.分组简介 RegionServer Group 通过对 RegionServer 进行分组,不同的 RegionServer 分到不同的组.每个组可以按需挂载不同的表,并且当组内的表发生异常后,R ...

  7. C++代码改造为UTF-8编码问题的总结

    1. 引言 无论是哪个平台哪种编程语言,字符串乱码真是一个让人无语的问题:你说这个问题比较小吧,但是关键时刻来一下真是受不了.解决方式也有很多种,但是与其将编码转换来转换去,不如统一使用同一种编码方式 ...

  8. JUC并发-4.wait和notify以及Atomic原理

    大纲 1.wait()与notify()实现一个简易的内存队列 2.wait()与notify()的底层原理 3.分布式存储系统NameNode机制介绍 4.分布式存储系统的edits log机制介绍 ...

  9. WSL2走主机IP地址代理的方式

    前言 工作需求导致需要使用到WSL2,git的时候出现网络原因无法拉取.故记录一下走完整个WSL2代理的流程 WSL1 和 WSL2 网络的区别 在 WSL1 时代,由于 Linux 子系统和 Win ...

  10. C语言中的*和&符号

    之前对*和&符号一直理解的比较浅显.只知道: *p好像表示的是一个指针: &p表示的是一个地址. 然而这次当遇到了下面这个情况的时候: int a = 10; int *b = &am ...