Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 76f850e

Browse files
author
zhangxing
committed
feat: 新增 删除重复字母
1 parent 667eb04 commit 76f850e

File tree

5 files changed

+160
-28
lines changed

5 files changed

+160
-28
lines changed

‎删除回文子序列.js‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// 给你一个字符串 s,它仅由字母 'a' 和 'b' 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。
2+
3+
// 返回删除给定字符串中所有字符(字符串为空)的最小删除次数。
4+
5+
// 「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。
6+
7+
// 「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。
8+
9+
// 示例 1:
10+
// 输入:s = "ababa"
11+
// 输出:1
12+
// 解释:字符串本身就是回文序列,只需要删除一次。
13+
14+
// 示例 2:
15+
// 输入:s = "abb"
16+
// 输出:2
17+
// 解释:"abb" -> "bb" -> "".
18+
// 先删除回文子序列 "a",然后再删除 "bb"。
19+
20+
// 示例 3:
21+
// 输入:s = "baabb"
22+
// 输出:2
23+
// 解释:"baabb" -> "b" -> "".
24+
// 先删除回文子序列 "baab",然后再删除 "b"。
25+
26+
// 提示:
27+
// 1 <= s.length <= 1000
28+
// s 仅包含字母 'a' 和 'b'
29+
30+
// 如果是每次需要删除连续回文子串而不是回文序列, 也不限定是a和b
31+
// 要求最小删除次数,那么就需要从最长的回文字符串开始 n -> n-1 -> n-2 -> ...
32+
const isPalind = (s) => {
33+
return s === s.split('').reverse().join('');
34+
};
35+
36+
var removePalindromeSub = function (s) {
37+
const n = s.length;
38+
39+
if (!n) return 0;
40+
41+
// 长度为n
42+
if (isPalind(s) || n === 1) return 1;
43+
44+
// 初始从长度为 n - 1开始;
45+
let dis = n - 1,
46+
start = 0,
47+
end = dis + start - 1, // end - start + 1 = dis -> end = dis + start - 1
48+
count = 0;
49+
50+
// 从长度n-1开始循环
51+
while (start <= end && dis > 0) {
52+
let target = s.slice(start, end + 1); // 要包含end
53+
console.log(dis, target, isPalind(target));
54+
// 如果是回文字符串就处理剩下的字符串
55+
if (isPalind(target)) {
56+
const left = s.slice(0, start);
57+
const right = s.slice(end + 1);
58+
count = 1 + removePalindromeSub(left) + removePalindromeSub(right);
59+
break;
60+
}
61+
start++;
62+
// 长度为dis情况下已经遍历结束了, 该遍历长度为dis-1
63+
if (end > n - 1) {
64+
dis--;
65+
start = 0;
66+
}
67+
end = dis + start - 1;
68+
}
69+
return count;
70+
};
71+
72+
console.log(removePalindromeSub('abbbbaaacccda'));

‎删除重复字母.js‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// 给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
2+
3+
// 示例 1:
4+
// 输入:s = "bcabc"
5+
// 输出:"abc"
6+
7+
// 示例 2:
8+
// 输入:s = "cbacdcbc"
9+
// 输出:"acdb"
10+
11+
// 提示:
12+
// 1 <= s.length <= 104
13+
// s 由小写英文字母组成
14+
15+
/**
16+
* 思路:后来的先匹配考虑用栈
17+
* 1. 找到重复的字符
18+
* 2. 原字符串依次入栈,入栈时判断当前字符和栈顶字符的字典排序大小,如果小于并且栈顶元素是重复元素则栈顶元素出栈, 需要注意因为重复而出栈的次数是有限的,否则一些大的重复的字母就可能一直不能入栈。
19+
* @param {*} s
20+
*/
21+
var removeDuplicateLetters = function (s) {
22+
if (!s.length) {
23+
return false;
24+
}
25+
26+
// 找到重复的字符
27+
const repeatCharacters = s
28+
.split('')
29+
.filter((item, index, arr) => index !== arr.indexOf(item));
30+
31+
const arr = [s[0]];
32+
for (let i = 1; i < s.length; i++) {
33+
if (!arr.includes(s[i])) {
34+
let top = arr[arr.length - 1];
35+
// 循环判断栈顶元素和当前元素的关系
36+
// repeatCharacters.includes(top)为true表明这次可以删除,因为后面还会遇到
37+
while (
38+
top &&
39+
s[i].charCodeAt(0) < top.charCodeAt(0) &&
40+
repeatCharacters.includes(top)
41+
) {
42+
arr.pop();
43+
// 移除该重复元素, 防止多删
44+
repeatCharacters.splice(repeatCharacters.indexOf(top), 1);
45+
top = arr[arr.length - 1];
46+
}
47+
arr.push(s[i]);
48+
} else {
49+
// 已经在单调栈中存在的元素不入栈并且需要把该重复元素移除,防止后面多删
50+
repeatCharacters.splice(repeatCharacters.indexOf(s[i]), 1);
51+
}
52+
}
53+
return arr.join('');
54+
};
55+
console.log(removeDuplicateLetters('bbcaac')); // b -> c -> a -> pop c -> b不能删 ->
56+
console.log(removeDuplicateLetters('cbacdcbc'));

