今日题目链接:左旋转字符串
左旋转字符串
难度:中等
描述
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列 S ,请你把其循环左移 K 位后的序列输出。例如,字符序列 S = "abcXYZdef" , 要求输出循环左移 3 位后的结果,即 "XYZdefabc"
举例
解题思路
方法一:遍历拼接;既然循环左移是前面n个字符平移到了最后,我们就可以分开加入字符串中,先挨个加入后面部分字符,然后再回过头加入前面的字符。但需要注意的是需要进行取余;
方法二:三次反转;循环左移相当于从第n个位置开始,左右两部分视作整体翻转。即abcdefg左移3位defgabc可以看成AB翻转成BA(这里小写字母看成字符元素,大写字母看成整体)。既然是翻转我们就可以用到reverse函数。
实现代码(java)
方法一:
java
import java.util.*;
public class Solution {
public String LeftRotateString(String str,int n) {
//取余,因为每次长度为n的旋转数组相当于没有变化
if(str.isEmpty() || str.length() == 0)
return "";
int m = str.length();
//取余,因为每次长度为m的旋转数组相当于没有变化
n = n % m;
StringBuilder res = new StringBuilder();
//先遍历后面的,放到前面
for(int i = n; i < m; i++)
res.append(str.charAt(i));
//再遍历前面的放到后面
for(int i = 0; i < n; i++)
res.append(str.charAt(i));
return res.toString();
}
}
方法二:
java
public class Solution {
public String LeftRotateString(String str,int n) {
//取余,因为每次长度为n的旋转数组相当于没有变化
if(str.isEmpty() || str.length() == 0)
return "";
int m = str.length();
n = n % m;
//第一次逆转全部元素
char[] s = str.toCharArray();
reverse(s, 0, m - 1);
//第二次只逆转开头m个
reverse(s, 0, m - n - 1);
//第三次只逆转结尾m个
reverse(s, m - n, m - 1);
return new String(s);
}
//反转函数
private void reverse(char[] s, int start, int end){
while(start < end){
swap(s, start++, end--);
}
}
//交换函数
private void swap(char[] s, int a, int b){
char temp = s[a];
s[a] = s[b];
s[b] = temp;
}
}
学习完本题的思路你可以解决如下题目:
替换空格
难度:简单
描述
请实现一个函数,将一个字符串s中的每个空格替换成"%20"。
例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
举例
解题思路
方法一:和上面题目一样可以使用StringBuilder,把字符串中的每个字符一个个添加到StringBuilder中,如果遇到空格就把他换成%20。
方法二:先将字符串转换为单个字符,申请一个临时数组,然后再遍历这个字符串的每个字符,如果不是空格就把遍历的字符添加到临时数组中,如果是空格就添加3个字符'%','2','0'分别到临时数组中,最后再把临时数组转化为字符串即可。
实现代码(java)
方法一:
java
public String replaceSpace(String s) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ')
stringBuilder.append("%20");
else
stringBuilder.append(s.charAt(i));
}
return stringBuilder.toString();
}
方法二:
java
public String replaceSpace(String s) {
int length = s.length();
char[] array = new char[length * 3];
int index = 0;
for (int i = 0; i < length; i++) {
char c = s.charAt(i);
if (c == ' ') {
array[index++] = '%';
array[index++] = '2';
array[index++] = '0';
} else {
array[index++] = c;
}
}
String newStr = new String(array, 0, index);
return newStr;
}
学习完本题的思路你可以解决如下题目:
翻转单词序列
难度:简单
描述
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,"nowcoder. a am I"。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是"I am a nowcoder."。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
举例
解题思路
方法一:栈;我们都知道栈是先进后出的,于是我们可以用方法一中分割单词的方式,在大的句子字符串中分割出一个一个地单词。然后从头到尾遍历单词,将分割出来的单词送入栈中,然后按照栈中弹出的字符串顺序拼接单词即可使单词之间逆序。
- step 1:遍历字符串,将整个字符串按照空格分割然后入栈。
- step 2:遍历栈,将栈中内容弹出拼接成字符串。
方法二:两次反转;我们需要的是将单词位置反转,也即是单词内部不变,属于字符串部分反转问题。如果将整个字符串反转,单词位置倒是反转了,但是内部次序也改变了,此时就需要将内部再反转回去,因此两次反转可以解决。
- step 1:将字符串整体反转。
- step 2:遍历反转后的字符串,以空格为界限找到一个单词。
- step 3:将每个单词部分反转。
实现代码(java)
方法一:
java
import java.util.*;
public class Solution {
public String ReverseSentence(String str) {
Stack<String> st = new Stack<String>();
String[] temp = str.split(" ");
//单词加入栈中
for(int i = 0; i < temp.length; i++){
st.push(temp[i]);
st.push(" ");
}
StringBuilder res = new StringBuilder();
//去掉最后一个空格
if(!st.isEmpty())
st.pop();
//栈遵循先进后厨,单词顺序是反的
while(!st.isEmpty())
res.append(st.pop());
return res.toString();
}
}
方法二:
java
import java.util.*;
public class Solution {
//字符串反转函数
private void reverse(char [] c, int l, int h){
//双指针反转
while(l < h)
swap(c, l++, h--);
}
//字符交换函数
private void swap(char [] c, int l, int h){
char temp = c[l];
c[l] = c[h];
c[h] = temp;
}
public String ReverseSentence(String str) {
int n = str.length();
char[] c = str.toCharArray();
//第一次整体反转
reverse(c, 0, n - 1);
for(int i = 0; i < n; i++){
int j = i;
//以空格为界找到一个单词
while(j < n && c[j] != ' ')
j++;
//将这个单词反转
reverse(c, i, j - 1);
i = j;
}
return new String(c);
}
}