Skip to content

Commit

Permalink
增加多个模块
Browse files Browse the repository at this point in the history
  • Loading branch information
luzhipeng committed Mar 29, 2019
1 parent f4d5227 commit ca1ecbb
Show file tree
Hide file tree
Showing 6 changed files with 315 additions and 34 deletions.
35 changes: 32 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,23 @@

leetcode 题解,记录自己的 leecode 解题之路。

本仓库目前分为四个部分:

- 第一个部分是 leetcode 经典题目的解析,包括思路,关键点和具体的代码实现。

- 第二部分是对于数据结构与算法的总结

- 第三部分是 anki 卡片, 将 leetcode 题目按照一定的方式记录在 anki 中,方便大家记忆。

- 第四部分是计划, 这里会记录将来要加入到以上三个部分内容

> 只有熟练掌握基础的数据结构与算法,才能对复杂问题迎刃有余
## 传送门

### 简单难度
### leetcode 经典题目的解析

#### 简单难度

- [20. Valid Parentheses](./problems/validParentheses.md)
- [26.remove-duplicates-from-sorted-array](./problems/26.remove-duplicates-from-sorted-array.md)
Expand All @@ -16,7 +30,7 @@ leetcode 题解,记录自己的 leecode 解题之路。
- [283.move-zeroes](./problems/283.move-zeroes.md)
- [349.intersection-of-two-arrays](./problems/349.intersection-of-two-arrays.md)

### 中等难度
#### 中等难度

