打基础的时候,不要太迷恋于库函数。
题目链接:https://leetcode.cn/problems/reverse-string/description/
双指针交换首尾字符即可
class Solution {
public void reverseString(char[] s) {
int left = 0,right = s.length-1;
// 双指针
while(left<right){
// 交换首尾
char tmp = s[right];
s[right] = s[left];
s[left] = tmp;
left++;
right--;
}
}
}
时间复杂度 O(n)
空间复杂度 O(1)
题目连接:https://leetcode.cn/problems/reverse-string-ii/description/
这道题目其实也是模拟,实现题目中规定的反转规则就可以了。
题目的意思其实概括为 每隔2k个反转前k个,尾数不够k个时候全部反转。题目的含义要理解,没理解题意的话就不好写。
class Solution {
public String reverseStr(String s, int k) {
//题目的意思其实概括为 每隔2k个反转前k个,尾数不够k个时候全部反转
char[] arr = s.toCharArray();
for(int i=0;i<s.length();i+=2*k){
if(s.length()-i<k)
reverseStr(arr,i,s.length()-1);
else
reverseStr(arr,i,i+k-1);
}
return new String(arr);
}
public void reverseStr(char[] ch,int i,int j){
for(;i<j;i++,j--){
char tmp = ch[j];
ch[j] = ch[i];
ch[i] = tmp;
}
}
}
时间复杂度 O(n)
空间复杂度 O(1)
题目连接:https://kamacoder.com/problempage.php?pid=1064
c++中如果想把这道题目做到极致,就不要只用额外的辅助空间了。
不过使用Java刷题,一定要使用辅助空间,因为Java里的string不能修改。
首先扩充数组到每个数字字符替换成 “number” 之后的大小。
例如 字符串 “a5b” 的长度为3,那么 将 数字字符变成字符串 “number” 之后的字符串为 “anumberb” 长度为 8。
然后从后向前替换数字字符,也就是双指针法,过程如下:i指向新长度的末尾,j指向旧长度的末尾。
很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这么做有两个好处:
(1)不用申请新数组。
(2)从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
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 (Character.isDigit(s.charAt(i))) {
sb.append("number");
}else sb.append(s.charAt(i));
}
System.out.println(sb);
}
}
时间复杂度:O(n)
空间复杂度:O(n)
题目连接:https://leetcode.cn/problems/reverse-words-in-a-string/
将整个字符串都反转过来,那么单词的顺序此时就是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,就是我们所要求的。
概括起来,也就是:
(1)移除多余空格
(2)将整个字符串反转
(3)将每个单词反转
举个例子,源字符串为:"the sky is blue "
移除多余空格 : “the sky is blue”
字符串反转:“eulb si yks eht”
单词反转:“blue is sky the”
这样我们就完成了翻转字符串里的单词。
在实现的细节上,单词级别的反转,left跟right都是只遍历了字符串一次,然后reverse反转字符串也是对于每个字符串只处理一次,总体上所有的反转操作加起来也是O(n),而不是O(n^2)
class Solution {
public String reverseWords(String s) {
char[] arr = s.toCharArray();
// 先去掉前导空格 和 尾随的空格
int left = 0, right = s.length()-1;
while(s.charAt(left)==' ') left++;
while(s.charAt(right)==' ') right--;
StringBuffer sb = new StringBuffer();
// 去掉单词中间多余的空格
for(int i=left;i<=right;i++){
if(s.charAt(i)!=' ' || sb.charAt(sb.length()-1) != ' '){
sb.append(s.charAt(i));
}
}
StringBuffer reverseSb = sb.reverse();
// 然后现在的话就是把每个单词给反转了
left = 0; right = 1;
while(left<sb.length()){
while(right<sb.length() && reverseSb.charAt(right)!=' ')
right++;
// 此时right是空格或者边界,反转前面的字符串
reverse(reverseSb,left,right-1);
left = right+1;
right = left+1;
}
return sb.toString();
}
public void reverse(StringBuffer s,int left,int right){
while(left < right){
char tmp = s.charAt(right);
s.setCharAt(right,s.charAt(left));
s.setCharAt(left,tmp);
left++;
right--;
}
}
}
时间复杂度:O(n)
空间复杂度:O(n)
题目连接:https://kamacoder.com/problempage.php?pid=1065
思路就是 通过 整体倒叙,把两段子串顺序颠倒,两个段子串里的的字符在倒叙一把,负负得正,这样就不影响子串里面字符的顺序了。
或者直接截取,拼起来也可以吧。
import java.util.*;
public class Main{
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());
String s = sc.nextLine();
StringBuffer ans = new StringBuffer();
String left = s.substring(0,s.length()-n);
String right = s.substring(s.length()-n,s.length());
ans.append(right);
ans.append(left);
System.out.println(ans.toString());
}
}
时间复杂度:O(n)
空间复杂度:O(n)