Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
wizardforcel committed Sep 27, 2020
0 parents commit 5441898
Show file tree
Hide file tree
Showing 721 changed files with 49,788 additions and 0 deletions.
115 changes: 115 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# 结构化算法刷题训练指南

> 此仓库是 [apachecn/Interview](https://github.com/apachecn/Interview) 的只读备份,用于打包和分发。任何修改请在原仓库上进行。
>
> **欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远**
* 英文官网: https://leetcode.com
* 中文官网: https://leetcode-cn.com
* [ApacheCN 组织资源](https://docs.apachecn.org/): <https://docs.apachecn.org/>
* **ApacheCN - 面试求职群【724187166】<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=9bcf2fb3985835c9c2f15783ec9c85822e23be1191a6581eaf22f574b5192b19"><img border="0" src="http://data.apachecn.org/img/logo/ApacheCN-group.png" alt="ApacheCN - 面试求职群[724187166]" title="ApacheCN - 面试求职群[724187166]"></a>**

## 关于刷题

```
刷题可能是目前来说:最有用,也是最没用的东西
有用只是指:面试最快捷的一种方式
最没用是指:基本上在工作中用不上
简单来说;形式主义为主,技术提升为辅,目的就是为了驯服和奴役思维
会刷题和当年会考试没有本质区别
我并没有觉得这个是一件值得骄傲的事情
相反,这恰恰是普通人没用选择的事情
我吐槽一下:
工作5年,面试还要刷题,写排序,聊一些优化细节和技巧,感觉比较惭愧
你能写出一个高性能的代码吗?(例如:处理10G,做排序)
你反问:为什么不用GPU和Spark.
他说:。。(他无语)
我觉得大家可能都很无语吧,最无语的应该是前沿的技术吧
很多时候,基本上你遇到问题百度一下答案就出来了
工作中你可能没遇到,但是面试你必须背下来,不管会不会
一个人的好坏,我觉得是在人的性格和搜索能力。
但是在各大公司的HR和不入流的面试官面前:高学历和强刷题
技术高低和花的时间有关系,而工作是否录取和高学历和强刷题有关
```

---

当然我们得先战胜市场,才能改变市场!
下面正式开始我们刷题教程入门 -- 你准备好了吗?

## 数据结构 - 排序

* 二分查找
* 冒泡排序
* 插入排序
* 选择排序
* 快速排序
* 希尔排序
* 归并排序
* 基数排序

实战入口: <https://interview.apachecn.org/docs/Algorithm/DataStructure>

## [算法刷题](https://github.com/apachecn/Interview/tree/master/docs/Algorithm/README.md)

1. [Leetcode](/docs/Algorithm/Leetcode)
- [Python](/docs/Algorithm/Leetcode/Python)
- [Java](/docs/Algorithm/Leetcode/Java)
- [JavaScript](/docs/Algorithm/Leetcode/JavaScript)
- [C++](/docs/Algorithm/Leetcode/C++)
- [ipynb](/docs/Algorithm/Leetcode/ipynb)
- [GO](https://github.com/aQuaYi/LeetCode-in-Go)
- [Golang](https://github.com/kylesliu/awesome-golang-leetcode)
2. [剑指 Offer](/docs/Algorithm/剑指offer)
- [Python](/docs/Algorithm/剑指offer/Python)
- [Scala](/docs/Algorithm/剑指offer/Scala)
- [Java](/docs/Algorithm/剑指offer/Java)
- [JavaScript](/docs/Algorithm/剑指offer/JavaScript)
- [C++](/docs/Algorithm/剑指offer/C++)
3. [数据结构](/docs/Algorithm/DataStructure)
- [Wikipedia: List of Algorithms](https://en.wikipedia.org/wiki/List_of_algorithms)

## 参与方式

> 提交PR基本要求(满足任意一种即可)
* 不一样的思路
* 优化时间复杂度和空间复杂度,或者解决题目的Follow up
* 有意义的简化代码
* 未提交过的题目

> **案例模版**
[模版 md: 001. Two Sum 两数之和](docs/Algorithm/Leetcode/Python/001._two_sum.md)
[模版页面效果: 001. Two Sum 两数之和](https://interview.apachecn.org/docs/Algorithm/Leetcode/Python/001._two_sum.html)

## 推荐 LeetCode 网站

- [KrisYu的Github](https://github.com/KrisYu/LeetCode-CLRS-Python)
- [kamyu104的Github](https://github.com/kamyu104/LeetCode)
- [数据结构与算法/leetcode/lintcode题解](https://algorithm.yuanbin.me/zh-hans/)
- [Leetcode 讨论区](https://discuss.leetcode.com/)
- [visualgo算法可视化网站](https://visualgo.net/en)
- [Data Structure Visualization](https://www.cs.usfca.edu/~galles/visualization/Algorithms.html)
- [我的算法学习之路 - Lucida](http://zh.lucida.me/blog/on-learning-algorithms/)
- [HiredInTech](https://www.hiredintech.com/) System Design 的总结特别适合入门
- [mitcc的Github](https://github.com/mitcc/AlgoSolutions)
- [小土刀的面试刷题笔记](http://wdxtub.com/interview/14520594642530.html)
- [nonstriater/Learn-Algorithms](https://github.com/nonstriater/Learn-Algorithms)
- [剑指 Offer 题解](https://github.com/gatieme/CodingInterviews)
- https://github.com/liuchuo/LeetCode
- https://github.com/anxiangSir/SwordforOffer
- https://www.nowcoder.com/ta/coding-interviews?page=1
- [【小姐姐】刷题博客](https://www.liuchuo.net/about)
- [公瑾的Github](https://github.com/yuzhoujr/leetcode)
- [shejie1993](https://shenjie1993.gitbooks.io/leetcode-python/content/096%20Unique%20Binary%20Search%20Trees.html)
- [编程之法:面试和算法心得](https://legacy.gitbook.com/book/wizardforcel/the-art-of-programming-by-july/details)
- [算法/NLP/深度学习/机器学习面试笔记](https://github.com/imhuay/Interview_Notes-Chinese)
72 changes: 72 additions & 0 deletions docs/jianzhioffer/java/03_01_DuplicationInArray.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
## 找出数组中重复的数字

### 题目描述
在一个长度为 `n` 的数组里的所有数字都在 `0``n-1` 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为 `7` 的数组 `{2, 3, 1, 0, 2, 5, 3}`,那么对应的输出是重复的数字 `2` 或者 `3`


### 解法
#### 解法一
排序后,顺序扫描,判断是否有重复,时间复杂度为 `O(n²)`

#### 解法二
利用哈希表,遍历数组,如果哈希表中没有该元素,则存入哈希表中,否则返回重复的元素。时间复杂度为 `O(n)`,空间复杂度为 `O(n)`

#### 解法三
长度为 `n`,元素的数值范围也为 `n`,如果没有重复元素,那么数组每个下标对应的值与下标相等。

从头到尾遍历数组,当扫描到下标 `i` 的数字 `nums[i]`
- 如果等于 `i`,继续向下扫描;
- 如果不等于 `i`,拿它与第 `nums[i]` 个数进行比较,如果相等,说明有重复值,返回 `nums[i]`。如果不相等,就把第 `i` 个数 和第 `nums[i]` 个数交换。重复这个比较交换的过程。

此算法时间复杂度为 `O(n)`,因为每个元素最多只要两次交换,就能确定位置。空间复杂度为 `O(1)`

```java

/**
* @author bingo
* @since 2018/10/27
*/

public class Solution {
/**
* 查找数组中的重复元素
* @param numbers 数组
* @param length 数组长度
* @param duplication duplication[0]存储重复元素
* @return boolean
*/
public boolean duplicate(int[] numbers, int length, int[] duplication) {
if (numbers == null || length < 1) {
return false;
}
for (int e : numbers) {
if (e >= length) {
return false;
}
}

for (int i = 0; i < length; ++i) {
while (numbers[i] != i) {
if (numbers[i] == numbers[numbers[i]]) {
duplication[0] = numbers[i];
return true;
}
swap(numbers, i, numbers[i]);
}
}

return false;
}

private void swap(int[] numbers, int i, int j) {
int t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
}
```

### 测试用例
1. 长度为 n 的数组中包含一个或多个重复的数字;
2. 数组中不包含重复的数字;
3. 无效测试输入用例(输入空指针;长度为 n 的数组中包含 0~n-1 之外的数字)。
86 changes: 86 additions & 0 deletions docs/jianzhioffer/java/03_02_DuplicationInArrayNoEdit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
## 不修改数组找出重复的数字

### 题目描述
在一个长度为 `n+1` 的数组里的所有数字都在 `1``n` 的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为 `8` 的数组 `{2, 3, 5, 4, 3, 2, 6, 7}`,那么对应的输出是重复的数字 `2` 或者 `3`


### 解法
#### 解法一
创建长度为 `n+1` 的辅助数组,把原数组的元素复制到辅助数组中。如果原数组被复制的数是 `m`,则放到辅助数组第 `m` 个位置。这样很容易找出重复元素。空间复杂度为 `O(n)`

#### 解法二
数组元素的取值范围是 `[1, n]`,对该范围对半划分,分成 `[1, middle]`, `[middle+1, n]`。计算数组中有多少个(count)元素落在 `[1, middle]` 区间内,如果 count 大于 middle-1+1,那么说明这个范围内有重复元素,否则在另一个范围内。继续对这个范围对半划分,继续统计区间内元素数量。

时间复杂度 `O(n * log n)`,空间复杂度 `O(1)`

注意,此方法无法找出所有重复的元素。

```java
/**
* @author bingo
* @since 2018/10/27
*/

public class Solution {
/**
* 不修改数组查找重复的元素,没有则返回-1
* @param numbers 数组
* @return 重复的元素
*/
public int getDuplication(int[] numbers) {
if (numbers == null || numbers.length < 1) {
return -1;
}

int start = 1;
int end = numbers.length - 1;
while (end >= start) {
int middle = start + ((end - start) >> 1);

// 调用 log n 次
int count = countRange(numbers, start, middle);
if (start == end) {
if (count > 1) {
return start;
}
break;
} else {
// 无法找出所有重复的数
if (count > (middle - start) + 1) {
end = middle;
} else {
start = middle + 1;
}
}
}
return -1;
}


/**
* 计算整个数组中有多少个数的取值在[start, end] 之间
* 时间复杂度 O(n)
* @param numbers 数组
* @param start 左边界
* @param end 右边界
* @return 数量
*/
private int countRange(int[] numbers, int start, int end) {
if (numbers == null) {
return 0;
}
int count = 0;
for(int e : numbers) {
if (e >= start && e <= end) {
++count;
}
}
return count;
}
}
```

### 测试用例
1. 长度为 n 的数组中包含一个或多个重复的数字;
2. 数组中不包含重复的数字;
3. 无效测试输入用例(输入空指针)。
57 changes: 57 additions & 0 deletions docs/jianzhioffer/java/04_FindInPartiallySortedMatrix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
## 二维数组中的查找

### 题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。


### 解法
从二维数组的右上方开始查找:
- 若元素值等于 `target`,返回 `true`
- 若元素值大于 `target`,砍掉这一列,即 `--j`
- 若元素值小于 `target`,砍掉这一行,即 `++i`

也可以从二维数组的左下方开始查找,以下代码使用左下方作为查找的起点。

注意,不能选择左上方或者右下方的数字,因为这样无法缩小查找的范围。

```java
/**
* @author bingo
* @since 2018/10/27
*/

public class Solution {
/**
* 二维数组中的查找
* @param target 目标值
* @param array 二维数组
* @return boolean
*/
public boolean find(int target, int[][] array) {
if (array == null) {
return false;
}
int rows = array.length;
int columns = array[0].length;

int i = rows - 1;
int j = 0;
while (i >= 0 && j < columns) {
if (array[i][j] == target) {
return true;
}
if (array[i][j] < target) {
++j;
} else {
--i;
}
}
return false;
}
}
```

### 测试用例
1. 二维数组中包含查找的数字(查找的数字是数组中的最大值和最小值;查找的数字介于数组中的最大值和最小值之间);
2. 二维数组中没有查找的数字(查找的数字大于/小于数组中的最大值;查找的数字在数组的最大值和最小值之间但数组中没有这个数字);
3. 特殊输入测试(输入空指针)。
Loading

0 comments on commit 5441898

Please sign in to comment.