还记得之前面试的时候,面试官问过我一个题,就是将一段英文单词逆序输出,类似这样: hello my name is Jack
输出: Jack is name my hello
看了一下网上的实现方式,基本都是一致的,取出单词然后进行重新拼接,但我当时却不是这样实现的,当时面试官要求不能生成新的空间(当然也不是绝对了),意思应该就是不能使用取单词后拼接的方式,然后我用了这种方式来实现的,下面来分享一下:(思路重要,代码次要)
思路:
- 首先将string转换为字符数组。
- 再将字符数组头尾互换,将整个句子翻转,类似变成这样:
kcaJ si eman ym olleh
- 然后循环遍历获取每个单词的头尾索引值,并嵌套一个循环进行单词翻转,类似这样:
kcaJ
->Jack
思路其实蛮简单的,然后面试官说如果中间有很多空格如何处理呢? 我说没关系,可以过滤的,再来看一下代码实现吧:
public class Test {
public static void main(String[] args) {
String test = "hello my name is Jack";
char[] testChars = test.toCharArray();
System.out.println("old is:" + test);
final int len = testChars.length;
for (int i = 0; i < len / 2; i++) {
//句子头尾互换,进行len/2次交互
testChars[len - 1 - i] = (char) (testChars[len - 1 - i] ^ testChars[i]);
testChars[i] = (char) (testChars[len - 1 - i] ^ testChars[i]);
testChars[len - 1 - i] = (char) (testChars[len - 1 - i] ^ testChars[i]);
}
// 交换后的句子:
System.out.println("tmp is:" + new String(testChars));
int start = -1;//每个单词的起始索引
int end = -1;//每个单词的结束索引
for (int i = 0; i < len; i++) {
if (start == -1 && testChars[i] != ' ') {//记住第一个单词的起始索引值
start = i;
}
//当前索引值为空时,单词结束索引为上一个索引值,这里不用考虑上一个是否还是空格
if (testChars[i] == ' ') {
end = i - 1;
} else if (i == len - 1) {//如果是最后一个索引值时,单词结束索引就是结尾字符
end = len - 1;
}
// 判断单词结束索引值符合要求,并且对应的字符不是空字符,则进行单词头尾交换
if (end >= 0 && testChars[end] != ' ') {
System.out.println("start:" + start + " end:" + end);
int wordLen = end - start;
// 单词头尾互换
for (int j = 0; j <= wordLen / 2; j++) {
int first = start + j;
int last = start + wordLen - j;
if (testChars[first] == testChars[last]) {
//如果字符相同不比交换
continue;
}
testChars[first] = (char) (testChars[first] ^ testChars[last]);
testChars[last] = (char) (testChars[first] ^ testChars[last]);
testChars[first] = (char) (testChars[first] ^ testChars[last]);
}
start = -1;
end = -1;
}
}
System.out.println("end is:" + new String(testChars));
}
}
输出结果:
old is:hello my name is Jack
tmp is:kcaJ si eman ym olleh
start:0 end:3
start:5 end:6
start:8 end:11
start:13 end:14
start:16 end:20
end is:Jack is name my hello
很好,完美的解决了此问题~~
不知大家注意上面的^操作没有,这是采用异或的方式进行交换数值,不需要借助临时变量tmp,下面来看一下原理:
现有A、B两个值需要交互,我们可以这样写:
A = A ^ B;
B = A ^ B;
A = A ^ B;
右侧很神奇的一致,为什么就可以成功进行交换呢?这里需要用离散的异或运算就知道了,下面分布解析:
a. A = A ^ B
这个就先记住就行
b. B = A ^ B
将上一步代入可以得到:B = (A ^ B) ^ B
进一步改变: B = A ^ (B ^ B)
大家直到,异或运算,自己异或自己为0,即 A^A = 0
而任何值异或0等于其本身,即 A^0 = A
所以上面的结果就是: B = A ^ 0 = A
这样就顺利的将A的值赋值给B,一次进行替代,第三步将B的值赋值给了A,完成交换了就~