反转字符串II
题目中看似是三类情况,其实可以合并成两类。
1.每2k个字符反转前k个字符。(如果字符数不足2k但是大于k也一样)
2.字符数不足k个,反转剩余所有字符。
所以方法可以精简为:从初始位置开始,每次反转前k个字符,之后将坐标向后移动2k个位置继续循环,当剩余字符不足k个时,将其剩余字符全部反转。
//leetcode-541
class Solution {
public String reverseStr(String s, int k) {
char []c = s.toCharArray();
for(int l = 0; l < s.length(); l += 2*k){
int r = l + k - 1;
reverse(c, l, Math.min(r, s.length() - 1));
}
return String.valueOf(c);
}
private void reverse(char[] c, int l, int r){
while(l < r){
char ch = c[l];
c[l] = c[r];
c[r] = ch;
l++;
r--;
}
}
}
替换空格
1.普通方法
声明一个新数组,先扫描旧数组判断空格的数量,每一个空格使得新数组长度+2,之后同时扫描两数组,当遇到空格时对新数组进行特殊字符的添加。
//leetcode-剑指Offer.05
class Solution {
public String replaceSpace(String s) {
char []ch = s.toCharArray();
int num = s.length();
for(int i = 0; i < s.length(); i++){
if(ch[i] == ' '){
num += 2;
}
}
char []re = new char[num];
for(int i = 0, j = 0; i < s.length(); i++){
if(ch[i] != ' '){
re[j++] = ch[i];
}
else{
re[j++] = '%';
re[j++] = '2';
re[j++] = '0';
}
}
return String.valueOf(re);
}
}
2.进阶方法
双指针法:此方法的目的是为了降低算法的空间复杂度,本意是将所有操作都集中于原数组,不另外开辟空间,但是java中string类型字符串声明了之后就不能改变,对其修改相当于另外声明了一个新的string类型字符串,所以此优化算法不会缩减空间复杂度。
基本思想:先扫描数组并根据空格的数量将数组延长,之后设置左右两个指针,左指针指向数组原结尾处,右指针指向数组新结尾处,之后两指针同时向左移动,在移动的过程中将左指针指向的值赋给右指针,如果遇到空格就单独让右指针移动并将特殊字符传给其指向。
//leetcode-剑指Offer.05
class Solution {
//因为java中string类型字符串声明了之后就不能改变,所以此优化算法不会缩减空间复杂度
public String replaceSpace(String s) {
StringBuilder str = new StringBuilder();
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == ' '){
str.append(" ");
}
}
//left指向旧字符串末尾
int left = s.length() - 1;
s += str;
//right指向新字符串末尾
int right = s.length() - 1;
char []ch = s.toCharArray();
while(left >= 0){
if(ch[left] != ' '){
ch[right--] = ch[left--];
}
else{
ch[right--] = '0';
ch[right--] = '2';
ch[right--] = '%';
left--;
}
//当left和right相等时其左侧已经没有空格
if(left == right){
break;
}
}
return String.valueOf(ch);
}
}
未完待续。。。