翻转字符串Ⅰ
这题本质还是双指针,跳出条件是两个指针相遇,即右指针不再大于左指针。
package String;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-08-13 16:20
*/
public class ZiFuChuanFanZhuan {
public void solution(char[] s){
int len = s.length;
for (int i = 0 ,j = len - 1; i < j ;i++,j--){
s[i] ^= s[j] ;
s[j] ^= s[i] ;
s[i] ^= s[j] ;
}
}
public static void main(String[] args) {
char[] s = {'x','d','l','z','w','m'};
ZiFuChuanFanZhuan ziFuChuanFanZhuan = new ZiFuChuanFanZhuan();
ziFuChuanFanZhuan.solution(s);
System.out.println();
}
}
这题最省内存的操作是,利用异或运算交换两个char !!!然后循环就好了。这里的异或操作,是在位(bit)上的操作。
class Solution {
public void reverseString(char[] s) {
int l = 0;
int r = s.length - 1;
while (l < r) {
s[l] ^= s[r]; //构造 a ^ b 的结果,并放在 a 中
s[r] ^= s[l]; //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
s[l] ^= s[r]; //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
l++;
r--;
}
}
}
翻转字符串Ⅱ
这题的需求就是为了绕你而绕,很奇怪的需求。题目的意思其实概括为 每隔2k个反转前k个,尾数不够k个也反转! 处理的时候第一步把字符串转成字符数组, char [] ch = s.toCharArray()。这题就是情况多,需要多考虑,如果最后一组不足2k个,大于k个。或者甚至还不足k个。这两种情况可以合并成int end = Math.min(ch.length - 1, start + k - 1) 就解决了。因为什么,因为我不管你有多少个,我就只反转k个。
package String;
import static java.lang.Math.min;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-08-13 16:46
*/
public class ZiFuFanZhuan2 {
public void rever(char[] s ,int start,int end){
int i =start;
int j =end;
while(i < j){
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
i++;
j--;
}
}
public String solution(String s, int k){
char[] ch = s.toCharArray();
for (int i = 0 ; i<s.length(); i += 2*k){
int end = min(i+k-1,s.length()-1);
rever(ch,i,end);
}
return new String(ch);
}
public static void main(String[] args) {
String s ="AaBbCcDdEe";
ZiFuFanZhuan2 ziFuFanZhuan2 = new ZiFuFanZhuan2();
String news = ziFuFanZhuan2.solution(s, 2);
System.out.println(news);
}
}
翻转单词
处理空格的思路是双指针,快指针扫描整个字符串遇到空格跳过,慢指针指向要覆盖的位置。
package String;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-08-20 13:53
*/
public class FanZhuanDanCi {
public String solution(String s){
char[] chars = s.toCharArray();
// 清理多余空格
chars = removeSpaces(chars);
// 翻转整个新字符串
reverse(chars,0,chars.length-1);
// 翻转单词。
reverseWords(chars);
//返回字符串类型
return new String(chars);
}
public char[] removeSpaces(char[] chars){
int slow = 0 ;
for (int fast = 0; fast < chars.length; fast++ ){
if (chars[fast] != ' '){
if (slow != 0){
chars[slow++] = ' ';
}
while(fast < chars.length && chars[fast] != ' '){ //防数组越界报错!
chars[slow++] = chars[fast++];
}
}
}
char[] newchars = new char[slow];
System.arraycopy(chars,0,newchars,0,slow);
return newchars;
}
public void reverse(char[] chars,int left, int right){
while (left < right){
chars[left] ^= chars[right];
chars[right] ^= chars[left];
chars[left] ^= chars[right];
left++;
right--;
}
}
public void reverseWords(char[] chars){
int start = 0;
for (int end = 1; end <= chars.length; end++ ){
if (end == chars.length || chars[end] == ' '){
reverse(chars,start,end-1);
start = end+1;
}
}
}
public static void main(String[] args) {
String s = "a good example";
FanZhuanDanCi fanZhuanDanCi = new FanZhuanDanCi();
System.out.println(fanZhuanDanCi.solution(s));
}
}
KMP
笔记太多,不展示了。
package String;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-08-13 17:07
*/
public class ZuiChangZiChuanWeiZhi {
public int KMP(String fuchuan, String zichuan){
int[] next = new int[zichuan.length()];
getNext(next,zichuan);
int j = 0;
for (int i = 0 ; i< fuchuan.length();i++){
//不相等
while(j>0 && fuchuan.charAt(i) != zichuan.charAt(j) ){
j = next[j-1];
}
if (fuchuan.charAt(i) == zichuan.charAt(j)){
j++ ;
}
if (j == zichuan.length()){
return i - j+1;
}
}
//没有找到子串,也就没有子串的位置,返回-1
return -1;
}
public void getNext(int[] next,String zichuan){
int j=0;
next[0] = 0 ;
for (int i =1;i<zichuan.length();i++){
//先考虑不相等
while(j>0 && zichuan.charAt(i) != zichuan.charAt(j)){
j = next[j-1];
}
//相等
if (zichuan.charAt(i) == zichuan.charAt(j)){
j++;
}
next[i] = j;
}
}
public static void main(String[] args) {
}
}
重复子串
直接背结论,就是前缀串和后缀串岔开的部分就是重复子串,不过好在这题只需要判断不需要找出。就是next数组生成后多一行背的结论。
package String;
/**
* 功能:
* 作者:RNG·Cryin
* 日期:2024-08-19 20:32
*/
public class ChongFuZiChuan {
public boolean solution(String s){
char[] chars = s.toCharArray();
int[] next = new int[s.length()];
int len = s.length();
next[0] = 0;
int j = 0;
//构建next数组
for (int i = 1; i< s.length(); i++){
while(j>0 && chars[i] != chars[j]){
j = next[j-1];
}
if (chars[i] == chars[j]){
j++ ;
}
next[i] = j;
}
for (int i= 0 ; i < len; i++)
System.out.println(next[i]);
//判断重复子串
if (next[len - 1] > 0 && len % (len - next[len - 1]) == 0 ){
return true;
}
return false;
}
public static void main(String[] args) {
String s = "abcabcabcabc";
ChongFuZiChuan chongFuZiChuan = new ChongFuZiChuan();
System.out.println(chongFuZiChuan.solution(s));
}
}