一、反转字符串(LeetCode344)
class Solution {
public void reverseString(char[] s) {
for(int i = 0,j = s.length - 1;i < j;i++,j--){
char c = s[i];
s[i] = s[j];
s[j] = c;
}
}
}
二、反转字符串||(LeetCode541)
转化为字符数组进行反转,控制好k的位置以及每次的遍历长度
class Solution {
public String reverseStr(String s, int k) {
char[] c = s.toCharArray(); //转化为字符数组
// 1. 每隔 2k 个字符的前 k 个字符进行反转
for(int i = 0;i < c.length;i += 2*k){
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if(i + k <= c.length){
reverse(c,i,i + k - 1);
continue;
}else{
// 3. 剩余字符少于 k 个,则将剩余字符全部反转
reverse(c,i,c.length - 1);
}
}
return new String(c);
}
// 定义翻转函数
public void reverse(char[] c,int m,int n){
for(;m<n;m++,n--){
char a = c[m];
c[m] = c[n];
c[n] = a;
}
}
}
通过StringB利用api进行反转
class Solution {
public String reverseStr(String s, int k) {
StringBuffer res = new StringBuffer();
int length = s.length();
int start = 0;
while (start < length) {
// 找到k处和2k处
StringBuffer temp = new StringBuffer();
// 与length进行判断,如果大于length了,那就将其置为length
int firstK = (start + k > length) ? length : start + k;
int secondK = (start + (2 * k) > length) ? length : start + (2 * k);
//无论start所处位置,至少会反转一次
temp.append(s.substring(start, firstK));
res.append(temp.reverse());
// 如果firstK到secondK之间有元素,这些元素直接放入res里即可。
if (firstK < secondK) { //此时剩余长度一定大于k。
res.append(s.substring(firstK, secondK));
}
start += (2 * k);
}
return res.toString();
}
}
三、替换空格(剑指05)
利用StringBuilder遍历进行复制替换
class Solution {
//使用一个新的对象,复制str,复制的过程对其判断,是空格则替换,否则直接复制,类似于数组复制
public static String replaceSpace(String s) {
if (s == null) {
return null;
}
//选用 StringBuilder 单线程使用,比较快,选不选都行
StringBuilder sb = new StringBuilder();
//使用 sb 逐个复制 s ,碰到空格则替换,否则直接复制
for (int i = 0; i < s.length(); i++) {
//s.charAt(i) 为 char 类型,为了比较需要将其转为和 " " 相同的字符串类型
//if (" ".equals(String.valueOf(s.charAt(i)))){}
if (s.charAt(i) == ' ') {
sb.append("%20");
} else {
sb.append(s.charAt(i));
}
}
return sb.toString();
}
}
使用StringBuilder扩充空间使空格扩为2倍,最后利用双指针从后往前遍历替换空格
class Solution {
public static String replaceSpace(String s) {
if (s == null || s.length() == 0) {
return s;
}
//扩充空间,空格数量2倍
StringBuilder sb = new StringBuilder();
for(int i = 0;i<s.length();i++){
if(s.charAt(i)==' '){
sb.append(" ");
}
}
//若是没有空格直接返回
if(sb.length() == 0){
return s;
}
//有空格情况 定义两个指针
int left = s.length() - 1;
s += sb.toString();
int right = s.length() -1;
char[] c = s.toCharArray();
while(left>=0){
if(c[left] == ' '){
c[right--] = '0';
c[right--] = '2';
c[right] = '%';
}else{
c[right] = c[left];
}
left--;
right--;
}
return new String(c);
}
}
四、反转字符串中的单词(LeetCode151)
先反转整个字符串,在对单词反转移位(此题一刷较难)
class Solution {
/**
* 思路:
* ①反转字符串 "the sky is blue " => " eulb si yks eht"
* ②遍历 " eulb si yks eht",每次先对某个单词进行反转再移位
* 这里以第一个单词进行为演示:" eulb si yks eht" ==反转=> " blue si yks eht" ==移位=> "blue si yks eht"
*/
public void reverse(char[] c,int a,int b){
for(int i=a,j=b;i<j;i++,j--){
char tem = c[i];
c[i] = c[j];
c[j] = tem;
}
}
public String reverseWords(String s) {
//步骤1:字符串整体反转(此时其中的单词也都反转了)
char[] c = s.toCharArray();
reverse(c, 0, s.length() - 1);
int slow = 0;
for(int fast = 0;fast < c.length;fast++){
if (c[fast] == ' ') {
continue;
}
int temp = fast;
while (fast < c.length && c[fast] != ' ') {
fast++;
}
for (int j = temp; j < fast; j++) {
if (j == temp) { //步骤二:二次反转
reverse(c, temp, fast - 1);//对指定范围字符串进行反转,不反转从后往前遍历一个个填充有问题
}
//步骤三:移动操作
c[slow++] = c[j];
if (j == fast - 1) { //遍历结束
//避免越界情况,例如=> "asdasd df f",不加判断最后就会数组越界
if (slow < c.length) {
c[slow++] = ' ';
}
}
}
}
if (slow == 0) {
return "";
} else {
//参数三:以防出现如"asdasd df f"=>"f df asdasd"正好凑满不需要省略空格情况
return new String(c,0,(slow == c.length) && (c[slow - 1] != ' ') ? slow : slow - 1);
}
}
}
此解法用到了双指针以及数组复制(较难,对api不太熟)
class Solution {
//用 char[] 来实现 String 的 removeExtraSpaces,reverse 操作
public String reverseWords(String s) {
char[] chars = s.toCharArray();
//1.去除首尾以及中间多余空格
chars = removeExtraSpaces(chars);
//2.整个字符串反转
reverse(chars, 0, chars.length - 1);
//3.单词反转
reverseEachWord(chars);
return new String(chars);
}
//1.用 快慢指针 去除首尾以及中间多余空格,可参考数组元素移除的题解
public char[] removeExtraSpaces(char[] chars) {
int slow = 0;
for (int fast = 0; fast < chars.length; fast++) {
//先用 fast 移除所有空格
if (chars[fast] != ' ') {
//在用 slow 加空格。 除第一个单词外,单词末尾要加空格
if (slow != 0)
chars[slow++] = ' ';
//fast 遇到空格或遍历到字符串末尾,就证明遍历完一个单词了
while (fast < chars.length && chars[fast] != ' ')
chars[slow++] = chars[fast++];
}
}
//相当于 c++ 里的 resize()
char[] newChars = new char[slow];
System.arraycopy(chars, 0, newChars, 0, slow);
return newChars;
}
//2.双指针实现指定范围内字符串反转,可参考字符串反转题解
public void reverse(char[] chars, int left, int right) {
if (right >= chars.length) {
System.out.println("set a wrong right");
return;
}
//用异或运算反转
while (left < right) {
chars[left] ^= chars[right];//构造 left ^ right 的结果,并放在 left 中
chars[right] ^= chars[left];//将 left ^ right 这一结果再 ^ right ,存入right中,此时 right = left, left = left ^ right
chars[left] ^= chars[right];//left ^ right 的结果再 ^ left ,存入 left 中,此时 right = left, left = right 完成交换
left++;
right--;
}
}
//3.单词反转
public void reverseEachWord(char[] chars) {
int start = 0;
//end <= s.length() 这里的 = ,是为了让 end 永远指向单词末尾后一个位置,这样 reverse 的实参更好设置
for (int end = 0; end <= chars.length; end++) {
// end 每次到单词末尾后的空格或串尾,开始反转单词
if (end == chars.length || chars[end] == ' ') {
reverse(chars, start, end - 1);
start = end + 1;
}
}
}
}
五、左旋转字符串(剑指58)
用字符数组来进行反转操作,先整个字符串反转,再反转前面的,最后反转后面 n 个,关键是要控制好反转位置
//空间复杂度:O(1)。用原始数组来进行反转操作
//思路为:先整个字符串反转,再反转前面的,最后反转后面 n 个
class Solution {
public void reverse(char[] a,int m,int n){
while(n>m){
a[m] ^= a[n];
a[n] ^= a[m];
a[m] ^= a[n];
m++;
n--;
}
}
public String reverseLeftWords(String s, int n) {
char[] c = s.toCharArray();
reverse(c,0,c.length-1);
reverse(c,0,c.length-1-n);
reverse(c,c.length-n,c.length-1);
return new String(c);
}
}
1032

被折叠的 条评论
为什么被折叠?



