【剑指Offer】个人学习笔记_58 - I翻转单词顺序&58 - II_左旋转字符串

刷题日期:下午5:32 2021年5月22日星期六

个人刷题记录,代码收集,来源皆为leetcode

经过多方讨论和请教,现在打算往Java方向发力

主要答题语言为Java

题目:

剑指 Offer 58 - I. 翻转单词顺序

难度简单98

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。

示例 1:

输入: "the sky is blue"
输出: "blue is sky the"

示例 2:

输入: "  hello world!  "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:

输入: "a good   example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

说明:

  • 无空格字符构成一个单词。
  • 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
  • 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
题目分析

需要不断的设置将条件包含进去。

可以用栈来存放每个识别到的单词,然后空格作为分割的条件,遍历完以后再全部出栈,中间以一个空格分隔每个内容,加到字符串变量中返回。

初始解答:

相关的操作已经模糊了,参考他人

class Solution {
    public String reverseWords(String s) {
        // 思路是trim + split,然后反向添加到sb中
        // 由于split可能会产生空字符串(连续多个空格),要排除掉这种情况
        // 最后一个空格要去掉
        s = s.trim(); //去除前面的空格
        String[] ss = s.split(" "); //分割,调库
        StringBuilder sb = new StringBuilder(); //方便调用append方法
        for (int i = ss.length - 1; i >= 0; i--) {
            if (!ss[i].equals("")) {
                sb.append(ss[i].trim()); //加单词,加空格
                sb.append(" ");
            }
        }
        return sb.toString().trim();
    }
}

执行结果:通过

显示详情 添加备注

执行用时:1 ms, 在所有 Java 提交中击败了100.00%的用户

内存消耗:37.9 MB, 在所有 Java 提交中击败了97.46%的用户

学习他人:

方法一:

算法使我快乐😍L1 2020-03-05

执行用时 :
2 ms, 在所有 Java 提交中击败了99.45%的用户
内存消耗 :
40.8 MB, 在所有 Java 提交中击败了100.00%的用户
public String reverseWords(String s) {
        //将传进来的字符串以空格拆分
        String[] strings = s.trim().split(" ");
        StringBuffer stringBuffer = new StringBuffer();
        //从尾巴开始遍历
        for (int i = strings.length - 1; i >= 0; i--) {
            if (strings[i].equals("")) {
                continue;
            }
            //到头了,append然后去空格
            if (i == 0) {
                stringBuffer.append(strings[i].trim());
            } else {
                // 怕有多余的空格,去掉,再加上去
                stringBuffer.append(strings[i].trim()).append(" ");
            }
        }
        //输出String 完事,安排!
        return stringBuffer.toString();
    }

方法二:

灭灵仔仔 3 天前 wdnmd不用库函数写了半天写不出来,最后还使用了库函数tm两分钟搞定了👴真是佛辣

class Solution {
	public String reverseWords(String s) {
		String arr[]=s.trim().split(" ");
		StringBuilder result=new StringBuilder();
		for(int i=arr.length-1;i>=0;i--) {
			if(!arr[i].equals("")) {
				result.append(arr[i]);
				if(i!=0)
					result.append(" ");
			}
		}
		return result.toString();
	}
}

方法三:

汪雪雷❄️imgL4 1 小时前 1ms 100%

public String reverseWords(String s) {
        String[] strs = s.split(" ");
        StringBuilder sb = new StringBuilder();
        for (int i = strs.length - 1; i >= 0; i--) {
            if (strs[i].equals("")) {
                continue;
            }
            sb.append(strs[i]);
            if (i != 0) {
                sb.append(" ");
            }
        }
        return sb.toString().trim();
    }

方法四:

middle_mountain 2021-03-12

class Solution {
    public String reverseWords(String s) {
        // 思路是trim + split,然后反向添加到sb中
        // 由于split可能会产生空字符串(连续多个空格),要排除掉这种情况
        // 最后一个空格要去掉
        s = s.trim();
        String[] ss = s.split(" ");
        StringBuilder sb = new StringBuilder();
        for (int i = ss.length - 1; i >= 0; i--) {
            if (!ss[i].equals("")) {
                sb.append(ss[i].trim());
                sb.append(" ");
            }
        }
        return sb.toString().trim();
    }
}

方法五

K神

方法一:双指针

作者:jyd
链接:https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof/solution/mian-shi-ti-58-i-fan-zhuan-dan-ci-shun-xu-shuang-z/
来源:力扣(LeetCode)

class Solution {
    public String reverseWords(String s) {
        s = s.trim(); // 删除首尾空格
        int j = s.length() - 1, i = j;
        StringBuilder res = new StringBuilder();
        while(i >= 0) {
            while(i >= 0 && s.charAt(i) != ' ') i--; // 搜索首个空格
            res.append(s.substring(i + 1, j + 1) + " "); // 添加单词
            while(i >= 0 && s.charAt(i) == ' ') i--; // 跳过单词间空格
            j = i; // j 指向下个单词的尾字符
        }
        return res.toString().trim(); // 转化为字符串并返回
    }
}
方法二:分割 + 倒序

利用 “字符串分割”、“列表倒序” 的内置函数 (面试时不建议使用) ,可简便地实现本题的字符串翻转要求。

class Solution {
    public String reverseWords(String s) {
        String[] strs = s.trim().split(" "); // 删除首尾空格,分割字符串
        StringBuilder res = new StringBuilder();
        for(int i = strs.length - 1; i >= 0; i--) { // 倒序遍历单词列表
            if(strs[i].equals("")) continue; // 遇到空单词则跳过
            res.append(strs[i] + " "); // 将单词拼接至 StringBuilder
        }
        return res.toString().trim(); // 转化为字符串,删除尾部空格,并返回
    }
}

题目:

剑指 Offer 58 - II. 左旋转字符串

难度简单118

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

示例 1:

输入: s = "abcdefg", k = 2
输出: "cdefgab"

示例 2:

输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"

限制:

  • 1 <= k < s.length <= 10000
题目分析

直接从n开始循环,然后再从头到n。

初始解答:

class Solution {
    public String reverseLeftWords(String s, int n) {
        StringBuilder res = new StringBuilder(); //方便调用append方法
        for (int i = n; i < s.length(); i++) {
            res.append(s.charAt(i)); //加单词,加空格
        }
        for (int i = 0; i < n; i++) {
            res.append(s.charAt(i)); //加单词,加空格
        }
        return res.toString();
    }
}

上一题的基础 执行结果:通过

显示详情 添加备注

执行用时:4 ms, 在所有 Java 提交中击败了31.50%的用户

内存消耗:38.2 MB, 在所有 Java 提交中击败了69.73%的用户

学习方法一调库

class Solution {
    public String reverseLeftWords(String s, int n) {
        return s.substring(n) + s.substring(0, n);
    }
}

学习他人:

方法一:

孙笑川L3 2020-03-02 Java 偷懒做法

class Solution {
    public String reverseLeftWords(String s, int n) {
        return s.substring(n) + s.substring(0, n);
    }
}

方法二:

cancer 2021-04-26 stringBuilder的相关用法

    public static String reverseLeftWords(String s, int n) {
        StringBuilder sb = new StringBuilder(s);
        sb.append(s);
        return sb.substring(n,s.length()+n);
    }

方法三:

还原靓靓拳 2021-04-10 感觉跟队列一个样子

class Solution {
    public String reverseLeftWords(String s, int n) {
        char[]arr = s.toCharArray();
        int len = arr.length;
        char[]res = new char[len];
        for(int i =0;i<len;i++){
            res[i] = arr[(i+n)%len];
        }
        return String.valueOf(res);
    }
}

方法四:

K神 解题思路:

本题做法较多,本文主要介绍 “字符串切片” , “列表遍历拼接” , “字符串遍历拼接” 三种方法。

由于本题的多解法涉及到了 字符串为不可变对象 的相关概念,导致效率区别较大。因此,单列一节 三种方法的效率分析 ,望对各位有所帮助。

作者:jyd
链接:https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/solution/mian-shi-ti-58-ii-zuo-xuan-zhuan-zi-fu-chuan-qie-p/
来源:力扣(LeetCode)

方法一:字符串切片

应用字符串切片函数,可方便实现左旋转字符串。

class Solution {
    public String reverseLeftWords(String s, int n) {
        return s.substring(n, s.length()) + s.substring(0, n);
    }
}
方法二:列表遍历拼接

若面试规定不允许使用 切片函数 ,则使用此方法。

class Solution {
    public String reverseLeftWords(String s, int n) {
        StringBuilder res = new StringBuilder();
        for(int i = n; i < s.length(); i++)
            res.append(s.charAt(i));
        for(int i = 0; i < n; i++)
            res.append(s.charAt(i));
        return res.toString();
    }
}

利用求余运算,可以简化代码。

class Solution {
    public String reverseLeftWords(String s, int n) {
        StringBuilder res = new StringBuilder();
        for(int i = n; i < n + s.length(); i++)
            res.append(s.charAt(i % s.length()));
        return res.toString();
    }
}

方法三:字符串遍历拼接

若规定 Python 不能使用 join() 函数,或规定 Java 只能用 String ,则使用此方法。

此方法与 方法二 思路一致,区别是使用字符串代替列表。

class Solution {
    public String reverseLeftWords(String s, int n) {
        String res = "";
        for(int i = n; i < s.length(); i++)
            res += s.charAt(i);
        for(int i = 0; i < n; i++)
            res += s.charAt(i);
        return res;
    }
}

同理,利用求余运算,可以简化代码。

class Solution {
    public String reverseLeftWords(String s, int n) {
        String res = "";
        for(int i = n; i < n + s.length(); i++)
            res += s.charAt(i % s.length());
        return res;
    }
}

总结

String:适用于少量的字符串操作的情况

StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况

StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

以上就是本题的内容和学习过程了,活用字符串的相关容器以及方法是关键。

最后,

他进入了一个梦乡,那里的稻穗比梧桐还高,穗粒比花生还大。风轻轻吹过,他戴着草帽,就坐在稻穗下乘凉。

袁老一路走好,国士无双。

欢迎讨论,共同进步。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值