leetcode算法练习
344.反转字符串
题目链接
双指针法的经典应用!
思路:
- 本题要求返回后的结果是原地操作 不要再去申请一个新的字符串 因为题目要求时间复杂度是O(1) 其实反转字符串做的就是首位交换 次首位交换 次次首位再交换——那么就想到应该头尾各有一个指针 两个指针指向要进行两两交换的元素的位置
- 元素交换可通过基础的三角交换 亦或者位运算
class Solution {
public void reverseString(char[] s) {
// 设置了双指针
int l = 0;
int r = s.length - 1;
// 循环遍历两个指针 让其往中间移动
while (l < r) {
// 交换元素
// 常见的交换元素为三角交换 即int tmp = s[i]; s[i] = s[j]; s[j] = tmp;
// 通过位运算也可以实现
s[l] ^= s[r]; // 构造s[l] ^ s[r]的结果 并放在s[l]中
s[r] ^= s[l]; // 将s[l] ^ s[r]这一结果再 ^ s[r] 存入s[r]中 此时 s[r] = s[l] s[l] = s[l] ^ s[r]
s[l] ^= s[r]; // s[l] ^ s[r]的结果再 ^ s[l] 存入 s[l] 中 此时 s[r] = s[l] s[l] = s[r] 完成交换
// 指针移动
l++;
r--;
}
}
}
541. 反转字符串II
题目链接
题目意思是对字符串里每2k个字符串进行反转
- 例如:abcdefgz k=3 则为cbadef 剩下gz不够2k了 判断够不够前k个 不够的话 剩下的都进行反转 故为cbadefzg
- abcdefgzjj k=3 则为cbadef 剩下gzjj不够2k了 判断够不够前k个 够的话对前k个进行反转 故为cbadefjzgj
思路:
- 本题for循环遍历字符串的时候是以2k为单位遍历的 而不是i++ 每次操作时只操作前k个就行了
class Solution {
public String reverseStr(String s, int k) {
char[] ch = s.toCharArray();
// 每隔2k个字符的前k个字符进行反转
for (int i = 0; i< ch.length; i += 2 * k) {
// 剩余字符小于2k但大于或等于k个 则反转前k个字符
// 作if判断防止翻转越界 因为i+k可能越界
if (i + k <= ch.length) {
// 翻转的部分是i到i+k 但是不包含i+k 一般定义边界都是左闭右开的
reverse(ch, i, i + k -1);
continue;
}
// 剩余字符少于k个 则将剩余字符全部反转
reverse(ch, i, ch.length - 1);
}
return new String(ch);
}
// 定义翻转函数
public void reverse(char[] ch, int i, int j) {
for (; i < j; i++, j--) {
char temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
}
}
}
剑指Offer 05.替换空格
思路:
- 首先将数组扩充到每个空格替换成"%20"之后的大小 例如:We are happy 扩充成We%20are%20happy的大小
- 定义两个指针 左指针指向原始字符串最后一个位置 右指针指向扩展字符串的最后一个位置
- 左指针从后往前遍历 如果左指针指向了空格 移动右指针 将%20依次赋值到末尾;如果左指针不是空格 把左指针的值赋值给右指针
class Solution {
public String replaceSpace(String s) {
if(s == null || s.length() == 0){
return s;
}
// 扩充空间
StringBuilder str = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
// 每有一个空格 就在后面追加两个空格的大小 因为空格被替换成%20 那从一位变成了三位 故追加两位
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){
// 如果左指针指向了空格 移动右指针 将%20依次赋值到末尾
if(chars[left] == ' '){
chars[right--] = '0';
chars[right--] = '2';
chars[right] = '%';
}else{
// 如果左指针不是空格 把左指针的值赋值给右指针
chars[right] = chars[left];
}
left--;
right--;
}
return new String(chars);
}
}
151.翻转字符串里的单词
题目链接
注意:
- 给的字符串可能前后都有空格 或者右多个连续空格
- 翻转后的字符串首位要去掉空格
- 反转后的字符串需要将单词间的空格减少到仅有一个
思路:
- 先对整个字符串进行翻转 而后对内里的单词再单独进行翻转
- 多余空格的删除
class Solution {
/**
* 不使用Java内置方法实现
* 1.去除首尾以及中间多余空格
* 2.反转整个字符串
* 3.反转各个单词
*/
public String reverseWords(String s) {
// System.out.println("ReverseWords.reverseWords2() called with: s = [" + s + "]");
// 1.去除首尾以及中间多余空格
StringBuilder sb = removeSpace(s);
// 2.反转整个字符串
reverseString(sb, 0, sb.length() - 1);
// 3.反转各个单词
reverseEachWord(sb);
return sb.toString();
}
private StringBuilder removeSpace(String s) {
// System.out.println("ReverseWords.removeSpace() called with: s = [" + s + "]");
int start = 0;
int end = s.length() - 1;
// 头部空格删除
while (s.charAt(start) == ' ') start++;
// 尾部空格删除
while (s.charAt(end) == ' ') end--;
StringBuilder sb = new StringBuilder();
// 遍历字符串
while (start <= end) {
// 从已删除前空格的字符位置开始
char c = s.charAt(start);
// 将删除多余空格的字符录入sb中
if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
sb.append(c);
}
start++;
}
// System.out.println("ReverseWords.removeSpace returned: sb = [" + sb + "]");
return sb;
}
/**
* 反转字符串指定区间[start, end]的字符
*/
public void reverseString(StringBuilder sb, int start, int end) {
// System.out.println("ReverseWords.reverseString() called with: sb = [" + sb + "], start = [" + start + "], end = [" + end + "]");
while (start < end) {
char temp = sb.charAt(start);
sb.setCharAt(start, sb.charAt(end));
sb.setCharAt(end, temp);
start++;
end--;
}
// System.out.println("ReverseWords.reverseString returned: sb = [" + sb + "]");
}
private void reverseEachWord(StringBuilder sb) {
int start = 0;
int end = 1;
int n = sb.length();
while (start < n) {
while (end < n && sb.charAt(end) != ' ') {
end++;
}
reverseString(sb, start, end - 1);
start = end + 1;
end = start + 1;
}
}
}