左旋转字符串
public class Solution {
public String LeftRotateString(String str,int n) {
if(str == null || str.length() ==0){
return str;
}
int len = str.length();
char[] charArrays = str.toCharArray();
reverse(charArrays,0,n-1);
reverse(charArrays,n,len-1);
reverse(charArrays,0,len-1);
return String.valueOf(charArrays);
}
private void reverse(char[] charArrays, int i, int j) {
char temp;
while (i < j){
temp = charArrays[i];
charArrays[i] = charArrays[j];
charArrays[j] = temp;
i++;
j--;
}
}
}
翻转单词顺序
public class Solution {
public String ReverseSentence(String str) {
if(str == null ||str.trim().length() ==0){
return str;
}
StringBuilder sb = new StringBuilder();
String res = reverse(str);
String[] newString = res.split(" ");
for(int i =0;i=0;i--){
newStr.append(str.charAt(i));
}
return String.valueOf(newStr);
}
}
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
观察字符串变化规律,你会发现这道题很简单。只需要对每个单词做翻转,然后再整体做翻转就得到了正确的结果。
public String trim() {
int len = value.length;// 有效字符(不是空格)结束位置
int st = 0;// 有效字符(不是空格)起始位置
char[] val = value; // 字符数组 /* avoid getfield opcode */
while ((st < len) && (val[st] <= ' ')) { // 从起始位置开始遍历,获取起始连续空格的最后空格位置
st++;// st值发生变化,说明起始有空格,st就是起始需要截取的位置
}
while ((st < len) && (val[len - 1] <= ' ')) { // 从末尾位置开始遍历,获取末尾连续空格的第一个空格位置
len--;// len值发生变化,说明末尾有空格,len是末尾需要截取的位置
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;// 判断是否有空格需要截取,有截取,没有返回原String
}
class Solution {
public String reverseWords(String s) {
char[] data = s.toCharArray();
if (data == null || data.length < 1) {
return String.valueOf(data);
}
reverse(data, 0, data.length - 1);
int start = 0;
int end = 0;
while (start < data.length) {
if (data[start] == ' ') {
start++;
end++;
} else if (end == data.length || data[end] == ' ') {
reverse(data, start, end - 1);
end++;
start = end;
} else {
end++;
}
}
return String.valueOf(data);
}
public static void reverse(char[] data, int start, int end) {
if (data == null || data.length < 1 || start < 0 || end > data.length || start > end) {
return;
}
while (start < end) {
char tmp = data[start];
data[start] = data[end];
data[end] = tmp;
start++;
end--;
}
}
}
//第二种思路,先将整个字符串反转,再逐个单词反转
public String ReverseSentence(String str) {
if (str == null || str.length() == 0)
{
return str;
}
if (str.trim().length() == 0)
{
return str;
}
StringBuilder sb = new StringBuilder();
String re = reverse(str);
String[] s = re.split(" ");
for (int i = 0; i < s.length - 1; i++) {
sb.append(reverse(s[i]) + " ");
}
sb.append(reverse(s[s.length-1]));
return String.valueOf(sb);
}
public String reverse(String str) {
StringBuilder sb = new StringBuilder();
for (int i = str.length() - 1; i >= 0 ; i--) {
sb.append(str.charAt(i));
}
return String.valueOf(sb);
}
public class Test2 {
public static void main(String[] args) {
String s = " hello world! ";
System.out.println(reverseWords(s));
}
public static String reverseWords(String s) {
String[] words = s.trim().split("\\s+");
StringBuilder ans = new StringBuilder();
for(int i = words.length - 1; i >= 0; i--) {
ans.append(words[i] + " ");
}
return ans.toString().trim();
}
}
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
例如:输入字符串"abcdefg"和数字2,该函数将返回左旋转2位得到的结果"cdefgab";
第一步:翻转字符串“ab”,得到"ba";
第二步:翻转字符串"cdefg",得到"gfedc";
第三步:翻转字符串"bagfedc",得到"cdefgab";
或者:
第一步:翻转整个字符串"abcdefg",得到"gfedcba"
第二步:翻转字符串“gfedc”,得到"cdefg"
第三步:翻转字符串"ba",得到"ab"
public class Test {
public static void main(String[] args) {
System.out.println(LeftRotateString("abcdefg",2));
}
public static String LeftRotateString(String pStr,int num){
if(pStr == null ||pStr.length()
public String LeftRotateString(String str,int n) {
if (str == null || str.trim().length() == 0) {
return str;
}
int len = str.length();
n = n % len;// 当len=3,n=4,其实相当于左旋转1位,所以需要取余
char[] charstr = str.toCharArray();
//先旋转前面的
reverse(charstr, 0, n-1);
//再旋转后面的字符串
reverse(charstr, n, len -1);
//最后整体反转
reverse(charstr, 0, len-1);
return String.valueOf(charstr);
}
//实现的是charstrs从i到j的反转,也可以使用上题中stringbuffer的反转方式
private void reverse(char[] charStrs, int i, int j) {
while(i
旋转字符串
给定两个字符串, A 和 B。
A 的旋转操作就是将 A 最左边的字符移动到最右边。 例如, 若 A = 'abcde',在移动一次之后结果就是'bcdea' 。如果在若干次旋转操作之后,A 能变成B,那么返回True。
示例 1:
输入: A = 'abcde', B = 'cdeab'
输出: true
示例 2:
输入: A = 'abcde', B = 'abced'
输出: false
注意:
A 和 B 长度不超过 100。
思路:首先确认两个字符串的长度要相等。其次只要保证A+A 的字符串中包含B就可以了。因为A+A已经包含了所有可移动的方案。
public static boolean rotateString(String A, String B) {
return A.length() == B.length() && (A+A).contains(B);
}
public static void main(String[] args) {
String a = "abcde";
String b = "abced";
boolean flag = rotateString(a,b);
System.out.println(flag);
}
判断一个串是否为另一个串的子串的最优时间复杂度的算法是 KMP 算法。和方法二相同,我们只需要用 KMP 算法判断 B 是否为 A + A 的子串即可。KMP 算法较难理解,这里给出了力扣第 28 题 实现 strstr() 讨论区中一个高赞 KMP 算法详解,以及著名博主 Matrix67 的 KMP 算法详解。
class Solution {
public boolean rotateString(String A, String B) {
int N = A.length();
if (N != B.length()) return false;
if (N == 0) return true;
//Compute shift table
int[] shifts = new int[N+1];
Arrays.fill(shifts, 1);
int left = -1;
for (int right = 0; right < N; ++right) {
while (left >= 0 && (B.charAt(left) != B.charAt(right)))
left -= shifts[left];
shifts[right + 1] = right - left++;
}
//Find match of B in A+A
int matchLen = 0;
for (char c: (A+A).toCharArray()) {
while (matchLen >= 0 && B.charAt(matchLen) != c)
matchLen -= shifts[matchLen];
if (++matchLen == N) return true;
}
return false;
}
}
复杂度分析
时间复杂度:O(N)O(N),其中 NN 是字符串 A 的长度。
空间复杂度:O(N)O(N)。