[LeetCode1544题 - 整理字符串] | 刷题打卡

116 阅读1分钟

掘金团队号上线,助你 Offer 临门! 点击 查看详情

前言

最近几天没逛掘金,也没有任何知识上的输出。今天刚上就看到掘金又发起了每日刷题打卡的活动。正好这几天手很颓。先做一个简单题来寻找一下状态。

题目描述

给你一个由大小写英文字母组成的字符串 s 。

一个整理好的字符串中,两个相邻字符 s[i] 和 s[i+1],其中 0<= i <= s.length-2 ,要满足如下条件:

若 s[i] 是小写字符,则 s[i+1] 不可以是相同的大写字符。 若 s[i] 是大写字符,则 s[i+1] 不可以是相同的小写字符。 请你将字符串整理好,每次你都可以从字符串中选出满足上述条件的 两个相邻 字符并删除,直到字符串整理好为止。

请返回整理好的 字符串 。题目保证在给出的约束条件下,测试样例对应的答案是唯一的。

注意:空字符串也属于整理好的字符串,尽管其中没有任何字符。

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/ma… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例 1:

输入:s = "leEeetcode"
输出:"leetcode"
解释:无论你第一次选的是 i = 1 还是 i = 2,都会使 "leEeetcode" 缩减为 "leetcode"

示例 2:

输入:s = "abBAcC"
输出:""
解释:存在多种不同情况,但所有的情况都会导致相同的结果。例如:
"abBAcC" --> "aAcC" --> "cC" --> ""
"abBAcC" --> "abBA" --> "aA" --> ""

示例 3:

输入:s = "s"
输出:"s"

提示:

  • 1 <= s.length <= 100
  • s 只包含小写和大写英文字母

解题思路

看到这个题目,最直接想到的暴力解法就是依次遍历,如果出现坐标 i 满足上述述场景就跳过当前元素和下一个元素。否则拼接当前字符。如果遍历结束,拼接后的字符串长度仍然等于当前长度。说明没有任何元素满足上述场景。直接返回该字符串。否则仍然执行该逻辑。

很明显的一个递归逻辑。直接看一下暴力解的代码,遍历的之后因为后面要判断下一个元素,防止下标越界可以先判断一下当前下标是不是最后一个下标,如果是最后一个下标就直接拼接当前元素。因为后面没有元素,显然也就不满足这种场景。

class Solution {
    public String makeGood(String s) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            if(i==s.length()-1){
                stringBuilder.append(s.charAt(i));
            }
            else if (Character.isUpperCase(s.charAt(i)) && !Character.isUpperCase(s.charAt(i + 1)) && Character.toLowerCase(s.charAt(i)) == s.charAt(i + 1)) {
                i += 1;
            } else if (!Character.isUpperCase(s.charAt(i)) && Character.isUpperCase(s.charAt(i + 1)) && Character.toUpperCase(s.charAt(i)) == s.charAt(i + 1)) {
                i += 1;
            } else {
                stringBuilder.append(s.charAt(i));
            }
        }
        //递归处理
        return s.length() == stringBuilder.length() ? s : makeGood(stringBuilder.toString());
    }
}

递归的内存消耗和时间复杂度无疑非常令人痛苦,那就接着考虑一下这题有没有更优雅一点的实现方案。在依次遍历输入字符串 s 的时候,如果不满足要求场景,选择拼接字符串。 如图所示:

未命名文件 (2).png 这是新串的 b 与老串的 B 满足场景,弹出新串最后一个元素(栈顶元素),老串顺移下标。此时新串的栈顶 a 与老串的 A 仍满足场景,弹出 a 元素,遍历老串的下标再次+1。当新串栈顶与老串当前字符不满足场景时。新串入栈老串的当前字符。这种做法时间复杂度只有 O(n) 。而且省去了递归造成的栈内存损耗。

未命名文件 (3).png

最终代码

class Solution {
    public String makeGood(String s) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            if (stringBuilder.length() > 0 && Character.toLowerCase(stringBuilder.charAt(stringBuilder.length()-1)) == Character.toLowerCase(s.charAt(i)) && stringBuilder.charAt(stringBuilder.length()-1) != s.charAt(i)) {
                stringBuilder.deleteCharAt(stringBuilder.length()-1);
            } else {
                stringBuilder.append(s.charAt(i));
            }
        }
        return stringBuilder.toString();
    }
}

总结

今天打卡第一天,先做一题激励一下自己,先给自己定个小目标,完成4月份每日打卡。

本文正在参与「掘金 2021 4 月刷题打卡」, 点击查看 活动详情