随想录Day8|力扣344.反转字符串、 541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串

344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 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--;
        }
    }

541. 反转字符串 II

给定一个字符串 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();

    }

151. 反转字符串中的单词

给你一个字符串 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--;
        }
    }

以上为本次训练的题目,感谢大家观看!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值