StringCompression [source code]
public class StringCompression {
static
/******************************************************************************/
class Solution {
public int compress(char[] chars) {
assert chars.length > 0;
int pStart = 0, pEnd = 0, pStore = 0;
while (pEnd < chars.length) {
// Move pEND to the first position where the current letter (at pSTART) is finished
while (pEnd < chars.length && chars[pEnd] == chars[pStart])
pEnd++;
int len = pEnd - pStart;
// Store this run's letter
chars[pStore++] = chars[pStart];
if (len > 1) {
// this can't be done if len == 1: will possibly overwrite [pEND], which is not processed yet
char[] chsLen = Integer.toString (len).toCharArray ();
// Store the length of this run, digit by digit
for (char c : chsLen)
chars[pStore++] = c;
}
// bring pSTART to speed with pEND: the next run of same letters to process
pStart = pEnd;
}
return pStore;
}
}
/******************************************************************************/
public static void main(String[] args) {
StringCompression.Solution tester = new StringCompression.Solution();
}
}
downvote出奇的多的一个题目, 还没有看出来复杂度在哪里, 准备直接就开始乱写了; 当然这个题目的笨办法就很简单, 直接counts就行了; 但是Follow-Up你准备怎么处理呢? 一个可能的方向是直接在input里面记录counts? 不对, 好像可以用快慢指针的方式来实现;
思路大概是有的, 从一个concrete的例子出发, 开始写算法, 我用的是abbccc
和aaabbbccc
;
写的时候感觉小细节很多的一个算法, 结果写完之后一次AC了, 速度是8ms (41%), 可以接受;
这个题目还是有不少值得学习的地方的, 尤其是三个指针版本的快慢指针算法, 以前其实是没有专门写过的; 不过其实三指针版本本身还是很intuitive的; 另外, 还是强调笔算的重要性, 如果不是自己动笔, 我是没有办法意识到这里两个指针不够的;
editorial里面awice的解法: 10(12)
class Solution {
public int compress(char[] chars) {
int anchor = 0, write = 0;
for (int read = 0; read < chars.length; read++) {
if (read + 1 == chars.length || chars[read + 1] != chars[read]) {
chars[write++] = chars[anchor];
if (read > anchor) {
for (char c: ("" + (read - anchor + 1)).toCharArray()) {
chars[write++] = c;
}
}
anchor = read + 1;
}
}
return write;
}
}
写法上看起来比我的好看, 因为没有两重循环; 但是实际上是类似的; 他的这个算法本质上还是依赖于类似分段算法里面的switch; 我因为不想处理收尾, 所以避免了这个算法;
具体的细节懒得看了, 大概意思应该是知道的; 注意他这里判断的read > anchor
跟我的len > 1
其实是类似的, 因为他这里read记录的其实是一个run最后的一个letter的位置, 而不是下一个run的开头, 所以他这里可以直接用一个>就可以判断了;
discussion基本没有其他什么新奇的解法;
submission的最优解大部分也就都是波动而已;
Problem Description
Given an array of characters, compress it in-place.
The length after compression must always be smaller than or equal to the original array.
Every element of the array should be a character (not int) of length 1.
After you are done modifying the input array in-place, return the new length of the array.
Follow up:
Could you solve it using only O(1) extra space?
Example 1:
Input:
["a","a","b","b","c","c","c"]
Output:
Return 6, and the first 6 characters of the input array should be: ["a","2","b","2","c","3"]
Explanation:
"aa" is replaced by "a2". "bb" is replaced by "b2". "ccc" is replaced by "c3".
Example 2:
Input:
["a"]
Output:
Return 1, and the first 1 characters of the input array should be: ["a"]
Explanation:
Nothing is replaced.
Example 3:
Input:
["a","b","b","b","b","b","b","b","b","b","b","b","b"]
Output:
Return 4, and the first 4 characters of the input array should be: ["a","b","1","2"].
Explanation:
Since the character "a" does not repeat, it is not compressed. "bbbbbbbbbbbb" is replaced by "b12".
Notice each digit has it's own entry in the array.
Note:
- All characters have an ASCII value in [35, 126].
- 1 <= len(chars) <= 1000.
Difficulty:Easy
Total Accepted:8.6K
Total Submissions:23.4K
Contributor:Grain_In_Ear
Companies
microsoftbloombergsnapchatyelpexpediagodaddylyft
Related Topics
string
Similar Questions
Count and SayEncode and Decode StringsDesign Compressed String Iterator
Hint 1
How do you know if you are at the end of a consecutive group of characters?