‎千位分隔符.js‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,15 @@ var thousandSeparator2 = function (n) {
3737
let count = 0;
3838
let ans = '';
3939
do {
40-
let cur = n % 10; // 最后一位
40+
let cur = n % 10; // 取最后一位
4141
n = Math.floor(n / 10); // 取整数部分
42-
ans += cur.toString(); // "432"
42+
ans += cur.toString(); // "432", 从最低位到最高位处理所以这里是倒序
4343
++count;
4444
if (count % 3 === 0 && n) {
4545
ans += '.'; // "432."
4646
}
4747
} while (n);
48+
console.log(ans);
4849
return ans.split('').reverse().join('');
4950
};
51+
console.log(thousandSeparator2(123456789));

‎有多少小于当前数字的数字.js‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,24 @@ console.log(smallerNumbersThanCurrent([8, 1, 2, 2, 3]));
7676
//对数组进行排序,并记录每一个数在原数组中的位置。对于排序后的数组中每一个数,我们找出其左侧第一个小于它的数,这样就能够知道数组中小于该数字的数量
7777
var smallerNumbersThanCurrent2 = function (nums) {
7878
const n = nums.length;
79+
7980
// [[0, 0], [0, 0], ...]
8081
// 记录原索引和值
8182
const data = new Array(n).fill(0).map((v) => new Array(2).fill(0));
8283
for (let i = 0; i < n; ++i) {
8384
data[i][0] = nums[i];
8485
data[i][1] = i;
8586
}
87+
88+
// 按照从小到大排序
8689
data.sort((a, b) => a[0] - b[0]);
90+
8791
const ret = new Array(n);
92+
8893
let prev = -1;
8994
for (let i = 0; i < n; ++i) {
9095
// [1,2,2,3,8]
91-
// 使用prev来越过重复元素, 比如第二个2和第一个2重复,那么就取上一次的pre,也就是取第一个2满足条件的pre
96+
// 注意重复元素的判断,只有当值变化的时候才去更新 prev
9297
if (prev == -1 || data[i][0] !== data[i - 1][0]) {
9398
prev = i;
9499
}

‎栈和队列/LeetCode 1249. 移除无效的括号.md‎

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL2Nob2NvbGF0ZTE5OTkvY2RuL2ltZy8yMDIwMDgyODE0NTUyMS5qcGc?x-oss-process=image/format,png)
2-
>仰望星空的人,不应该被嘲笑
2+
3+
> 仰望星空的人,不应该被嘲笑
34
45
## 题目描述
6+
57
给你一个由` '('``')'` 和小写字母组成的字符串 `s`
68

79
你需要从字符串中删除最少数目的 `'('` 或者 `')' `(可以删除任意位置的括号),使得剩下的「括号字符串」有效。
@@ -13,7 +15,6 @@
1315
空字符串或只包含小写字母的字符串
1416
可以被写作 `AB`(A 连接 B)的字符串,其中 `A``B` 都是有效「括号字符串」
1517
可以被写作 (A) 的字符串,其中 `A` 是一个有效的「括号字符串」
16-
1718

1819
示例 1:
1920

@@ -45,8 +46,6 @@
4546
输出:"a(b(c)d)"
4647
```
4748

48-
49-
5049
提示:
5150

5251
```javascript
@@ -58,8 +57,8 @@ s[i] 可能是 '('、')' 或英文小写字母
5857
链接:https://leetcode-cn.com/problems/minimum-remove-to-make-valid-parentheses
5958
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
6059

61-
6260
## 解题思路
61+
6362
一开始我是想着只要对应括号匹配就好了,将多余的右括号删掉,但是这个样例 `))((` 不可能过的,因为左括号也可以不匹配呀。于是我想着将括号对应字符串索引存起来,起初我们可以将不匹配的右括号还是按原来方法删掉就好了,匹配一个就删掉一个对应左括号的索引值,最后多出来的索引值全删掉就好了,这样就不会出现左括号还余留的情况。
6463

6564
这里提示一下:不要用 `splice`去删除指定下标的元素,`splice`会改变原数组长度,而你原本存的下标是基于原数组的。
@@ -68,30 +67,29 @@ s[i] 可能是 '('、')' 或英文小写字母
6867
最后通过 `res.join('')` 方法,将数组转换成我们最后要的字符串即可。
6968

7069
```javascript
71-
var minRemoveToMakeValid = function(s) {
72-
let res = [...s]
73-
let stack = []
74-
for(let i=-0;i<s.length;i++){
75-
let ch = s[i]
76-
if(ch === '('){
77-
stack.push(i)
78-
}else if(ch === ')'){
79-
if(stack.length) stack.pop()
80-
else delete(res[i])
81-
}
70+
var minRemoveToMakeValid = function (s) {
71+
let res = [...s];
72+
let stack = [];
73+
for (let i = -0; i < s.length; i++) {
74+
let ch = s[i];
75+
if (ch === '(') {
76+
stack.push(i);
77+
} else if (ch === ')') {
78+
if (stack.length) stack.pop();
79+
else delete res[i];
8280
}
83-
while(stack.length){
84-
let idx = stack.pop()
85-
delete(res[idx])
86-
}
87-
res = res.filter(item=>item)
88-
return res.join('')
81+
}
82+
while (stack.length) {
83+
let idx = stack.pop();
84+
delete res[idx];
85+
}
86+
res = res.filter((item) => item);
87+
return res.join('');
8988
};
9089
```
9190

92-
93-
9491
## 最后
92+
9593
文章产出不易,还望各位小伙伴们支持一波!
9694

9795
往期精选:
@@ -105,4 +103,3 @@ var minRemoveToMakeValid = function(s) {
105103
```javascript
106104
学如逆水行舟,不进则退
107105
```
108-

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /