- 序:有的时候调用库中直接给的类方法解决起来更轻松,有的时候里面的方法并不能解决实际性问题,这时候就需要我们自个儿重写了。首先我们可以学习库里面方法怎么实现的,随后我们可以写出不同于它的(别人的东西不一定有自个儿的好)下面说说c++STL中string和Java中的String与StringBuffer解决反转问题所遇到的情况。
咱现在就从题入手,进行解释
(玩呢?我直接调个c++reverse库函数不就解决了吗?(reverse(s.begin(),s.end()) 就这?)
先不急,咱先掌握其实现原理,后续肯定是有用的。
如何反转呢?我们是不是可以利用双指针对左右进行交换,让双指针向中间靠拢。
实现代码:
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0;
int right = s.size() - 1;
while(left<right){//当left等于right或者left大于right就不需要进行交换了已经反转完毕了
swap(s[left],s[right]);//交换元素
++left;
--right;
}
}
};
交换数据有三种常见的方法: 1. 创建第三变量 int temp = s[left]; s[left] = s[right]; s[right] = temp; 2. 用加法运算(但可能导致数据溢出) s[left] = s[left] + s[right]; s[right] = s[left] - s[right]; s[left] = s[left] - s[right]; 3. 采用位运算(异或^) s[left] ^= s[right]; s[right] ^= s[left]; s[left] ^= s[right]; (第一种是最好的,不受类型限制,用异或不能解决float等数据类型的数据,数据不大的情况下,第一种更好) |
现在掌握了反转字符串的原理,思考一下如果是只反转字符串片段呢?c++中reverse是可以解决这一反转的,但是Java中StringBuffer是不能选取字符串片段进行反转的,接下来看题:
这题用c++库还是蛮简单的,首先我们定一下反转的起始位置,每反转一次起始位置就开始变化(左右俩次反转的距离是2*k),然后再确定反转的末位置,如果反转字符小于k了,那就反转起始位置到字符串尽头(s.size()),如果大于k的话,那末位置就是起始位置+k。
C++代码如下:
class Solution {
public:
string reverseStr(string s, int k) {
int start = 0;
int end;
while(start<s.size()){
end = start + k;
//反转末位置在长度之内则反转该序列
if(end<=s.size()){
reverse(s.begin()+start,s.begin()+end);
}
//不在长度之内则说明,反转序列小于k,直接把起始位置到字符串尽头都反转
else
reverse(s.begin()+start,s.end());
start += 2*k;
}
return s;
}
};
如果我们想用Java提供的库方法呢?咱就得采用拼接的形式:
Java采用库的代码如下:
class Solution {
public String reverseStr(String s, int k) {
String xs = new String(); //用来存取反转的字符串(也可以说是对字符串s进行重新拼接)
int start = 0; //一样的,定义起始位置
while(start<s.length()){
StringBuffer acts = new StringBuffer();//定义一个动态字符串,进行翻转操作
//但这里得注意需要给出两个变量,一个是反转的末位置,一个是不用反转的莫位置
int _start = start+k<s.length()?start+k:s.length();
int end = start+2*k<s.length()?start+2*k:s.length();
//存取加反转操作
acts.append(s.substring(start,_start));
acts.reverse();
xs += acts.toString();
start += 2*k; //更新初始位置
if(_start<end)
xs += s.substring(_start,end);
}
return xs;
}
}
这样写真是费时费力不讨喜。
那Java库中没有提供片段式反转,那么我们可以怎样?自己写一个方法实现呗,题1说了反转实现的原理,外加俩参数定义需要反转的区间就可以了。
接下来看代码,更好理解:
class Solution {
//反转
private void reverseS(char[] s,int left,int right){
while(left<right){
char ch = s[left];
s[left] = s[right];
s[right] = ch;
++left;
--right;
}
}
public String reverseStr(String s, int k) {
int start = 0;
int end;
char[] ss = s.toCharArray();//转化成数组进行操作
//模拟上面c++写的就行了
while(start<s.length()){
end = start + k;
if(end<ss.length){
reverseS(ss,start,end-1);//这里注意这里和库里面的反转不一样,这里的末尾是反转序列最后一个数据,而不是最后一个再往后一个
}
else
reverseS(ss,start,ss.length-1);
start += 2*k;
}
return new String(ss);//根据构造函数String(char[])将字符数组转化成字符串
}
}
接下来咱拿它去练手:
这题第一步肯定先得去除额外的空格,因为最后结果字符串单词之间最多只能有一个空格。
有俩种想法可以尝试了: 第一种:先将各个单词存入容器中,把单词看成容器里面的元素,然后进行反转就🆗了(这个c++写起来比较轻松) 第二种:先总的反转,然后再将每个单词进行反转,这样也可以得到同样的结果 |
(这里为了联系上文,只写第二种,第一种有疑问可以发私信,一起交流学习)
代码如下:
class Solution {
//去除字符串s中多余出来的空格
private StringBuffer removeExtraSpace(String s){
s = s.trim(); //去除s的首尾空格
StringBuffer ss = new StringBuffer(s);
//去除ss|s中间多余的空格
for(int i=ss.length()-1;i>=1;--i){
if(s.charAt(i)==' '&&s.charAt(i-1)==' ')
ss.delete(i,i+1);
}
return ss;
}
//反转字符串序列方法
private void reverseS(StringBuffer ss,int left,int right){
while(left<right){
char temp = ss.charAt(left);
ss.setCharAt(left,ss.charAt(right));
ss.setCharAt(right,temp);
++left;
--right;
}
}
//反转单词
private void reverseWords(StringBuffer ss){
int left = 0;
for(int right = 0;right<ss.length();++right){
if(ss.charAt(right)==' '){
reverseS(ss,left,right-1);
left = right + 1;
}
else
continue;
}
//给最后一个单词反转
reverseS(ss,left,ss.length()-1);
}
public String reverseWords(String s) {
StringBuffer ss = removeExtraSpace(s);
ss.reverse();
reverseWords(ss);
return ss.toString();
}
}
再推荐一题练手,和上述方法一样的(当然方法不唯一):
看完这个有没有想看库里面源码的冲动 😍😍😍
点个小赞赞鼓励一下😆😆😆让我知晓你来过👩💻 我的主页🎈🎈🎈 |