- [2. Add Two Numbers](https://github.com/azl397985856/leetcode/blob/master/addTwoNumbers.md)
- [3. Longest Substring Without Repeating Characters](https://github.com/azl397985856/leetcode/blob/master/longestSubstringWithoutRepeatingCharacters.md)
Expand All @@ -38,7 +52,22 @@ leetcode 题解,记录自己的 leecode 解题之路。
- [199.binary-tree-right-side-view](./problems/199.binary-tree-right-side-view.md)
- [209.minimum-size-subarray-sum](./problems/209.minimum-size-subarray-sum.md)

### 困难难度
#### 困难难度

- [145.binary-tree-postorder-traversal](./problems/145.binary-tree-postorder-traversal.md)
- [146.lru-cache](./problems/146.lru-cache.md)

### 数据结构与算法的总结

- [basic-data-structure](./thinkings/basic-data-structure.md)
- [binary-tree-traversal](./thinkings/binary-tree-traversal.md)

### anki 卡片

TODO

### 计划

[301.remove-invalid-parentheses]

[609.find-duplicate-file-in-system]
59 changes: 28 additions & 31 deletions problems/136.single-number.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

## 题目地址

https://leetcode.com/problems/single-number/description/

## 题目描述
Expand All @@ -11,22 +11,24 @@ Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
```

## 思路

根据题目描述,由于加上了时间复杂度必须是O(n),并且空间复杂度为O(1)的条件,因此不能用排序方法,也不能使用map数据结构
根据题目描述,由于加上了时间复杂度必须是 O(n),并且空间复杂度为 O(1)的条件,因此不能用排序方法,也不能使用 map 数据结构

我们可以利用二进制异或的性质来完成,将所有数字异或即得到唯一出现的数字。

## 关键点

1. 异或的性质
两个数字异或的结果`a^b`是将a和b的二进制每一位进行运算,得出的数字。 运算的逻辑是
如果同一位的数字相同则为0,不同则为1
两个数字异或的结果`a^b`是将 a 和 b 的二进制每一位进行运算,得出的数字。 运算的逻辑是
如果同一位的数字相同则为 0,不同则为 1

2. 异或的规律

- 任何数和本身异或则为`0`

- 任何数和0异或是`本身`
- 任何数和 0 异或是`本身`

3. 很多人只是记得异或的性质和规律,但是缺乏对其本质的理解,导致很难想到这种解法(我本人也没想到)

Expand All @@ -48,52 +50,49 @@ Your algorithm should have a linear runtime complexity. Could you implement it w
*
* Given a non-empty array of integers, every element appears twice except for
* one. Find that single one.
*
*
* Note:
*
*
* Your algorithm should have a linear runtime complexity. Could you implement
* it without using extra memory?
*
*
* Example 1:
*
*
*
*
* Input: [2,2,1]
* Output: 1
*
*
*
*
* Example 2:
*
*
*
*
* Input: [4,1,2,1,2]
* Output: 4
*
*
*
*
*/
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function(nums) {
let ret = 0;
for (let index = 0; index < nums.length; index++) {
const element = nums[index];
ret = ret ^ element;

}
return ret;
let ret = 0;
for (let index = 0; index < nums.length; index++) {
const element = nums[index];
ret = ret ^ element;
}
return ret;
};

```

## 延伸

有一个 n 个元素的数组,除了两个数只出现一次外,其余元素都出现两次,让你找出这两个只出现一次的数分别是几,要求时间复杂度为 O(n) 且再开辟的内存空间固定(与 n 无关)。


和上面一样,只是这次不是一个数字,而是两个数字。还是按照上面的思路,我们进行一次全员异或操作,
得到的结果就是那两个只出现一次的不同的数字的异或结果。

我们刚才讲了异或的规律中有一个`任何数和本身异或则为0`因此我们的思路是能不能将这两个不同的数字分成两组A和B
我们刚才讲了异或的规律中有一个`任何数和本身异或则为0`因此我们的思路是能不能将这两个不同的数字分成两组 A 和 B
分组需要满足两个条件.

1. 两个独特的的数字分成不同组
Expand All @@ -104,12 +103,10 @@ var singleNumber = function(nums) {

问题的关键点是我们怎么进行分组呢?

由于异或的性质是,同一位相同则为0,不同则为1. 我们将所有数字异或的结果一定不是0,也就是说至少有一位是1.
由于异或的性质是,同一位相同则为 0,不同则为 1. 我们将所有数字异或的结果一定不是 0,也就是说至少有一位是 1.

我们随便取一个, 分组的依据就来了, 就是你取的那一位是0分成1组,那一位是1的分成一组
这样肯定能保证`2. 相同的数字分成相同组`, 不同的数字会被分成不同组么。 很明显当然可以, 因此我们选择是1,也就是
我们随便取一个, 分组的依据就来了, 就是你取的那一位是 0 分成 1 组,那一位是 1 的分成一组
这样肯定能保证`2. 相同的数字分成相同组`, 不同的数字会被分成不同组么。 很明显当然可以, 因此我们选择是 1,也就是
`两个独特的的数字`在那一位一定是不同的,因此两个独特元素一定会被分成不同组。

Done!


41 changes: 41 additions & 0 deletions thinkings/basic-data-structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 基础的数据结构

## 线性结构

### 数组

React Hooks

### 队列

message queue

###

call stack, view stack

### 链表

React fiber

### 非线性结构

##

### 二叉树

####

优先级队列

#### 二叉查找树

### 平衡树

database engine

#### AVL

#### 红黑树

##
79 changes: 79 additions & 0 deletions thinkings/binary-tree-traversal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# 二叉树的遍历算法

## 概述

二叉树作为一个基础的数据结构,遍历算法作为一个基础的算法,两者结合当然是经典的组合了。
很多题目都会有 ta 的身影,有直接问二叉树的遍历的,有间接问的。

> 你如果掌握了二叉树的遍历,那么也许其他复杂的树对于你来说也并不遥远了
二叉数的遍历主要有前中后遍历和层次遍历。 前中后属于 DFS,层次遍历属于 BFS。
DFS 和 BFS 都有着自己的应用,比如 leetcode 301 号问题和 609 号问题。

DFS 都可以使用栈来简化操作,并且其实树本身是一种递归的数据结构,因此递归和栈对于 DFS 来说是两个关键点。

BFS 的关键点在于如何记录每一层次是否遍历完成, 我们可以用一个标识位来表式当前层的结束。

下面我们依次讲解:

## 前序遍历

相关问题[144.binary-tree-preorder-traversal](../problems/144.binary-tree-preorder-traversal.md)

前序遍历的顺序是`根-左-右`

思路是:

1. 先将根结点入栈

2. 出栈一个元素,将右节点和左节点依次入栈

3. 重复 2 的步骤

总结: 典型的递归数据结构,典型的用栈来简化操作的算法。

## 中序遍历

相关问题[94.binary-tree-inorder-traversal](../problems/94.binary-tree-inorder-traversal.md)

中序遍历的顺序是 `左-根-右`,根节点不是先输出,这就有一点点复杂了。

1. 根节点入栈

2. 判断有没有左节点,如果有,则入栈,直到叶子节点

> 此时栈中保存的就是所有的左节点和根节点。
3. 出栈,判断有没有右节点,有则入栈,继续执行 2

## 后序遍历

相关问题[145.binary-tree-postorder-traversal](../problems/145.binary-tree-postorder-traversal.md)

后序遍历的顺序是 `左-右-根`

这个就有点难度了,要不也不会是 leetcode 困难的 难度啊。

其实这个也是属于根节点先不输出,并且根节点是最后输出。 这里可以采用一种讨巧的做法,
就是记录当前节点状态,如果 1. 当前节点是叶子节点或者 2.当前节点的左右子树都已经遍历过了,那么就可以出栈了。

对于 1. 当前节点是叶子节点,这个比较好判断,只要判断 left 和 rigt 是否同时为 null 就好。

对于 2. 当前节点的左右子树都已经遍历过了, 我们只需要用一个变量记录即可。最坏的情况,我们记录每一个节点的访问状况就好了,空间复杂度 O(n)
但是仔细想一下,我们使用了栈的结构,从叶子节点开始输出,我们记录一个当前出栈的元素就好了,空间复杂度 O(1), 具体请查看上方链接。

## 层次遍历

层次遍历的关键点在于如何记录每一层次是否遍历完成, 我们可以用一个标识位来表式当前层的结束。

具体做法:

1. 根节点入队列, 并入队列一个特殊的标识位,此处是 null

2. 出队列

3. 判断是不是 null, 如果是则代表本层已经结束。我们再次判断是否当前队列为空,如果不为空继续入队一个 null,否则说明遍历已经完成,我们什么都不不用做

4. 如果不为 null,说明这一层还没完,则将其左右子树依次入队列。

相关问题[102.binary-tree-level-order-traversal](../problems/102.binary-tree-level-order-traversal.md)
48 changes: 48 additions & 0 deletions todo/301.remove-invalid-parentheses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* @lc app=leetcode id=301 lang=javascript
*
* [301] Remove Invalid Parentheses
*
* https://leetcode.com/problems/remove-invalid-parentheses/description/
*
* algorithms
* Hard (38.52%)
* Total Accepted: 114.3K
* Total Submissions: 295.4K
* Testcase Example: '"()())()"'
*
* Remove the minimum number of invalid parentheses in order to make the input
* string valid. Return all possible results.
*
* Note: The input string may contain letters other than the parentheses ( and
* ).
*
* Example 1:
*
*
* Input: "()())()"
* Output: ["()()()", "(())()"]
*
*
* Example 2:
*
*
* Input: "(a)())()"
* Output: ["(a)()()", "(a())()"]
*
*
* Example 3:
*
*
* Input: ")("
* Output: [""]
*
*/
/**
* @param {string} s
* @return {string[]}
*/
var removeInvalidParentheses = function(s) {

};

Loading

0 comments on commit ca1ecbb

Please sign in to comment.