题目: 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s
的形式给出。
不要给另外的数组分配额外的空间,你必须**原地修改输入数组**、使用 O(1) 的额外空间解决这一问题。
思路: 在刷题的时候,尽量不要使用例如reverse这种可以直接完成题目要求的函数,就没有了做题的意义。这道题比较简单,让首尾的元素交换即可,我们可以是用双指针。因为数组的长度是固定的,使用一个头指针就可以,可以根据头指针的位置计算出尾指针的位置。
代码:
class Solution {
public void reverseString(char[] s) {
for(int i = 0; i < s.length / 2; i++){
char tmp = s[i];
s[i] = s[s.length - i - 1];
s[s.length - i - 1] = tmp;
}
}
}
时间复杂度O(n),空间复杂度O(1)
题目: 给定一个字符串 s
和一个整数 k
,从字符串开头算起,每计数至 2k
个字符,就反转这 2k
字符中的前 k
个字符。
k
个,则将剩余字符全部反转。2k
但大于或等于 k
个,则反转前 k
个字符,其余字符保持原样。思路: 前2k个字符串反转前k个字符,很容易想到使用计数器记录字符串的个数,实际上只需要在for循环的时候每次都累加2k即可,然后为了防止索引溢出,每次都要和字符串长度比较一下,然后再反转。
代码:
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;
int end = Math.min(ch.length - 1, start + k - 1);
while(start < end){
char tmp = ch[start];
ch[start] = ch[end];
ch[end] = tmp;
start++;
end--;
}
}
return new String(ch);
}
}
时间复杂度O(n)
题目: 请实现一个函数,把字符串 s
中的每个空格替换成"%20"。
思路: 这道题可以直接将空格替换成20%,我们想要掌握这道题的精髓,可以使用双指针的方法。首先遍历原字符串,遇到空格在末尾添加两个空格占位,然后左指针指向原字符串末尾位置,右指针指向扩容之后的字符串的末尾位置,然后左指针向左遍历,如果遇到空格,右指针一次向左增加0,2,%,如果左指针指向的内容不是空格,右指针的内容改为左指针的内容。因为要对字符串的内容进行增加,所以不能从左向右遍历,那样的时间复杂度为O(n^2)。(图片来源:代码随想录)
注意在java的操作中,不能直接对字符串操作,要将字符串转化为char数组进行操作。
代码:
class Solution {
public String replaceSpace(String s) {
if(s == null) return s;
StringBuffer str = new StringBuffer(s);
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == ' '){
str.append(" ");
}
}
if(s.length() == str.length()) return s;
int left = s.length() - 1, right = str.length() - 1;
char[] ch = str.toString().toCharArray();
while(left >= 0){
if(ch[left] == ' '){
ch[right--] = '0';
ch[right--] = '2';
ch[right--] = '%';
}else{
ch[right--] = ch[left];
}
left--;
}
return new String(ch);
}
}
时间复杂度O(n)
题目: 给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意: 输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
思路: 不适用java的内置函数操作。分为以下几步:
代码:
class Solution {
public String reverseWords(String s) {
StringBuffer str = new StringBuffer();
//去除多余的空格
int left = 0, right = s.length() - 1;
while(s.charAt(left) == ' ' && left <= right) left++;
while(s.charAt(right) == ' ' && right >= left) right--;
while(left <= right){
if(left > 0 && s.charAt(left) == ' ' && s.charAt(left - 1) == ' ') left++;
else {
str.append(s.charAt(left));
left++;
}
}
if(str.length() == 0) return str.toString();
//反转字符串
char[] ch = str.toString().toCharArray();
int start = 0, end = 0;
for(int i = 0; i < ch.length; i++){
if(i == ch.length - 1 || ch[i + 1] == ' '){
end = i;
while(start <= end){
char tmp = ch[start];
ch[start] = ch[end];
ch[end] = tmp;
start++;
end--;
}
start = i + 2;
}
}
start = 0;
end = ch.length - 1;
while(start <= end){
char tmp = ch[start];
ch[start] = ch[end];
ch[end] = tmp;
start++;
end--;
}
return new String(ch);
}
}
时间复杂度O(n)
题目: 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
思路: 1. 拼接一个s到末尾,返回s+s的(n,len+n部分)
代码:
class Solution {
public String reverseLeftWords(String s, int n) {
String str = s + s;
return str.substring(n, s.length() + n);
}
}
class Solution {
public String reverseLeftWords(String s, int n) {
char[] ch = s.toCharArray();
//反转区间(,n)和(n,)
int left = 0, right = n - 1;
while(left <= right){
char tmp = ch[left];
ch[left++] = ch[right];
ch[right--] = tmp;
}
left = n;
right = ch.length - 1;
while(left <= right){
char tmp = ch[left];
ch[left++] = ch[right];
ch[right--] = tmp;
}
left = 0;
right = ch.length - 1;
while(left <= right){
char tmp = ch[left];
ch[left++] = ch[right];
ch[right--] = tmp;
}
return new String(ch);
}
}
时间复杂度O(n)