Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
wwwanlingxiao
LeetCodeAnimation
Commits
c11ab1e5
Unverified
Commit
c11ab1e5
authored
May 26, 2020
by
chilimyan
Committed by
GitHub
May 26, 2020
Browse files
Merge pull request #4 from MisterBooo/master
更新项目
parents
244bfaad
62bcddcb
Changes
33
Hide whitespace changes
Inline
Side-by-side
0260-Single-Number-III/Article/0260-Single-Number-III.md
0 → 100644
View file @
c11ab1e5
# LeetCode 第 260 号问题:只出现一次的数字 III
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
>
> 同步博客:https://www.algomooc.com
题目来源于 LeetCode 上第 260 号问题:只出现一次的数字 III。题目难度为 Medium,目前通过率为 72.1% 。
## 题目描述
给定一个整数数组
`nums`
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。
**示例:**
```
输入: [1,2,1,3,2,5]
输出: [3,5]
```
**注意:**
1.
结果输出的顺序并不重要,对于上面的例子, [5, 3] 也是正确答案。
2.
你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?
<br>
## 题目解析
第三道题目,和第一道题目只变化了一点,就是输入数组中除了
**两**
个元素出现了一次,其余的都出现了两次。我们依然可以从第一道题目的解法去思考这道题,如果我们还是按照第一题的做法,最后我们得到的答案将会是
`ele1 ^ ele2`
的结果,我们需要思考如何从这个结果出发,得到
`ele1`
和
`ele2`
。首先思考一个问题
`ele1 ^ ele2`
的结果具体是什么,或者说里面有什么样的信息,异或操作是将相同的 bit 位置 0,相异的置 1,也就是说
**`ele1` 和 `ele2` 异或的结果中为 1 的 bit 位是两个元素相异的 bit 位,再进一步讲,我们可以用这个 bit 位来区分两个元素**
。于是在第一题的基础之上,用一个 bit 位作为判断条件,来决定当前遍历到的元素和那个值进行异或,因为这时我们要求的值有两个。
从上面这些题目中你可以看到位运算的强大,三道系列题目的时间复杂度均为
`O(n)`
,但是位运算是更加底层的运算,实际时间消耗会比正常操作要更快一些。在理解位运算的时候,
**试着把 bit 作为最小单位去思考,或许会有不一样的发现**
。
<br>
### 代码实现
```
java
public
int
[]
singleNumber
(
int
[]
nums
)
{
if
(
nums
==
null
||
nums
.
length
==
0
)
{
return
new
int
[
2
];
}
int
different
=
0
;
for
(
int
i
:
nums
)
{
different
^=
i
;
}
// 这个操作是取 different 从左往右最后一个为 1 的 bit 位
different
&=
-
different
;
int
[]
ans
=
{
0
,
0
};
for
(
int
i
:
nums
)
{
if
((
different
&
i
)
==
0
)
{
ans
[
0
]
^=
i
;
}
else
{
ans
[
1
]
^=
i
;
}
}
return
ans
;
}
```
<br>
### 动画演示


\ No newline at end of file
0530-minimum-absolute-difference-in-bst/Animation/0530.m4v
0 → 100644
View file @
c11ab1e5
File added
0530-minimum-absolute-difference-in-bst/Article/0530-minimum-absolute-difference-in-bst
0 → 100644
View file @
c11ab1e5
# 530. 二叉搜索树的最小绝对差
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
>
> 同步博客:https://www.algomooc.com
题目来源于 LeetCode 上 530. 二叉搜索树的最小绝对差. 是关于树的一道题。
## 题目
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
示例:
```
输入:
1
\
3
/
2
输出:
1
解释:
最小绝对差为 1,其中 2 和 1 的差的绝对值为 1(或者 2 和 3)。
```
提示:
树中至少有 2 个节点。
本题与 783 https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/ 相同
## 题目解析
计算树中任意两节点的差的绝对值的最小值,那么肯定是要遍历树,然后相邻节点求差对比是不是最小的。
二叉树的遍历有三种,前序遍历,中序遍历,后序遍历。
题目中给的是二叉搜索树,二叉搜索树有一个特色,就是中序遍历出来的结果,值是按照从小到大排列的。
所以我们只要中序遍历,保存上一个节点,然后遍历的时候取得当前节点和上一个节点的值的绝对值,如果比当前最小差还要小,那么更新最小差。
中序遍历是遍历左子树,然后根节点,最后是右子树,我们用递归去实现。
## 动画理解
<video id="video" controls="" preload="none" >
<source id="mp4" src="../Animation/0530.m4v" type="video/mp4">
</video>
## 参考代码
```javaScript
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var getMinimumDifference = function(root) {
let min = Number.MAX_VALUE
let preNode = null
var travelTree = function (node) {
if (node) {
travelTree(node.left)
if(preNode) {
min = Math.min(min, Math.abs(preNode.val - node.val))
}
preNode = node
travelTree(node.right)
}
}
travelTree(root)
return min
};
```
## 复杂度分析
时间复杂度:O(N),N为树中节点个数。
空间复杂度:O(log(N))。

