字符串问题,大家记得模板思路即可,一个类型的题目有很多种。
1. 字符串反转的问题
1.1 反转字符串
题目:LeetCode344:
思路
还是我们常见的双指针问题,
- left字符数组头部指针,right字符数组尾部指针。
- 当left < right,交换元素。
- 当left >= right,反转结束,返回字符数组。
代码
/*** 双指针反转字符串* @param s*/public static void reverseString(char[] s){if (s == null || s.length == 0){return;}int n = s.length;for (int left = 0,right = n - 1; left < right; ++left ,--right){char tmp = s[left];s[left] = s[right];s[right] = tmp;}}
1.2 k个一组反转
题目:LeetCode541
思路
反转每个下表从2k的倍数开始,长度为k的子字符串,若该字符串长度不为k,则反转整个字符串,注意判断字符串长度不为k的时候。
代码
public String reverseK(String s, int k){if (s == null || s.length() == 0){return s;}int n = s.length();char[] arr = s.toCharArray();for (int i = 0; i < n; i+= 2* k) {reverse(arr,i, Math.min(i+k,n)-1);}return new String(arr);}public void reverse(char[] arr ,int left, int right){while (left < right){char tmp = arr[left];arr[left] = arr[right];arr[right] = tmp;++left;--right;}}
1.3 仅仅反转字母
题目:
思路一
分析题目后我们知道,只将字符串反转其他符号位置不变
方法一
第一次遍历将s中的多有字符存入栈中,然后第二次遍历所有字符串,遇到字符串就从栈顶元素弹出元素替换,遇到其他符号直接拼接。
代码一
/*** 使用栈* @param s* @return*/public String reverseOnlyLeeters(String s){Stack<Character> letters = new Stack<>();for (char c :s.toCharArray()) {//c是字符串,则压入if (Character.isLetter(c)){letters.push(c);}}StringBuilder ans = new StringBuilder();for (char c : s.toCharArray()) {//再次遍历,是字符弹栈,不是直接拼接if (Character.isLetter(c)) {ans.append(letters.pop());}else {ans.append(c);}}return ans.toString();}
思路二
方法二双指针
- 左指针首部元素,右指针尾部元素
- 左指针遇到元素交换,右指针遇到元素停止,遇到其他符号移动
代码二
/*** 双指针*/public String reverseOnlyletter2(String s){if (s == null || s.length() == 0){return s;}StringBuilder ans = new StringBuilder();int j = s.length() -1;for (int i = 0; i < s.length(); i++) {//第i位是字符,与j位置字符交换if (Character.isLetter(s.charAt(i))){//是字符停止,不是字符移动while (!Character.isLetter(s.charAt(j)))j--;ans.append(j--);}else {//前面不是字符,不用反转ans.append(s.charAt(i));}}return ans.toString();}
1.4 反转字符串里的单词
题目:LeetCode151
思路一
使用语言提供的方法来解决
- trim(),去掉头部和尾部空格
- split(),按空格分割成数组
- reverse(),将字符串数组反转,每个元素是一个单词
- join(),将字符串数组拼接成一个字符串
代码一
public String reverseWord1(String s){if (s == null || s.length() == 0){return s;}//除去开头和末尾空格s = s.trim();//除去开头和末尾的空白字符作为分割符分割。"s+"匹配多个空白字符List<String> wordlist = Arrays.asList(s.split("\\s+"));Collections.reverse(wordlist);return String.join(" ",wordlist);}
思路二
自己实现上面的方法
1. tirmSpaces(),去掉多余的空白字符,包括开头和结尾
2. reverse(),将每个字符反转,
3. reverseWord(),根据空格反转每个单词
代码二
/*** 手动实现上述功能*/public String reverseWords(String s){StringBuilder sb = tirmSpaces(s);//反转全部字符串reverse(sb,0,s.length()-1);//反转每个单词reverseWord(sb);return sb.toString();}/*** 去除开头和末尾空格,以及多余的空格*/public StringBuilder tirmSpaces(String s){int left = 0,right = s.length() - 1;//去除开头空格while (left <= right && s.charAt(left) == ' '){++left;}//去除末尾空格while (left <= right && s.charAt(right) == ' '){--right;}//去除中间多余的空格StringBuilder sb = new StringBuilder();while (left <= right){char c = s.charAt(left);if (c != ' '){sb.append(c);//只能有一个空格} else if (sb.charAt(sb.length() - 1) != ' ') {sb.append(c);}++left;}return sb;}//反转字符串啊public void reverse(StringBuilder sb, int left, int right){while (left < right){char tmp = sb.charAt(left);sb.setCharAt(left++,sb.charAt(right));sb.setCharAt(right,tmp);}}//反转单词public void reverseWord(StringBuilder sb){int n = sb.length();//start判断单词的首字母,end判断末尾字母int start = 0 ,end = 0;while (start < n){//循环值单词末尾while (end < n && sb.charAt(end) != ' '){++end;}//反转单个单词reverse(sb,start,end-1);//更新start寻找下一个单词start = end + 1;++end;//此时两个指针是重合状态}}