From f55786bdb2c01e3618d8b5b5b2d046e0581a5d89 Mon Sep 17 00:00:00 2001 From: Flow-sandyu <72751523+Flow-sandyu@users.noreply.github.com> Date: Sun, 2 Oct 2022 14:24:52 +0800 Subject: [PATCH 1/6] =?UTF-8?q?Update=EF=BC=9A=E5=89=91=E6=8C=87Offer05.?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E7=A9=BA=E6=A0=BC.md=20java=E7=89=88?= =?UTF-8?q?=E6=9C=AC=20=E5=8F=98=E9=87=8F=E7=9A=84=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=92=8C=E5=91=BD=E5=90=8D=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 159 行 StringBuffer str 改成 String s 并把后续的 str 都换成 s 不然原答案是不能AC 的 --- problems/剑指Offer05.替换空格.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/problems/剑指Offer05.替换空格.md b/problems/剑指Offer05.替换空格.md index e1ccc458..7a2712ef 100644 --- a/problems/剑指Offer05.替换空格.md +++ b/problems/剑指Offer05.替换空格.md @@ -156,20 +156,20 @@ char* replaceSpace(char* s){ Java: ```Java //使用一个新的对象,复制 str,复制的过程对其判断,是空格则替换,否则直接复制,类似于数组复制 -public static String replaceSpace(StringBuffer str) { - if (str == null) { +public static String replaceSpace(String s) { + if (s == null) { return null; } - //选用 StringBuilder 单线程使用,比较快,选不选都行 + //选用 StringBuilder 单线程使用,比较快,选不选都行 StringBuilder sb = new StringBuilder(); - //使用 sb 逐个复制 str ,碰到空格则替换,否则直接复制 - for (int i = 0; i < str.length(); i++) { - //str.charAt(i) 为 char 类型,为了比较需要将其转为和 " " 相同的字符串类型 - //if (" ".equals(String.valueOf(str.charAt(i)))){ + //使用 sb 逐个复制 s ,碰到空格则替换,否则直接复制 + for (int i = 0; i < s.length(); i++) { + //s.charAt(i) 为 char 类型,为了比较需要将其转为和 " " 相同的字符串类型 + //if (" ".equals(String.valueOf(s.charAt(i)))){} if (s.charAt(i) == ' ') { sb.append("%20"); } else { - sb.append(str.charAt(i)); + sb.append(s.charAt(i)); } } return sb.toString(); From e9a164add1f9c82318597bfbbc10737f700a8298 Mon Sep 17 00:00:00 2001 From: Flow-sandyu <72751523+Flow-sandyu@users.noreply.github.com> Date: Mon, 3 Oct 2022 17:59:23 +0800 Subject: [PATCH 2/6] =?UTF-8?q?update=EF=BC=9A0151.=E7=BF=BB=E8=BD=AC?= =?UTF-8?q?=E5=AD=97=E7=AC=A6=E4=B8=B2=E9=87=8C=E7=9A=84=E5=8D=95=E8=AF=8D?= =?UTF-8?q?.md=20java=20=E7=89=88=E6=9C=AC=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=A7=A3=E6=B3=95=E5=9B=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 时间复杂度 O(n) 参考卡哥 c++ 代码的实现:先移除多余空格,再将整个字符串反转,最后把单词逐个反转 --- problems/0151.翻转字符串里的单词.md | 68 ++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/problems/0151.翻转字符串里的单词.md b/problems/0151.翻转字符串里的单词.md index a848d6a3..5a8f8094 100644 --- a/problems/0151.翻转字符串里的单词.md +++ b/problems/0151.翻转字符串里的单词.md @@ -360,6 +360,74 @@ class Solution { } ``` +```java +/* + * 解法四:时间复杂度 O(n) + * 参考卡哥 c++ 代码的实现:先移除多余空格,再将整个字符串反转,最后把单词逐个反转 + */ +class Solution { + //用 char[] 来实现 String 的 removeExtraSpaces,reverse 操作 + public String reverseWords(String s) { + char[] chars = s.toCharArray(); + //1.去除首尾以及中间多余空格 + chars = removeExtraSpaces(chars); + //2.整个字符串反转 + reverse(chars, 0, chars.length - 1); + //3.单词反转 + reverseEachWord(chars); + return new String(chars); + } + + //1.用 快慢指针 去除首尾以及中间多余空格,可参考数组元素移除的题解 + public char[] removeExtraSpaces(char[] chars) { + int slow = 0; + for (int fast = 0; fast < chars.length; fast++) { + //先用 fast 移除所有空格 + if (chars[fast] != ' ') { + //在用 slow 加空格。 除第一个单词外,单词末尾要加空格 + if (slow != 0) + chars[slow++] = ' '; + //fast 遇到空格或遍历到字符串末尾,就证明遍历完一个单词了 + while (fast < chars.length && chars[fast] != ' ') + chars[slow++] = chars[fast++]; + } + } + //相当于 c++ 里的 resize() + char[] newChars = new char[slow]; + System.arraycopy(chars, 0, newChars, 0, slow); + return newChars; + } + + //双指针实现指定范围内字符串反转,可参考字符串反转题解 + public 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--; + } + } + + //3.单词反转 + public void reverseEachWord(char[] chars) { + int start = 0; + //end <= s.length() 这里的 = ,是为了让 end 永远指向单词末尾后一个位置,这样 reverse 的实参更好设置 + for (int end = 0; end <= chars.length; end++) { + // end 每次到单词末尾后的空格或串尾,开始反转单词 + if (end == chars.length || chars[end] == ' ') { + reverse(chars, start, end - 1); + start = end + 1; + } + } + } +} +``` + python: ```Python From 42d72e2a313cc0409b183923c1d3d8d9bcc38fdf Mon Sep 17 00:00:00 2001 From: Flow-sandyu <72751523+Flow-sandyu@users.noreply.github.com> Date: Mon, 3 Oct 2022 18:14:34 +0800 Subject: [PATCH 3/6] =?UTF-8?q?update=EF=BC=9A0151.=E7=BF=BB=E8=BD=AC?= =?UTF-8?q?=E5=AD=97=E7=AC=A6=E4=B8=B2=E9=87=8C=E7=9A=84=E5=8D=95=E8=AF=8D?= =?UTF-8?q?.md=20java=20=E7=89=88=E6=9C=AC=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=A7=A3=E6=B3=95=E5=9B=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 时间复杂度 O(n) 参考卡哥 c++ 代码的实现:先移除多余空格,再将整个字符串反转,最后把单词逐个反转 有别于解法一 :没有用 StringBuilder 实现,而是对 String 的 char[] 数组操作来实现以上三个步骤 --- problems/0151.翻转字符串里的单词.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/problems/0151.翻转字符串里的单词.md b/problems/0151.翻转字符串里的单词.md index 5a8f8094..be35c2f2 100644 --- a/problems/0151.翻转字符串里的单词.md +++ b/problems/0151.翻转字符串里的单词.md @@ -363,7 +363,8 @@ class Solution { ```java /* * 解法四:时间复杂度 O(n) - * 参考卡哥 c++ 代码的实现:先移除多余空格,再将整个字符串反转,最后把单词逐个反转 + * 参考卡哥 c++ 代码的三步骤:先移除多余空格,再将整个字符串反转,最后把单词逐个反转 + * 有别于解法一 :没有用 StringBuilder 实现,而是对 String 的 char[] 数组操作来实现以上三个步骤 */ class Solution { //用 char[] 来实现 String 的 removeExtraSpaces,reverse 操作 From b24e3f04ac05798947ac1bd580c7a094c3353e19 Mon Sep 17 00:00:00 2001 From: Flow-sandyu <72751523+Flow-sandyu@users.noreply.github.com> Date: Mon, 3 Oct 2022 19:37:53 +0800 Subject: [PATCH 4/6] =?UTF-8?q?update=EF=BC=9A=E5=89=91=E6=8C=87Offer58-II?= =?UTF-8?q?.=E5=B7=A6=E6=97=8B=E8=BD=AC=E5=AD=97=E7=AC=A6=E4=B8=B2.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 解法二:空间复杂度:O(1)。用原始数组来进行反转操作 思路:先整个字符串反转,再反转前面的,最后反转后面 n 个 --- .../剑指Offer58-II.左旋转字符串.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/problems/剑指Offer58-II.左旋转字符串.md b/problems/剑指Offer58-II.左旋转字符串.md index bf5d3f90..b14c26cc 100644 --- a/problems/剑指Offer58-II.左旋转字符串.md +++ b/problems/剑指Offer58-II.左旋转字符串.md @@ -115,6 +115,29 @@ class Solution { } ``` +```java +//解法二:空间复杂度:O(1)。用原始数组来进行反转操作 +//思路为:先整个字符串反转,再反转前面的,最后反转后面 n 个 +class Solution { + public String reverseLeftWords(String s, int n) { + char[] chars = s.toCharArray(); + reverse(chars, 0, chars.length - 1); + reverse(chars, 0, chars.length - 1 - n); + reverse(chars, chars.length - n, chars.length - 1); + return new String(chars); + } + + public void reverse(char[] chars, int left, int right) { + while (left < right) { + chars[left] ^= chars[right]; + chars[right] ^= chars[left]; + chars[left] ^= chars[right]; + left++; + right--; + } + } +``` + python: ```python From f86b17a1f09915988a2a6dda54f4b8a9b1d5dca7 Mon Sep 17 00:00:00 2001 From: Flow-sandyu <72751523+Flow-sandyu@users.noreply.github.com> Date: Tue, 4 Oct 2022 21:40:54 +0800 Subject: [PATCH 5/6] =?UTF-8?q?update=EF=BC=9A=E5=8F=8C=E6=8C=87=E9=92=88?= =?UTF-8?q?=E6=80=BB=E7=BB=93.md=20=E6=9B=B4=E6=94=B9=E9=94=99=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更改错字 --- problems/双指针总结.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/双指针总结.md b/problems/双指针总结.md index 06752cac..5abcec53 100644 --- a/problems/双指针总结.md +++ b/problems/双指针总结.md @@ -42,7 +42,7 @@ for (int i = 0; i < array.size(); i++) { **其实很多数组(字符串)填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。** -那么在[字符串:花式反转还不够!](https://programmercarl.com/0151.翻转字符串里的单词.html)中,我们使用双指针法,用O(n)的时间复杂度完成字符串删除类的操作,因为题目要产出冗余空格。 +那么在[字符串:花式反转还不够!](https://programmercarl.com/0151.翻转字符串里的单词.html)中,我们使用双指针法,用O(n)的时间复杂度完成字符串删除类的操作,因为题目要删除冗余空格。 **在删除冗余空格的过程中,如果不注意代码效率,很容易写成了O(n^2)的时间复杂度。其实使用双指针法O(n)就可以搞定。** From 680cf3dbd74d4266d1a077c493d0c440fd6bebfb Mon Sep 17 00:00:00 2001 From: Flow-sandyu <72751523+Flow-sandyu@users.noreply.github.com> Date: Wed, 5 Oct 2022 10:12:19 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=200225.=E7=94=A8?= =?UTF-8?q?=E9=98=9F=E5=88=97=E5=AE=9E=E7=8E=B0=E6=A0=88.md=20java=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化,使用一个 Queue 实现 对比 『使用一个 Deque 实现』 的解法,我把移动元素的代码放到 push 方法里,代码看起来更简洁 --- problems/0225.用队列实现栈.md | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/problems/0225.用队列实现栈.md b/problems/0225.用队列实现栈.md index fb2851f1..4412a819 100644 --- a/problems/0225.用队列实现栈.md +++ b/problems/0225.用队列实现栈.md @@ -292,6 +292,40 @@ class MyStack { } ``` +优化,使用一个 Queue 实现 +```java +class MyStack { + + Queue queue; + + public MyStack() { + queue = new LinkedList<>(); + } + + //每 offer 一个数(A)进来,都重新排列,把这个数(A)放到队列的队首 + public void push(int x) { + queue.offer(x); + int size = queue.size(); + //移动除了 A 的其它数 + while (size-- > 1) + queue.offer(queue.poll()); + } + + public int pop() { + return queue.poll(); + } + + public int top() { + return queue.peek(); + } + + public boolean empty() { + return queue.isEmpty(); + } +} + +``` + Python: ```python