\ No newline at end of file
0695-Max-Area-of-Island/Animation/Animation.gif
0 → 100644
View file @
c11ab1e5
3.03 MB
0695-Max-Area-of-Island/Animation/Animation.m4v
0 → 100644
View file @
c11ab1e5
File added
0695-Max-Area-of-Island/Article/0695-Max-Area-of-Island.md
0 → 100644
View file @
c11ab1e5
# LeetCode 图解 |
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
>
> 同步博客:https://www.algomooc.com
本题解作者:nettee
## 题目描述
给定一个包含了一些
`0`
和
`1`
的非空二维数组
`grid`
。
一个
**岛屿**
是由一些相邻的
`1`
(代表土地) 构成的组合,这里的「相邻」要求两个
`1`
必须在水平或者竖直方向上相邻。你可以假设
`grid`
的四个边缘都被
`0`
(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为
`0`
。)
**示例 1:**
```
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
```
对于上面这个给定矩阵应返回 6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的
`1`
。
**示例 2:**
```
[[0,0,0,0,0,0,0,0]]
```
对于上面这个给定的矩阵, 返回 0。
注意: 给定的矩阵
`grid`
的长度和宽度都不超过 50。
## 题目解析
这道题的主要思路是深度优先搜索。每次走到一个是 1 的格子,就搜索整个岛屿,并计算当前岛屿的面积。最后返回岛屿面积的最大值。
网格可以看成是一个无向图的结构,每个格子和它上下左右的四个格子相邻。如果四个相邻的格子坐标合法,且是陆地,就可以继续搜索。
在深度优先搜索的时候要注意避免重复遍历。我们可以把已经遍历过的陆地改成 2,这样遇到 2 我们就知道已经遍历过这个格子了,不进行重复遍历。
## 动画理解

