仅自己学习记录
-
如果
s[left]
和s[right]
都是整数类型(如 int、long 等),那么执行异或操作后的结果也是整数类型,可以直接赋值给s[left]
。 -
如果
s[left]
和s[right]
是字符类型(char),Java 会将它们转换为整数进行异或操作,然后将结果转换回字符类型,并赋值给s[left]
。 -
如果
s[left]
和s[right]
是其他类型(如浮点数),则不支持按位异或操作,会导致编译错误。
344.反转字符串
主要涉及双指针以及交换元素位置,其中需要注意的点在于使用加或者异或交换时,下标不能相等即while(left < right),同时字符数组同样可以使用加或者是异或操作。
541. 反转字符串II
在开始时候直接 将字符串转为字符数组进行操作,同时操作完成后不用c.tostring(),在Java中,数组的 toString()
方法是继承自 Object
类的默认实现,它会返回对象的哈希码的字符串表示形式。因此,如果你直接返回数组的 toString()
方法,它将返回类似 "[I@1f6f0d2d"
的字符串,其中 I
表示整型数组,@
后面是数组对象的哈希码的十六进制表示。故而使用 return new String(arr)的方式。
主要是344 反转字符串的进阶操作,遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。其实就是模拟过程。
可以分为三种情况1.正常2k可以取完 2.剩余字符小于k 3.剩余字符大于等于k小于2k
只需要单独对剩余字符小于k做判断,那么剩余字符必会大于等于k则无论是1,3情况中的哪一种操作都相同。
卡码网:54.替换数字
双指针法来遍历
java使用stringbuilder或者是创建一个新数组长度为原来的长度加上要替换的元素个数乘以长度,string类型不可变
为什么要从后向前填充,从前向后填充不行么?
从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素整体向后移动。
其实很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
Character.isDigit()
是 Java 中的一个静态方法,用于判断指定的字符是否为数字字符。如果指定的字符是 0 到 9 中的任意一个数字字符,则该方法返回 true
,否则返回 false
。这个方法常用于验证用户输入是否是数字字符。
Java 中的 Character
类包含了一些用于处理字符的静态方法。以下是一些常用的 Character
类方法:
isLetter(char ch)
:判断指定的字符是否是一个字母。isDigit(char ch)
:判断指定的字符是否是一个数字字符。isWhitespace(char ch)
:判断指定的字符是否是一个空白字符(空格、制表符、换行符等)。isUpperCase(char ch)
:判断指定的字符是否是一个大写字母。isLowerCase(char ch)
:判断指定的字符是否是一个小写字母。toUpperCase(char ch)
:将指定的字符转换为大写形式。toLowerCase(char ch)
:将指定的字符转换为小写形式。toString(char ch)
:返回字符ch
的字符串表示形式。compareTo(char x, char y)
:比较两个字符x
和y
的值。getNumericValue(char ch)
:返回指定字符的数值表示形式。
151.翻转字符串里的单词
trim()
方法是 String
类中的一个实用方法,用于删除字符串的首尾空白字符(空格、制表符、换行符等)。该方法返回一个新的字符串,该字符串是去除了首尾空白字符后的原始字符串副本。
多个单词之间或者最前面可能有一个或者多个空格,故而使用spilt分割可能会出现""(空字符串);
如果非要分割可以考虑正则
List<String> wordList = Arrays.asList(s.split("\\s+"));
s.split("\\s+")
将会根据正则表达式 "\\s+"
进行分割,其中 "\\s+"
表示一个或多个空白字符(空格、制表符、换行符等)。然后,Arrays.asList()
方法将分割后的结果转换为一个 List<String>
类型的集合,使得我们可以更方便地对分割后的字符串进行操作和处理。
class Solution { public String reverseWords(String s) { s=s.trim(); String [] news = s.split("\\s+"); StringBuilder sb =new StringBuilder(); for (int i = news.length-1; i >= 0; i--) { sb.append(news[i]); if(i != 0){ sb.append(" "); } } return sb.toString(); } }
1.去除多余空格 使用双指针法去除首尾以及中间多余的空格
2.反转字符串 反转整个字符串
3.反转单词 反转单词,每次变量指向单词后一位的空格或者指向末尾,统一格式
/*
* 解法四:时间复杂度 O(n)
* 参考卡哥 c++ 代码的三步骤:先移除多余空格,再将整个字符串反转,最后把单词逐个反转
* 有别于解法一 :没有用 StringBuilder 实现,而是对 String 的 char[] 数组操作来实现以上三个步骤
*/
class Solution {
//用 char[] 来实现 String 的 removeExtraSpaces,reverse 操作
public String reverseWords(String s) {
char[] chars = s.toCharArray();
//1.去除首尾以及中间多余空格
chars = removeExtraSpaces(chars);
//2.整个字符串反转
reverse(chars, 0, chars.length - 1);
//3.单词反转
reverseEachWord(chars);
return new String(chars);
}
//1.用 快慢指针 去除首尾以及中间多余空格,可参考数组元素移除的题解
public char[] removeExtraSpaces(char[] chars) {
int slow = 0;
for (int fast = 0; fast < chars.length; fast++) {
//先用 fast 移除所有空格
if (chars[fast] != ' ') {
//在用 slow 加空格。 除第一个单词外,单词末尾要加空格
if (slow != 0)
chars[slow++] = ' ';
//fast 遇到空格或遍历到字符串末尾,就证明遍历完一个单词了
while (fast < chars.length && chars[fast] != ' ')
chars[slow++] = chars[fast++];
}
}
//相当于 c++ 里的 resize()
char[] newChars = new char[slow];
System.arraycopy(chars, 0, newChars, 0, slow);
return newChars;
}
//双指针实现指定范围内字符串反转,可参考字符串反转题解
public void reverse(char[] chars, int left, int right) {
if (right >= chars.length) {
System.out.println("set a wrong right");
return;
}
while (left < right) {
chars[left] ^= chars[right];
chars[right] ^= chars[left];
chars[left] ^= chars[right];
left++;
right--;
}
}
//3.单词反转
public void reverseEachWord(char[] chars) {
int start = 0;
//end <= s.length() 这里的 = ,是为了让 end 永远指向单词末尾后一个位置,这样 reverse 的实参更好设置
for (int end = 0; end <= chars.length; end++) {
// end 每次到单词末尾后的空格或串尾,开始反转单词
if (end == chars.length || chars[end] == ' ') {
reverse(chars, start, end - 1);
start = end + 1;
}
}
}
}
卡码网:55.右旋转字符串
如果允许额外的空间可以使用数组或者是StringBuilder来实现后k个元素即length-k到length(不包括),将其放到前面就,将0到length-k(不包括)放到后面即完成操作。
不能申请额外空间,只能在本串上操作。
思路就是 通过 整体倒叙,把两段子串顺序颠倒,两个段子串里的的字符在倒叙一把,负负得正,这样就不影响子串里面字符的顺序了。