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; }
|