## 参考代码
C++ 代码:
```
C++
class Solution {
public:
int maxAreaOfIsland(vector<vector<int>>& grid) {
int res = 0;
for (int r = 0; r < grid.size(); r++) {
for (int c = 0; c < grid[0].size(); c++) {
if (grid[r][c] == 1) {
int a = area(grid, r, c);
res = max(res, a);
}
}
}
return res;
}
int area(vector<vector<int>>& grid, int r, int c) {
if (!(inArea(grid, r, c))) {
return 0;
}
if (grid[r][c] != 1) {
return 0;
}
grid[r][c] = 2;
return 1
+ area(grid, r - 1, c)
+ area(grid, r + 1, c)
+ area(grid, r, c - 1)
+ area(grid, r, c + 1);
}
bool inArea(vector<vector<int>>& grid, int r, int c) {
return 0 <= r && r < grid.size()
&& 0 <= c && c < grid[0].size();
}
};
```
Java 代码:
```
Java
class Solution {
public int maxAreaOfIsland(int[][] grid) {
int res = 0;
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[0].length; c++) {
if (grid[r][c] == 1) {
int a = area(grid, r, c);
res = Math.max(res, a);
}
}
}
return res;
}
int area(int[][] grid, int r, int c) {
if (!inArea(grid, r, c)) {
return 0;
}
if (grid[r][c] != 1) {
return 0;
}
grid[r][c] = 2;
return 1
+ area(grid, r - 1, c)
+ area(grid, r + 1, c)
+ area(grid, r, c - 1)
+ area(grid, r, c + 1);
}
boolean inArea(int[][] grid, int r, int c) {
return 0 <= r && r < grid.length
&& 0 <= c && c < grid[0].length;
}
}
```
Python 代码:
```
Python
class Solution:
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
res = 0
for r in range(len(grid)):
for c in range(len(grid[0])):
if grid[r][c] == 1:
a = self.area(grid, r, c)
res = max(res, a)
return res
def area(self, grid: List[List[int]], r: int, c: int) -> int:
if not self.inArea(grid, r, c):
return 0
if grid[r][c] != 1:
return 0
grid[r][c] = 2
return 1 \
+ self.area(grid, r - 1, c) \
+ self.area(grid, r + 1, c) \
+ self.area(grid, r, c - 1) \
+ self.area(grid, r, c + 1)
def inArea(self, grid: List[List[int]], r: int, c: int) -> bool:
return 0 <= r < len(grid) and 0 <= c < len(grid[0])
```
## 复杂度分析
设网格的边长为 n,则时间复杂度为 O(n²)。
\ No newline at end of file
0942-di-String-Match/Animation/0942-di-String-Match.mp4
0 → 100644
View file @
c11ab1e5
File added
0942-di-String-Match/Animation/0942-di-String-Match01.gif
0 → 100644
View file @
c11ab1e5
1.66 MB
0942-di-String-Match/Animation/0942-di-String-Match02.gif
0 → 100644
View file @
c11ab1e5
1.35 MB
0942-di-String-Match/Article/0942-di-String-Match.md
0 → 100644
View file @
c11ab1e5
## LeetCode第942号问题:增减字符串匹配
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
>
> 同步个人博客:www.zhangxiaoshuai.fun
本题在leetcode中题目序号942,属于easy级别,目前通过率为71.4%
### 题目描述:
```
给定只含 "I"(增大)或 "D"(减小)的字符串 S ,令 N = S.length。
返回 [0, 1, ..., N] 的任意排列 A 使得对于所有 i = 0, ..., N-1,都有:
如果 S[i] == "I",那么 A[i] < A[i+1]
如果 S[i] == "D",那么 A[i] > A[i+1]
示例 1:
输出:"IDID"
输出:[0,4,1,3,2]
示例 2:
输出:"III"
输出:[0,1,2,3]
示例 3:
输出:"DDI"
输出:[3,2,0,1]
提示:
1 <= S.length <= 10000
S 只包含字符 "I" 或 "D"
```
**题目分析:**
```
题目中的意思很明确,我们只要满足给出的两个条件即可。
1.假如字符串的长度为N,那么目标数组的长度就为N+1;
2.数组中的数字都是从0~N,且没有重复;
3.遇见‘I’,要增加;遇见‘D’要减少;
```
### GIF动画演示:

### 代码:
```
java
//这里搬运下官方的解法
public
int
[]
diStringMatch
(
String
S
)
{
int
N
=
S
.
length
();
int
lo
=
0
,
hi
=
N
;
int
[]
ans
=
new
int
[
N
+
1
];
for
(
int
i
=
0
;
i
<
N
;
++
i
)
{
if
(
S
.
charAt
(
i
)
==
'I'
)
ans
[
i
]
=
lo
++;
else
ans
[
i
]
=
hi
--;
}
ans
[
N
]
=
lo
;
return
ans
;
}
```
**虽然上述代码很简洁,好像已经不需要我们去实现什么;但是满足条件的序列并不止一种,官方的好像只能通过一种,下面的代码虽然有些冗余,但是得出的序列是满足题意要求的,但是并不能AC;**
### 思路:
```
(1)如果遇见的是‘I’,那么对应数组当前位置的数字要小于它右边的第一个数字
(2)如果遇见的是‘D’,那么对应数组当前位置的数字要大于它右边的第一个数字
首先对目标数组进行初始化,赋值0~N
我们开始遍历字符串,如果遇见‘I’就判断对应数组该位置上的数是否满足(1)号条件
如果满足,跳过本次循环;如果不满足,交换两个数字的位置;
对于‘D’,也是同样的思路;
```
### GIF动画演示:

