编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s
的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
示例 1:
输入:s = ["h","e","l","l","o"] 输出:["o","l","l","e","h"]
示例 2:
输入:s = ["H","a","n","n","a","h"] 输出:["h","a","n","n","a","H"]
提示:
1 <= s.length <= 105
s[i]
都是 ASCII 码表中的可打印字符
思路:本题目只要是考验对字符串的基本操作能力,看一遍代码就懂思路了
public static void reverseString(char[] s) {
char temp;
//用两个分别指向串首与串尾的指针,对下标对应元素实现交换
int left =0;
int right = s.length-1;
while(left<right){
//用异或位运算实现两个字符的交换
//不懂的伙伴可以手动运算检验
s[left] ^=s[right];
s[right] ^= s[left];
s[left] ^=s[right];
left++;
right--;
}
}
给定一个字符串 s
和一个整数 k
,从字符串开头算起,每计数至 2k
个字符,就反转这 2k
字符中的前 k
个字符。
- 如果剩余字符少于
k
个,则将剩余字符全部反转。 - 如果剩余字符小于
2k
但大于或等于k
个,则反转前k
个字符,其余字符保持原样。
示例 1:
输入:s = "abcdefg", k = 2 输出:"bacdfeg"
示例 2:
输入:s = "abcd", k = 2 输出:"bacd"
提示:
1 <= s.length <= 104
s
仅由小写英文组成1 <= k <= 104
思路:
首先我使用的编程语言为java,java中有一个特性是String的值是作为常量不可修改的,所以要先把题目所给的String值转成char[]字符串数组方便进行操作.
第一步先写一个反转字符串数组元素的反转函数,原理同上一题,只不过这次为了操作更细致一些增加了操作区域的选择.
然后我们来分析题目,题目中我们可以看到每次操作字符串的时候都是以k或者2*k作为单位的,所以我们也不必用for(int i = 0;i<chars.length;i++)这样一个个遍历下去了,直接以2*k作为步进的单位即可,省时省力,然后让i指向一个2*k区域的末尾,对这个区域的前k的元素进行反转的操作,最后应该会剩下一个长度小于2*k 的区域
int n = 2*k;
for(int i =n;i<=chars.length;i += n)
最后我们再对这个最后的区域进行判断,如果长度小于k的话就对剩余的区域进行反转
(ps:我们可以用一个简单的取余操作获取剩下空间的大小信息)
int m = s.length()%n;
reverse(chars,s.length()-m,s.length()-1);
长度大于k就对剩余区域的前k部分进行反转
reverse(chars,s.length()-m,s.length()-m+k-1);
这样问题也就解决了,下面是代码演示
public static String reverseStr(String s, int k) {
char[] chars = s.toCharArray();
int n = 2*k;
for(int i =n;i<=chars.length;i += n){
//将前k个元素反转
int begin = i - n;
int end = i-k-1;
reverse(chars,begin,end);
}
//判断剩余个数
int m = s.length()%n;
if(m>=k){
reverse(chars,s.length()-m,s.length()-m+k-1);
}
else {
reverse(chars,s.length()-m,s.length()-1);
}
return String.valueOf(chars);
}
public static 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--;
}
}
描述
请实现一个函数,将一个字符串s中的每个空格替换成“%20”。
例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
数据范围: 0≤len(s)≤1000 。保证字符串中的字符为大写英文字母、小写英文字母和空格中的一种。
示例1
输入:
"We Are Happy"
复制返回值:
"We%20Are%20Happy"
思路:一个个搜索,找到空格了进行替换即可,我选择的是在一个新的数组进行操作
代码如下:
public static String replease(String s){
StringBuilder sb =new StringBuilder();
for(int i =0;i<s.length();i++){
if(s.charAt(i) == ' '){
sb.append("%20");
continue;
}
sb.append(s.charAt(i));
}
return sb.toString();
}
给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例 1:
输入:s = "the sky is blue
" 输出:"blue is sky the
"
示例 2:
输入:s = " hello world " 输出:"world hello" 解释:反转后的字符串中不能存在前导空格和尾随空格。
示例 3:
输入:s = "a good example" 输出:"example good a" 解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。
思路:
本题看起来很简单,但是实际上难的地方不在于反转单词,而在于去除多余无意义的空格,这里如果我们想使用O(1)空间复杂度的算法在java中是不可能的,因为题目给的String不可修改,只能转换成char[]再进行相应的操作,但是听卡哥说面试官往往是问空间复杂度为O(1)的解法比较多,故在此也使用相应的思路解题
首先第一步,将字符串转为字符数组
char[] chars= s.toCharArray();
第二步,对字符串组进行倒转
为什么要进行倒转呢?这样也还是得不到最后的结果,但是这样单词的次序就是正确的了,我们最后再对单词进行一一反转即可得出结果
第三步,去除多余的空格
在此使用快慢指针的思想,与我之前写的一到移除数组元素有异曲同工之妙,在我的主页也写过这一题,感兴趣的朋友可以去看看.
代码如下
public static char[] removeExtraSpaces(char[] chars) {
//思路快指针慢指针删除多余空格
int slow =0;
int fast = 0;
for(;fast<chars.length;fast++){
//碰到单词第一个字母的时候
if (chars[fast] != ' '){
//排除首个单词的情况
if(slow != 0){
chars[slow] = ' ';
slow++;
}
//依次赋值直到最后一个,最后两个指针++指向单词后一位
while(fast < chars.length &&chars[fast] != ' '){
chars[slow] = chars[fast];
fast++;
slow++;
}
}
}
char[] newchars = new char[slow];
System.arraycopy(chars, 0, newchars, 0, slow);
return newchars;
}
第四步,对单词进行一一反转
public static String reverseWords(String s){
char[] chars= s.toCharArray();
reverse(chars,0,chars.length-1);//对数组倒转
char[] newChars = removeExtraSpaces(chars);//去除多余空格
//定义双指针找出单词
int star=0;
int end =0;
while(end<newChars.length){
if(newChars[star] != ' '){
//到了字符串结尾或者碰到' '字符停止循环
while(end< newChars.length&&newChars[end] !=' '){
end++;
}
//为了不操作空格字符
end--;
reverse(newChars,star,end);
star = end;
}
star++;
end++;
}
return String.valueOf(newChars);
}
如此便可得出最后结果
描述
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列 S ,请你把其循环左移 K 位后的序列输出。例如,字符序列 S = ”abcXYZdef” , 要求输出循环左移 3 位后的结果,即 “XYZdefabc”
数据范围:输入的字符串长度满足 0≤len≤100 , 0≤n≤100
进阶:空间复杂度 O(n) ,时间复杂度 O(n)
示例1
输入:
"abcXYZdef",3
复制返回值:
"XYZdefabc"
思路:
摆了
代码如下:
public static String LeftRotateString(String str, int n) {
if(str.isEmpty() || str.length() == 0)
return "";
char[] s = str.toCharArray();
int m = str.length();
n = n % str.length();
//第一次逆转全部元素
reverse(s, 0, s.length - 1);
//第二次逆转开头元素
reverse(s, 0, m-n - 1);
//第三次逆转结尾元素
reverse(s, m-n, m - 1);
return String.valueOf(s);
}
public static void reverse(char[] s, int begin, int last) {
// 操作空间为[begin,last]
if (begin < 0 || begin >= s.length || last < 0 || last >= s.length || last < begin) {
System.out.println("操作有误!");
}
while (begin < last) {
s[begin] ^= s[last];
s[last] ^= s[begin];
s[begin] ^= s[last];
begin++;
last--;
}
}
以上为本次训练的题目,感谢大家观看!