学习目标:
1.利用对撞指针反转字符数组
2.反转字符串2
3.替换数字
4.反转字符串中的单词
5.右旋转字符串
1.利用对撞指针反转字符数组
创建两个指针分别从字符数组两端向中间遍历交换,这里用了异或交换,字符交换用异或比较合适,但如果碰到了数据较大的float类型的整形数字,就不能随便用异或交换了,还是老老实实创建变量吧。
class Solution {
public void reverseString(char[] s) {
int l = 0 , r = s.length-1;
while(l<r){
s[l] ^= s[r];
s[r] ^= s[l];
s[l] ^= s[r];
l++;
r--;
}
}
}
2.反转字符串2
第一种自己写的方法:我首先定义了两个指针作为移动窗口的区间,他们的差值是2k,定义循环的次数是数组的长度除于2k,每次循环两个指针都+2k,然后每次在这个区间里面切割字符串并反转,定义res字符串每次处理完区间内的字符串就加进去。
class Solution {
public static String reverseStr(String s, int k) {
int l = 0;
int r = l + 2 * k;
int len = s.length() / (2 * k);
String res = "";
while (len-- > 0) {
String temp = s.substring(l, l + k);
StringBuffer sb = new StringBuffer(temp);
res += sb.reverse() + s.substring(l + k, r);
l += 2 * k;
r += 2 * k;
}
if (s.length() - l < k)
res += new StringBuffer(s.substring(l)).reverse();
else if (s.length() - l < 2 * k && s.length() - l >= k) {
StringBuffer sb = new StringBuffer(s.substring(l, l + k));
res += sb.reverse() + s.substring(l + k);
}
return res;
}
}
自己写的方法非常麻烦,并且很容易就乱,在看了答案的处理方法后,我发现解法1的处理方法和我一样,但是解法二运用对撞指针的解法非常易懂简洁:
答案中的思路是左指针每次走2k,然后前k个互换,如果不够k个就全部互换,Math.min(ch.length - 1, start + k - 1);这句代码非常妙,如果遍历到后面发现k个不够了,那么就将后面所有的数都互换。
class Solution {
public String reverseStr(String s, int k) {
char[] ch = s.toCharArray();
for(int i = 0; i < ch.length; i += 2 * k){
int start = i;
//这里是判断尾数够不够k个来取决end指针的位置
int end = Math.min(ch.length - 1, start + k - 1);
//用异或运算反转
while(start < end){
ch[start] ^= ch[end];
ch[end] ^= ch[start];
ch[start] ^= ch[end];
start++;
end--;
}
}
return new String(ch);
}
}
3.替换数字
在java中这类题较简单,只需要定义一个StringBuffer对象就可以缓冲字符串,只需要判断是不是数字就好了: s.charAt(i) >= '0' && s.charAt(i) <= '9' ,答案不是用这个,但是我用这个比较好理解。
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) >= '0' && s.charAt(i) <= '9') {
sb.append("number");
}else sb.append(s.charAt(i));
}
System.out.println(sb);
}
}
4.反转字符串中的单词
我靠真写的快爆炸了,这题花了有两个小时一直在报错调试。先说说思路是什么样的吧,反转整个字符串,再把每个单词也反转,利用双指针把空格删掉,就可以完成了。
真的好难啊!但是自我感觉比答案写的要好。
class Solution {
public String reverseWords(String s) {
//双指针去空格
char[] chars = s.toCharArray();
StringBuffer res = new StringBuffer();
int fast = 0;
int slow = 0;
while (fast < chars.length) {
if(chars[fast] == ' ') fast++;
else{
if(slow != 0)res.append(' ');
while(fast < chars.length && chars[fast] != ' '){
res.append(chars[fast++]);
slow++;
}
}
}
res.reverse();
int l = 0,r = 0;
while(r <= res.length()){
if(r==res.length() ||res.charAt(r)==' '){
int tempR =r;
while(l < r-1){
char temp = res.charAt(l);
res.setCharAt(l,res.charAt(r-1));
res.setCharAt(r-1,temp);
l++;
r--;
}
l = tempR+1;
r = tempR+1;
}
r++;
}
return res.toString();
}
}
5.右旋转字符串
这道题其实可以用java中的subString方法直接秒掉,但是学一下这题反转字符串的思路,也是先翻转所有,再反转部分,跟上题的思路大差不差。
下面的模板方法区间翻转字符串倒是可以记一下!
class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String s = sc.next();
char[] chars = s.toCharArray();
reverseString(chars,0, chars.length-1);
reverseString(chars,0,n-1);
reverseString(chars,n, chars.length-1);
System.out.println(new String(chars));
}
public static void reverseString(char[] ch, int start, int end) {
while(start < end){
ch[start] ^= ch[end];
ch[end] ^= ch[start];
ch[start] ^= ch[end];
start++;
end--;
}
}
}