### 代码:
```
java
public
int
[]
diStringMatch
(
String
S
)
{
int
[]
res
=
new
int
[
S
.
length
()+
1
];
String
[]
s
=
S
.
split
(
""
);
for
(
int
i
=
0
;
i
<
res
.
length
;
i
++)
{
res
[
i
]
=
i
;
}
for
(
int
i
=
0
;
i
<
s
.
length
;
i
++)
{
if
(
s
[
i
].
equals
(
"I"
))
{
//判断指定位置的数字是否符合条件
if
(
res
[
i
]
<
res
[
i
+
1
])
{
continue
;
}
else
{
//交换两个数字的位置
res
[
i
]
=
res
[
i
]
^
res
[
i
+
1
];
res
[
i
+
1
]
=
res
[
i
]
^
res
[
i
+
1
];
res
[
i
]
=
res
[
i
]
^
res
[
i
+
1
];
}
}
else
{
if
(
res
[
i
]
>
res
[
i
+
1
])
{
continue
;
}
else
{
res
[
i
]
=
res
[
i
]
^
res
[
i
+
1
];
res
[
i
+
1
]
=
res
[
i
]
^
res
[
i
+
1
];
res
[
i
]
=
res
[
i
]
^
res
[
i
+
1
];
}
}
}
return
res
;
}
```
**以上内容如有错误、不当之处,欢迎批评指正。**
\ No newline at end of file
1054-rearrangeBarcodes/Animation/1054-rearrangeBarcodes.gif
0 → 100644
View file @
c11ab1e5
3.69 MB
1054-rearrangeBarcodes/Animation/1054-rearrangeBarcodes.mp4
0 → 100644
View file @
c11ab1e5
File added
1054-rearrangeBarcodes/Article/1054-rearrangeBarcodes.md
0 → 100644
View file @
c11ab1e5
## LeetCode第1054号问题:距离相等的条形码
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
>
> 同步个人博客:www.zhangxiaoshuai.fun
**本题选自leetcode第1054号问题,medium级别,目前通过率33.3%**
**题目描述:**
在一个仓库里,有一排条形码,其中第 i 个条形码为 barcodes[i]。
请你重新排列这些条形码,使其中两个相邻的条形码不能相等。
你可以返回任何满足该要求的答案,此题保证存在答案。
示例 1:
输入:[1,1,1,2,2,2]
输出:[2,1,2,1,2,1]
示例 2:
输入:[1,1,1,1,2,2,3,3]
输出:[1,3,1,3,2,1,2,1]
提示:
1 <= barcodes.length <= 10000
1 <= barcodes[i] <= 10000
### 题目分析:
1.
首先我们需要将每个条形码和出现的次数作一记录,为了存取方便,这里使用数组(题目中已经给出了数组的最大和最小长度)进行操作;
2.
找出其中出现最多次数的条形码,拿到该barcode和count;
3.
先将出现次数最多的条形码存入目标数组中(偶数位或者奇数位),并对记录数组作一更新;
4.
随后将剩余的barcode填充进目标数组中。
### GIF动画展示:

### 代码:
```
java
public
static
int
[]
rearrangeBarcodes
(
int
[]
barcodes
){
int
[]
address
=
new
int
[
10001
];
for
(
int
barcode
:
barcodes
)
address
[
barcode
]++;
// 找到出现次数最多的barcode
int
maxCode
=
0
,
maxCount
=
0
;
for
(
int
i
=
0
;
i
<
address
.
length
;
i
++)
{
if
(
maxCount
<
address
[
i
])
{
maxCode
=
i
;
maxCount
=
address
[
i
];
}
}
int
index
=
0
;
// 先填充最大的那一位barcode
for
(;
address
[
maxCode
]
>
0
;
index
+=
2
)
{
barcodes
[
index
]
=
maxCode
;
address
[
maxCode
]--;
}
// 继续填充剩余的条形码
for
(
int
i
=
1
;
i
<
address
.
length
;
i
++)
{
while
(
address
[
i
]
>
0
)
{
//偶数位填充完毕
if
(
index
>=
barcodes
.
length
)
index
=
1
;
barcodes
[
index
]
=
i
;
address
[
i
]--;
index
+=
2
;
}
}
return
barcodes
;
}
```
\ No newline at end of file
Prev
1
2
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment