左右字符串交换
题目描述
给定一个字符串str和长度leftsize,请把str左侧leftsize的部分和右部分做整体交换。要求额外空间复杂度 O ( 1 ) O(1) O(1)。
进阶:如果交换代价很昂贵,有没有更好一些方法。
示例1
输入:abcdefg leftsize=3
返回值:defgabc
解题思路一
- 左边字符串逆序
- 右边字符串逆序
- 字符串整体逆序
原字符串:abcdefg
左边字符串逆序:cbadefg
右边字符串逆序:cbagfed
整体逆序:defgabc
代码如下:
//解法一:三次逆序
public static String change(char[] str, int lSize){
int length = str.length;
//左边字符串逆序,右边字符串逆序,然后整体逆序
//就可以实现左边字符串与右边字符串交换位置
reverse(str, 0, lSize-1);
reverse(str, lSize, length-1);
reverse(str, 0, length-1);
return new String(str);
}
public static void reverse(char[] str, int start, int end){
while (start < end){
char temp = str[start];
str[start++] = str[end];
str[end--] = temp;
}
}
解题思路二
先判断两边字符串大小,将字符串交换位置,交换后长度小的字符串就固定位置,
然后长度大的字符串重新划分左右字符,并按上的方法交换,
当左边字符长度等于右边字符长度,两边整体交换程序结束。
原字符串:abcdefg
第一次交换:(efgd)abc
第二次交换:(d)fge(abc)
第三次交换:(de)gf(abc)
第四次交换(左边字符串等于右边字符串):defgabc
与解法一对比,coding难很多,但是整体的比较次数要更少,适合交换代价很昂贵的一些场景
代码如下:
//解法二:
public static String change2(char[] str, int lSize){
int L = 0;
int R = str.length - 1;
//左边字符串长度
int lPart = lSize;
//右边字符串长度
int rPart = str.length - lPart;
//左右字符串中较小字符串的长度
int same = Math.min(lPart, rPart);
//左边字符串与右边字符串长度差
int diff = lPart - rPart;
exchange(str, L, R, same);
while(diff != 0){
if (diff < 0){
//左边字符串长度小于右边,此时交换完左边固定same长度字符
R -= same;
rPart = -diff;
}else {
//此时左边字符串大于右边,此时交换完右边固定same长度字符
L += same;
lPart = diff;
}
same = Math.min(lPart, rPart);
//当diff=0时,说明左边的字符和右边的字符长度相同,此时只需要将左边字符和右边字符进行整体交换变完成
//最坏情况就是当diff=0时,左边字符和右边字符长度都为1
diff = lPart - rPart;
exchange(str, L, R, same);
}
return new String(str);
}
//str[L...]数出size大小和str[...R]输出size大小出来进行交换
private static void exchange(char[] str, int L, int R, int size) {
//确定右边字符开始交换的位置
int i = R - size + 1;
char temp = 0;
while (size-- != 0){
temp = str[L];
str[L++] = str[i];
str[i++] = temp;
}
}
main测试代码
public static void main(String[] args) {
String arr = "abcdefg";
//String change = change(arr.toCharArray(), 3);
String change = change2(arr.toCharArray(), 3);
System.out.println(change);
}