leetcode:344反转字符串
- 这道题目就是用双指针的方式,进行收尾交换,更新2个指针,向中间靠拢进行再次的更换。
- 注意我们的temp一定是char字符串类型,不是int类型;
- 方法是void,所以没有返回值。
- 代码如下:
-
-
class Solution { public void reverseString(char[] s) { // 双指针方法进行头尾的22交换 char temp = 0; int before = 0; int after = s.length - 1; while (before < after) { temp = s[before]; s[before] = s[after]; s[after] = temp; before++; after--; } } }
-
class Solution(object):
def reverseString(self, s):
"""
:type s: List[str]
:rtype: None Do not return anything, modify s in-place instead.
"""
left,right =0,len(s)-1
for i in range (len(s)//2):
s[left],s[right] =s[right],s[left]
left +=1
right -=1
541. 反转字符串II
用一行代码就能把分类问题一起总结:
int end = Math.min(i + k - 1, s.length() - 1); // 反转前 k 个字符
用一个end把各种情况都考虑
第一种情况就是 ,前面的每个2k阶段,都是用这个start和end能约束
第二种情况:剩下的部分大于k,小于2k, 还是按照 end =i+k-1的逻辑,和第一种情况一样进行转换字符串
最后一种情况就是: 剩下的不足k,按照起点算起,到end=s.length() - 1的这部分, 这样把题目的几种分类问题都一起处理了。
class Solution {
public String reverseStr(String s, int k) {
char[] chars = s.toCharArray(); // 将字符串转换成字符数组
// 每 2k 个字符为一个段落
for (int i = 0; i < s.length(); i += 2 * k) {
// 计算反转区间的结束位置
int start = i;
int end = Math.min(i + k - 1, s.length() - 1); // 反转前 k 个字符
// 反转前 k 个字符
while (start < end) {
char temp = chars[start];
chars[start] = chars[end];
chars[end] = temp;
start++;
end--;
}
}
// 将字符数组转换回字符串并返回
return new String(chars);
}
}
用python写
class Solution(object):
def reverseStr(self, s, k):
"""
:type s: str
:type k: int
:rtype: str
"""
chars =list(s)
n=len(chars)
for i in range(0,n,2*k):
left,right =i,min(i+k-1,n-1)
while left <right:
chars[left],chars[right]=chars[right],chars[left]
left +=1
right -=1
return ''.join(chars)
示例分析:"abcdefg", k=2
- 初始状态:
"abcdefg"
- 将字符串分为两组:
"abcd"
(第一个2k组) 和"efg"
(剩余字符)
- 将字符串分为两组:
- 第一步:反转第一个2k组的前k个字符
- 反转
"ab"
→"ba"
- 结果:
"bacdefg"
- 反转
- 第二步:反转第二个区间的前k个字符
- 剩余部分
"efg"
,前k个字符是"ef"
- 反转
"ef"
→"fe"
- 结果:
"bacdfeg"
- 剩余部分
- 最终结果:
"bacdfeg"
边界情况分析
- 剩余字符少于k个:
- 例如:"ab", k=3
- 通过
min(i+k-1, n-1)
自动处理为全部反转
- k < 剩余字符 < 2k:
- 例如:"abcde", k=2
- 只反转前k个字符,其余保持不变
- 空字符串:
- 无需特殊处理,直接返回空字符串
算法复杂度
- 时间复杂度:O(n),每个字符最多被处理一次
- 空间复杂度:O(n),需要一个与原字符串等长的字符数组
这种算法的巧妙之处在于通过计算边界条件和步长,简洁地处理了所有可能的情况,而不需要繁琐的条件判断。
54. 替换数字(第八期模拟笔试)
这个题目解题思路是: 先计算旧字符串中有多少个数字,然后我们创建新的字符数组时候,便于定义新数组的大小。 我们在原来的字符串长度s.length() 的基础上,再进行扩充每个数字的5倍,进行加和。 之所以是5倍,是因为number这6个空间中,有一个位置最后会被原来的数字空位填充,所以是5而不是6. 并且我们使用System.arraycopy()
的方式,把旧数组的(字符串转数组s.toCharArray(), 方便后续的数组拷贝)拷贝到新数组的开头。 然后用i和j 两个指针, i指针指向新数组的末尾, j指向拷贝来的数组的尾字符位置。 如果是字母, 新数组的末尾进行替换填充,如果是数字,就给6个空间,一次向前填充number。 最后 使用new String(新数组) 返回一个String类型的数据。
当然在acm格式条件下,我们需要创建输入的的类 Scanner scanner =new Scanner (System.in),以及使用scanner实例中的方法scanner.next() ,获取对应的字符串 并最后关闭scanner实例的流式使用。 代码中的确需要在使用完 Scanner
后关闭它,以确保流被正确释放
代码如下:
import java.util.Scanner;
public class Main {
/* code */
public static void main (String[] args){
Scanner scanner = new Scanner(System.in);
String s = scanner.next();
System.out.println(replaceNumber(s));
scanner.close();
}
public static String replaceNumber(String s){
int count=0;
for(int i=0;i<s.length();i++){
if(Character.isDigit(s.charAt(i))){
count ++;
}
}
char [] newStr = new char [s.length()+count*5];
System.arraycopy(s.toCharArray(),0,newStr,0,s.length());
//从后段进行判断并进行填充:
for(int i=newStr.length-1, j=s.length()-1;j<i;i-- ,j--){
if(! Character.isDigit( newStr[j])){
newStr[i]=newStr[j];
}else{
newStr[i]='r';
newStr[i-1]='e';
newStr[i-2]='b';
newStr[i-3]='m';
newStr[i-4]='u';
newStr[i-5]='n';
i -=5;
}
}
return new String(newStr);
}
}