翻转字符串 & 找到指定的新类型字符
作者:互联网
翻转字符串
《程序员代码面试指南》第84题 P267 难度:士★☆☆☆
太菜了,想半天想不出来额外空间复杂度O(1)的方法。
原问题,先把chas整体逆序,然后再遍历chas找到每一个单词,把每个单词里的字符逆序即可。
public void rotateWord(char[] chas) {
if (chas == null || chas.length == 0) {
return;
}
reverse(chas, 0, chas.length - 1);
int l = -1;
int r = -1;
for (int i = 0; i < chas.length; i++) {
if (chas[i] != ' ') {
l = i == 0 || chas[i - 1] == ' ' ? i : l;
r = i == chas.length - 1 || chas[i + 1] == ' ' ? i : r;
}
if (l != -1 && r != -1) {
reverse(chas, l, r);
l = -1;
r = -1;
}
}
}
public void reverse(char[] chas, int start, int end) {
char tmp = 0;
while (start < end) {
tmp = chas[start];
chas[start] = chas[end];
chas[end] = tmp;
start++;
end--;
}
}
补充问题,方法一,先把chas[0..size-1]部分逆序处理,再把chas[size..N-1]部分逆序处理,最后把chas整体逆序处理即可。
public void rotate1(char[] chas, int size) {
if (chas == null || size <= 0 || size >= chas.length) {
return;
}
reverse(chas, 0, size - 1);
reverse(chas, size, chas.length - 1);
reverse(chas, 0, chas.length - 1);
}
方法二。是我想了一会想出来的方法。核心思想就是对比未交换的左右部分的长度,来进行交换,并且划分下一步要交换的左右部分,直到左右部分长度一样,交换完即完成全部过程。具体举例见书P269,这里不再赘述。
public void rotate2(char[] chas, int size) {
if (chas == null || size <= 0 || size >= chas.length) {
return;
}
int start = 0;
int end = chas.length - 1;
int lpart = size;
int rpart = chas.length - size;
int s = Math.min(lpart, rpart);
int d = lpart - rpart;
while (true) {
exchange(chas, start, end, s);
if (d == 0) {
break;
} else if (d > 0) {
start += s;
lpart = d;
} else {
end -= s;
rpart = -d;
}
s = Math.min(lpart, rpart);
d = lpart - rpart;
}
}
public void exchange(char[] chas, int start, int end, int size) {
int i = end - size + 1;
char tmp = 0;
while (size-- != 0) {
tmp = chas[start];
chas[start] = chas[i];
chas[i] = tmp;
start++;
i++;
}
}
如果每一次左右部分的划分进行M次交换,那么都有M个字符再也不需要移动。而字符数一共为N,所以交换行为最多发生N次。另外,如果某一次划分出的左右部分长度一样,那么交换完成后将不会再有新的划分,因此很多时候交换操作会少于N次。总体上达到了时间复杂度O(N)的要求。
找到指定的新类型字符
题目:找到指定类型的新类型字符
《程序员代码面试指南》第95题 P302 难度:士★☆☆☆
本题比较简单。一个笨方法是从str[0]开始,从左到右依次划分出新类型字符,到k位置就知道指向的新类型字符是什么了。
更快的方法。从k-1位置开始,向左统计连续出现的大写字母的数量记为uNum,遇到小写字母就停止。如果uNum为奇数,str[k-1..k]是被指定的新类型字符。如果uNum为偶数:str[k]为大写字母时为str[k..k+1];str[k]为小写字母时则就是str[k]。
public String pointNewchar(String s, int k) {
if (s == null || s.equals("") || k < 0 || k >= s.length()) {
return "";
}
char[] chas = s.toCharArray();
int uNum = 0;
for (int i = k - 1; i >= 0; i--) {
if (!isUpper(chas[i])) {
break;
}
uNum++;
}
if ((uNum & 1) == 1) {
return s.substring(k - 1, k + 1);
}
if (isUpper(chas[k])) {
return s.substring(k, k + 2);
}
return String.valueOf(chas[k]);
}
public boolean isUpper(char ch) {
return !(ch < 'A' || ch > 'Z');
}
代码写的太优秀了,这个&1用的很妙,还有isUpper方法,学习学习。
标签:字符,end,start,int,chas,length,字符串,翻转,size 来源: https://www.cnblogs.com/CWZhou/p/16198447.html