344.反转字符串 leetcode链接
思考
将字符串看作一个数组,我们不难想到在 反转数组 那道题的做法,使用双指针的方法可以在时间复杂度为O(n)空间复杂度为O(1)
代码展示
public void reverseString(char[] s) {
int i;
int j;
char temp;
for (i = 0,j = s.length - 1; i < s.length / 2; i++,j--) {
temp = s[i];
s[i]=s[j];
s[j] = temp;
}
for (int k = 0; k < s.length; k++) {
System.out.print(s[k]+"\t");
}
}
总结
本题考察了对字符串的最基本的翻转操作,并且在后面会常常用到此类操作,应牢记掌握
541. 反转字符串II leetcode链接
思考
本题在上一题反转函数的基础上添加了局部反转的特性即反转的目标变成了不固定的一段子字符串。我们可以通过编写一个方法来解决局部反转的问题,并且要向该方法中传入三个参数,分别为:字符串,起始下标,终止下标。每次满足反转的条件时就进行反转
代码展示
public String reverseStr(String s, int k) {
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i+=2*k) {
if (i + k <= chars.length){
reserve(chars,i,i+k-1);
continue;
}
reserve(chars,i,chars.length - 1);
}
return new String(chars);
}
public void reserve(char[] ch,int i,int j){
char temp;
for (; i < j; i++,j--) {
temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
}
}
总结
本题是在反转链表的基础上加了一个反转的区间,只需做出一个函数完成局部反转,再明确题目要求在什么时候反转即可。在该题中的reserve方法在后续的题目中也会经常充当一个辅助方法的身份,需要熟练掌握
151.翻转字符串里的单词 leetcode链接
思考
先去除去字符串中多余的空格,这里可以使用快慢指针在原数char组上进行修改,使用快指针在前面遍历,如果遇到空格就跳过,如果不是空格并且慢指针没有指在0下标处时,就领慢指针指向的位置的字符变为空格,并让slow++,然后再进入while循环,直到char[fast]为空格,这时跳出while循环,直到遍历完所有单词。在这之后将字符串进行整体的反转,之后再将字符串中的每个单词进行反转,即可得出答案
代码展示
public static String reverseWords(String s) {
String s1 = reserveStr(s); //反转整个字符串
String s2 = removeExtraSpaces(s1); //删去多余的空格
String s3 = reaerveEachWord(s2); //反转每个单词
return s3;
}
public static String removeExtraSpaces(String str){
char[] charArray = str.toCharArray();
int fast = 0;
int slow = 0;
for (; fast < charArray.length; fast++) {
if (charArray[fast]!=' '){
if (slow != 0)
charArray[slow++] = ' ';
//遍历完一个单词
while (fast < charArray.length && charArray[fast] != ' ')
charArray[slow++] = charArray[fast++];
}
}
char[] newChars = new char[slow];
System.arraycopy(charArray, 0, newChars, 0, slow);
return String.valueOf(newChars);
}
public static String reserveStr(String str){
char[] chars = str.toCharArray();
char temp;
int i;
int j;
for (i = 0,j = chars.length - 1; i < chars.length / 2; i++,j--) {
temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
return String.valueOf(chars);
}
public static String reaerveEachWord(String str){
char[] chars = str.toCharArray();
int floag = 0;
for (int i = 0; i <= chars.length; i++) {
if (i == chars.length||chars[i]==' ' ){//此处使用短路或可以避免数组越界异常,判断的顺序不能变
reserve(chars,floag,i - 1);
floag = i + 1;
}
}
return String.valueOf(chars);
}
public static void reserve(char[] ch,int i,int j){
char temp;
for (; i < j; i++,j--) {
temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
}
}
总结
本题中使用到的三个方法都是以前使用过的,尤其是其中反转整个字符串和局部反转字符串在前两题就写过。而快慢指针则在前面的 数组-移除元素 以及 删除链表中倒数第n个节点 中使用过,不难看出,在进行删除元素的时候,考虑快慢指针还是一个不错的选择的
右旋字符串 卡码网链接
思考
可以根据n将字符数组分为两部分,先对字符数组整体进行反转,在对字符串中的两部分分别进行反转,从而得出答案
代码展示
public static String rightTurnString(String str,int num){
String reserveAll = reserveAll(str);
char[] chars = reserveAll.toCharArray();
int start = 0;
for (int i = 0; i <= chars.length; i++) {
if (i == num || i == chars.length){
reserveLocal(chars,start,i - 1);
start = i;
}
}
return String.valueOf(chars);
}
//反转整个字符串
public static String reserveAll(String str){
char[] chars = str.toCharArray();
int i;
int j;
char temp;
for (i = 0,j = chars.length - 1; i < chars.length / 2; i++,j--) {
temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
return String.valueOf(chars);
}
//局部反转
public static void reserveLocal(char[] ch,int start,int end){
char temp;
for (; start < end; start++,end--) {
temp = ch[start];
ch[start] = ch[end];
ch[end] = temp;
}
}
总结
本题的要点在于抓住题中的有效信息从而得出解法,根据本题题干中的后面 k 个字符移到字符串的前面可以推断出本题势必会用到字符串的局部反转,然而仅仅局部反转是不够的,毕竟本题最终将字符串后面的一部分移到前面,这就可以联想到上一题,反转单词,从而得出本题解法,依然是结合字符串的整体反转和局部反转解题。