0%

LeetCode-Day47

394 字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

示例:

1
2
3
s = "3[a]2[bc]", 返回 "aaabcbc".
s = "3[a2[c]]", 返回 "accaccacc".
s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".

思路:

记住!凡是括号匹配的问题就用来解决!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
string decodeString(string s) {
stack<string> strstack;
stack<int> numstack;
int n = s.size();
strstack.push("");
int num = 0;
for(int i = 0; i < n; i++) {
if(isalpha(s[i])) {
strstack.top() += s[i];
} else if(isdigit(s[i])) {
num = num * 10 + s[i] - '0';
} else if(s[i] == '[') {
numstack.push(num);
num = 0;
strstack.push("");
} else if(s[i] == ']') {
string temp = strstack.top();
int times = numstack.top();
numstack.pop();
for(int i = 1; i < times; i++) {
strstack.top() += temp;
}
temp = strstack.top();
strstack.pop();
strstack.top() += temp;
}
}
return strstack.top();
}

395 至少有K个重复字符的最长子串

找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。

示例 :

1
2
3
4
5
6
7
8
9
10
11
输入:
s = "aaabb", k = 3
输出:
3
最长子串为 "aaa" ,其中 'a' 重复了 3 次。

输入:
s = "ababbc", k = 2
输出:
5
最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次。

思路:分治法

先用map存每个字符出现的数量

  • 当一个字符出现的次数小于k时,该字符肯定不会出现在某个满足条件的子串中,即该字符可以把字符串分割
  • 使用两个指针,第一个指针指向当前出现次数大于等于k的位置,第二个指针往后移动到后面第一个出现次数小于k的位置,那么中间这部分子串可能是一个结果,递归该子串求结果
  • 找到一个可能子串之后,第一个指针指向第二个指针的后一个位置,继续找下一个子串,知道找到字符串s的结尾
  • 不断递归找到所有可能结果中满足条件的最大值返回即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void substring(string s, int l, int r, int k, int& maxL) {
if(r - l < k) {
return ;
}
map<char, int> m;
for(int i = l; i < r; i++) {
m[s[i]]++;
}
int left = l;
bool flag = false;
for(int i = l; i < r; i++) {
if(m[s[i]] < k) {
substring(s, left, i, k, maxL);
flag = true;
left = i + 1;
}
}
if(!flag) {
maxL = max(maxL, r - l);
} else {
substring(s, left, r, k, maxL);
}
}

396 旋转函数

给定一个长度为 n 的整数数组 A 。

假设 Bk 是数组 A 顺时针旋转 k 个位置后的数组,我们定义 A 的“旋转函数” F 为:

F(k) = 0 * Bk[0] + 1 * Bk[1] + ... + (n-1) * Bk[n-1]

计算F(0), F(1), ..., F(n-1)中的最大值。

注意:
可以认为 n 的值小于 105。

示例:

1
2
3
4
5
6
7
8
A = [4, 3, 2, 6]

F(0) = (0 * 4) + (1 * 3) + (2 * 2) + (3 * 6) = 0 + 3 + 4 + 18 = 25
F(1) = (0 * 6) + (1 * 4) + (2 * 3) + (3 * 2) = 0 + 4 + 6 + 6 = 16
F(2) = (0 * 2) + (1 * 6) + (2 * 4) + (3 * 3) = 0 + 6 + 8 + 9 = 23
F(3) = (0 * 3) + (1 * 2) + (2 * 6) + (3 * 4) = 0 + 2 + 12 + 12 = 26

所以 F(0), F(1), F(2), F(3) 中的最大值是 F(3) = 26 。

思路:错位相减,记得手推一下公式

推导过程:

  • (1)F(k) = 0 * Bk[0] + 1 * Bk[1] + … + (n-2) * Bk[n-2] + (n-1) * Bk[n-1]
  • (2)F(k+1) = 0 * Bk[n-1] + 1 * Bk[0] + 2 * Bk[2] + … + (n-1) * Bk[n-2]
  • (2)-(1)得:F(k+1) - F(k) = (Bk[0] + Bk[1] + ... + Bk[n-2]) - (n-1)*Bk[n-1]
    可得:F(k+1) - F(k) = (Bk[0] + Bk[1] + ... + Bk[n-2] + Bk[n-1]) - n*Bk[n-1]
    S=Sum{Bk}
    有:F(k+1) = F(k) + S - n * Bk[n-1]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
typedef long long ll;
int maxRotateFunction(vector<int>& A) {
int n = A.size();
ll sum = 0, maxSum = 0;
if(n <= 1) {
return 0;
}
for(int i = 0;i < n; i++) {
sum += A[i];
maxSum += (i * A[i]);
}
ll tempSum = maxSum;
for(int i = 1; i < n; i++) {
tempSum += (n * A[i - 1] - sum);
maxSum = max(maxSum, tempSum);
}
return maxSum;
}