344.反转字符串建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数
题目链接/文章讲解/视频讲解:代码随想录
如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。
毕竟面试官一定不是考察你对库函数的熟悉程度, 如果使用python和java 的同学更需要注意这一点,因为python、java提供的库函数十分丰富。
如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。
双指针从首尾向中间移动,交换两指针指向的位置的元素,用一个中间值item保存,实现两元素交换。
class Solution {
public void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
while( left < right){
char item = s[left];
s[left] = s[right];
s[right] = item;
left++;
right--;
}
}
}
541. 反转字符串II建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。
题目链接/文章讲解/视频讲解:代码随想录
没做出来,写复杂了,没想到 i += (2 * k)
其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。
所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。
操作字符串或数组时,如果发现让我们一段一段去处理的时候,for循环的i可以成段成段的去跳。
class Solution {
public String reverseStr(String s, int k) {
char[] charset = s.toCharArray();
for(int i = 0; i < charset.length; i += 2*k){
int left = i;
// 判断尾数够不够k个来取决right指针的位置
int right = Math.min(charset.length - 1,i + k - 1);
while( left < right){
char temp = charset[left];
charset[left] = charset[right];
charset[right] = temp;
left++;
right--;
}
}
return new String(charset);
}
}
class Solution {
public String reverseStr(String s, int k) {
char[] charset = s.toCharArray();
// 1. 每隔 2k 个字符的前 k 个字符进行反转
for(int i = 0; i < charset.length; i += 2*k){
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if(i + k <= charset.length){
reverse(charset, i, i + k - 1);
continue;
}
// 3. 剩余字符少于 k 个,则将剩余字符全部反转
reverse(charset, i, charset.length - 1);
}
return new String(charset);
}
private void reverse(char[] charset, int left, int right){
while( left < right){
char temp = charset[left];
charset[left] = charset[right];
charset[right] = temp;
left++;
right--;
}
}
}
剑指Offer 05.替换空格建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。
题目链接/文章讲解:代码随想录
双指针法:
很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这么做有两个好处:
- 不用申请新数组。
- 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
//双指针法
public String replaceSpace(String s) {
if(s == null || s.length() == 0){
return s;
}
//扩充空间,空格数量2倍
StringBuilder str = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if(s.charAt(i) == ' '){
str.append(" ");
}
}
//若是没有空格直接返回
if(str.length() == 0){
return s;
}
//有空格情况 定义两个指针
int left = s.length() - 1;//左指针:指向原始字符串最后一个位置
s += str.toString();
int right = s.length()-1;//右指针:指向扩展字符串的最后一个位置
char[] chars = s.toCharArray();
while(left>=0){
if(chars[left] == ' '){
chars[right--] = '0';
chars[right--] = '2';
chars[right] = '%';
}else{
chars[right] = chars[left];
}
left--;
right--;
}
return new String(chars);
}
数组复制法:
class Solution {
//使用一个新的对象,复制 str,复制的过程对其判断,是空格则替换,否则直接复制,类似于数组复制
public String replaceSpace(String s) {
if(s == null) return null;
//选用 StringBuilder 单线程使用,比较快,选不选都行
StringBuilder sb = new StringBuilder();
//使用 sb 逐个复制 s ,碰到空格则替换,否则直接复制
for(int i = 0; i< s.length(); i++){
if (s.charAt(i) == ' '){
sb.append("%20");
}else{
sb.append(s.charAt(i));
}
}
return sb.toString();
}
}
151.翻转字符串里的单词建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。
题目链接/文章讲解/视频讲解:代码随想录
解题思路:
- 移除多余空格
- 将整个字符串反转
- 将每个单词反转
class Solution {
public String reverseWords(String s) {
char[] chars = s.toCharArray();
// 1.去除首尾以及中间多余空格
int slow = 0;
int size = chars.length;
for(int fast = 0; fast < size; fast++){
if( (chars[fast] != ' ') || (fast > 0 && chars[fast-1] != ' ')){
chars[slow++] = chars[fast];
}
}
if(chars[slow - 1] == ' '){
slow--;
}
size = slow;
// 2.反转整个字符串
reverse(chars, 0, size - 1);
//3.反转各个单词
int temp = 0;
for(int fast = 0; fast < size; fast++){
if(chars[fast] == ' '){
reverse(chars, temp, fast-1);
temp = fast + 1;
}
}
reverse(chars, temp, size-1);
return new String(chars, 0, size);
}
public void reverse(char[] chars, int left, int right){
while(left < right){
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
left++;
right--;
}
}
}
剑指Offer58-II.左旋转字符串建议:题解中的解法如果没接触过的话,应该会想不到
题目链接/文章讲解:代码随想录
这道题目类似上一题翻转字符串里的单词,依然可以通过局部反转+整体反转 达到左旋转的目的。
具体步骤为:
- 反转区间为前n的子串
- 反转区间为n到末尾的子串
- 反转整个字符串
最后就可以达到左旋n的目的,而不用定义新的字符串,完全在本串上操作。
class Solution {
public String reverseLeftWords(String s, int n) {
char[] chars = s.toCharArray();
reverse(chars, 0, n - 1);
reverse(chars, n, chars.length - 1);
reverse(chars, 0, chars.length - 1);
return new String(chars);
}
public void reverse(char[] chars, int left, int right){
while(left < right){
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
left++;
right--;
}
}
}