题目一
316. 去除重复字母
给你一个字符串 s
,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
示例 1:
输入:s = “bcabc”
输出:“abc”
示例 2:
输入:s = “cbacdcbc”
输出:“acdb”
提示:
1 <= s.length <= 104
s 由小写英文字母组成
没做出来
官方答案:贪心+单调栈
class Solution {
public String removeDuplicateLetters(String s) {
boolean[] vis = new boolean[26]; // 每个字母只添加一次
int[] num = new int[26]; // 每个单词出现的次数
for (int i = 0; i < s.length(); i++) {
num[s.charAt(i) - 'a']++;
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (!vis[ch - 'a']) { // 判断是否已包含该字母
while (sb.length() > 0 && sb.charAt(sb.length() - 1) > ch) { // 当前一个字母大于当前字母
if (num[sb.charAt(sb.length() - 1) - 'a'] > 0) { // 当前一个字母不止一个时
vis[sb.charAt(sb.length() - 1) - 'a'] = false; // 就把前一个字母给去掉
System.out.println(sb.charAt(sb.length() - 1));
sb.deleteCharAt(sb.length() - 1);
} else {
break;
}
}
vis[ch - 'a'] = true;
sb.append(ch); // 每个字母都会被添加进去
// System.out.println(ch);
}
num[ch - 'a'] -= 1;
}
return sb.toString();
}
}
复杂度分析
时间复杂度:O(N),其中 NN 为字符串长度。代码中虽然有双重循环,但是每个字符至多只会入栈、出栈各一次。
空间复杂度:O(∣Σ∣),其中 Σ 为字符集合,本题中字符均为小写字母,所以∣Σ∣=26。由于栈中的字符不能重复,因此栈中最多只能有 ∣Σ∣ 个字符,另外需要维护两个数组,分别记录每个字符是否出现在栈中以及每个字符的剩余数量。
题目二
5629. 重新格式化电话号码
给你一个字符串形式的电话号码 number 。number 由数字、空格 ’ '、和破折号 ‘-’ 组成。
请你按下述方式重新格式化电话号码。
首先,删除 所有的空格和破折号。
其次,将数组从左到右 每 3 个一组 分块,直到 剩下 4 个或更少数字。剩下的数字将按下述规定再分块:
2 个数字:单个含 2 个数字的块。
3 个数字:单个含 3 个数字的块。
4 个数字:两个分别含 2 个数字的块。
最后用破折号将这些块连接起来。注意,重新格式化过程中 不应该 生成仅含 1 个数字的块,并且 最多 生成两个含 2 个数字的块。
返回格式化后的电话号码。
示例 1:
输入:number = “1-23-45 6”
输出:“123-456”
解释:数字是 “123456”
步骤 1:共有超过 4 个数字,所以先取 3 个数字分为一组。第 1 个块是 “123” 。
步骤 2:剩下 3 个数字,将它们放入单个含 3 个数字的块。第 2 个块是 “456” 。
连接这些块后得到 “123-456” 。
示例 2:
输入:number = “123 4-567”
输出:“123-45-67”
解释:数字是 “1234567”.
步骤 1:共有超过 4 个数字,所以先取 3 个数字分为一组。第 1 个块是 “123” 。
步骤 2:剩下 4 个数字,所以将它们分成两个含 2 个数字的块。这 2 块分别是 “45” 和 “67” 。
连接这些块后得到 “123-45-67” 。
示例 3:
输入:number = “123 4-5678”
输出:“123-456-78”
解释:数字是 “12345678” 。
步骤 1:第 1 个块 “123” 。
步骤 2:第 2 个块 “456” 。
步骤 3:剩下 2 个数字,将它们放入单个含 2 个数字的块。第 3 个块是 “78” 。
连接这些块后得到 “123-456-78” 。
示例 4:
输入:number = “12”
输出:“12”
示例 5:
输入:number = "–17-5 229 35-39475 "
输出:“175-229-353-94-75”
提示:
2 <= number.length <= 100
number 由数字和字符 ‘-’ 及 ’ ’ 组成。
number 中至少含 2 个数字。
我的答案
class Solution {
public String reformatNumber(String number) {
StringBuilder sb = new StringBuilder();
int index = 0;
for(int i = 0;i<number.length();i++) {
if(Character.isDigit(number.charAt(i))) { // 判断是不是字母
sb.append(number.charAt(i)); // 添加进去
index++; // 计数
if(index %3 == 0) sb.append('-'); // 是三的倍数就先添加 - 进 返回字符串中
}
}
if(index%3 == 0) sb.deleteCharAt(sb.length()-1); // 如果是三的倍数,那么只需要将最后一个 - 删掉就可以了
else if(index%3 == 1) { // 如果不是,那么最后四个数字要变成 12 - 34 这样
sb.deleteCharAt(sb.length()-2);
sb.insert(sb.length()-2,'-');
}
return sb.toString();
}
}