Merge pull request #100 from peteryuhang/master

Solve problem 0189 & 0242
This commit is contained in:
程序员吴师兄 2020-06-04 11:31:55 +08:00 committed by GitHub
commit 296392f3bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 185 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

View File

@ -0,0 +1,95 @@
# LeetCode第 189 号问题旋转数组
> 本文首发于公众号图解面试算法 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一
>
> 同步博客https://www.algomooc.com
题目来源于 LeetCode 上第 189 号问题旋转数组题目难度为 Easy目前通过率为 41.7%
### 题目描述
给定一个数组将数组中的元素向右移动 k 个位置其中 k 是非负数
**示例 1:**
```
输入: [1,2,3,4,5,6,7] k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 : [7,1,2,3,4,5,6]
向右旋转 2 : [6,7,1,2,3,4,5]
向右旋转 3 : [5,6,7,1,2,3,4]
```
**示例 2:**
```
输入: [-1,-100,3,99] k = 2
输出: [3,99,-1,-100]
解释:
向右旋转 1 : [99,-1,-100,3]
向右旋转 2 : [3,99,-1,-100]
```
**说明:**
* 尽可能想出更多的解决方案至少有三种不同的方法可以解决这个问题
* 要求使用空间复杂度为 O(1) 原地 算法
<br>
### 题目解析
如果没有空间复杂度为 `O(1)` 这个限制这道题相对来说会简单很多需要做的仅仅复制一份数组然后将 `[n - k, n]` 区间上的元素覆盖在数组的开头接着遍历并覆盖剩下的元素即可
不能使用额外的空间意味着你只能从数组本身来入手这里我们可以使用反转数组来解决这道题这是一个 rotate 数组的小技巧如果仔细观察你会发现 **数组经过 rotate 后会变成两个连续的区间段**这两个区间段中的元素顺序和 rotate 之前的顺序是一样的首先我们对数组当中所有的元素进行反转然后分别对这两个区间进行反转这样就可以保证区间内的顺序和之前一样你可以看看动图或者自己动手尝试一下这里并没有复杂的知识点只是数组操作上的小技巧了解了之后可以运用到其他 rotate 数组的场景中
<br>
### 代码实现
```java
class Solution {
public void rotate(int[] nums, int k) {
if (nums.length < k) {
k %= nums.length;
}
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int tmp = nums[start];
nums[start] = nums[end];
nums[end] = tmp;
}
}
}
```
<br>
### 动画描述
![](../Animation/189.gif)
<br>
### 复杂度分析
空间O(1)
时间O(n)
![](../../Pictures/qrcode.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

View File

@ -0,0 +1,90 @@
# LeetCode 242 号问题有效的字母异位词
> 本文首发于公众号图解面试算法 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一
>
> 同步博客https://www.algomooc.com
题目来源于 LeetCode 上第 242 号问题有效的字母异位词题目难度为 Easy目前通过率为 60.5%
### 题目描述
给定两个字符串 s t 编写一个函数来判断 t 是否是 s 的字母异位词
**示例 1:**
```
输入: s = "anagram", t = "nagaram"
输出: true
```
**示例 2:**
```
输入: s = "rat", t = "car"
输出: false
```
**说明**
你可以假设字符串只包含小写字母
**进阶**
如果输入字符串包含 unicode 字符怎么办你能否调整你的解法来应对这种情况
### 题目解析
字母异位词的意思是如果两个字符串互为字母异位词那么两个字符串里的字符数量和种类都一样不一样的是每个字符出现的位置以及先后顺序最简单的方法是直接将字符串按一定的规则排序然后遍历对比即可这种方法省空间但是因为涉及到排序时间复杂度就是 `O(nlgn)`
还有一个类似计数排序的方法就是统计一个字符串里面所有字符对应的个数然后再拿另外一个字符串做对比这么做可以把时间复杂度降到 `O(n)`如果这道题目中的字符串仅仅包含小写字母的话我们可以开辟一个长度是 26 的数组这样就不需要额外的空间但如果说输入的字符串包含 unicode 字符由于 unicode 字符集过于庞大常量级别的数组变得不那么可取我们可以考虑使用散列表这样的结构进行存储逻辑是和之前一样的但是这里的空间复杂度就不再是 `O(1)`而是 `O(n)`
<br>
### 代码实现排序
```java
public boolean isAnagram(String s, String t) {
if ((s == null) || (t == null) || (t.length() != s.length())) {
return false;
}
char[] sArr1 = s.toCharArray();
char[] sArr2 = t.toCharArray();
Arrays.sort(sArr1);
Arrays.sort(sArr2);
return Arrays.equals(sArr1, sArr2);
}
```
### 代码实现哈希
```java
public boolean isAnagram(String s, String t) {
if ((s == null) || (t == null) || (t.length() != s.length())) {
return false;
}
int n = s.length();
Map<Character, Integer> counts = new HashMap<>();
for (int i = 0; i < n; ++i) {
counts.put(s.charAt(i), counts.getOrDefault(s.charAt(i), 0) + 1);
}
for (int i = 0; i < n; ++i) {
counts.put(t.charAt(i), counts.getOrDefault(t.charAt(i), 0) - 1);
if (counts.getOrDefault(t.charAt(i), -1) < 0) {
return false;
}
}
return true;
}
```
### 动画描述
![](../Animation/242.gif)
![](../../Pictures/qrcode.jpg)