update readme.md
This commit is contained in:
+31
-2
@@ -149,7 +149,7 @@ void quicksort(int *a, int left, int right){
|
||||
|
||||
### 归并排序merge
|
||||
|
||||
分治算法(divide-and-conquer),必然用到递归 ;
|
||||
分治算法(divide-and-conquer),必然用到递归 ;
|
||||
|
||||
2个有序数组的合并操作是O(n)的复杂度
|
||||
因此我们可以将无序的数组,分成2个子数组分别排序,然后再merge,依次类推
|
||||
@@ -161,7 +161,7 @@ void quicksort(int *a, int left, int right){
|
||||
3. 合并
|
||||
|
||||
|
||||
归并排序的代码框架如下:
|
||||
归并排序的代码框架,套用二叉树的后续遍历思路,如下:
|
||||
|
||||
```
|
||||
void sort(int[] nums, int lo, int hi) {
|
||||
@@ -174,6 +174,35 @@ void sort(int[] nums, int lo, int hi) {
|
||||
merge(nums, lo, mid, hi);
|
||||
/************************/
|
||||
}
|
||||
|
||||
//合并连个有序数组; 从后往前merge
|
||||
public void merge(int[] arr,int low,int mid,int high,int[] tmp){
|
||||
int i = 0;
|
||||
int j = low,k = mid+1; //左边序列和右边序列起始索引
|
||||
|
||||
while(j <= mid && k <= high){
|
||||
if(arr[j] < arr[k]){
|
||||
tmp[i++] = arr[j++];
|
||||
}else{
|
||||
tmp[i++] = arr[k++];
|
||||
}
|
||||
}
|
||||
|
||||
//若左边序列还有剩余,则将其全部拷贝进tmp[]中
|
||||
while(j <= mid){
|
||||
tmp[i++] = arr[j++];
|
||||
}
|
||||
|
||||
while(k <= high){
|
||||
tmp[i++] = arr[k++];
|
||||
}
|
||||
|
||||
for(int t=0;t<i;t++){
|
||||
arr[low+t] = tmp[t];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||

|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
详细介绍每一种算法设计的思路,并为每种方法给出一个经典案例的详细解读,总结对应设计思路,最后给出其它案例,以供参考。
|
||||
|
||||
|
||||
* [递归](递归.md)
|
||||
* [分治算法](分治算法.md)
|
||||
* [动态规划](动态规划.md)
|
||||
* [回溯法](回溯法.md)
|
||||
* [迭代法](迭代法.md)
|
||||
* [穷举搜索法](穷举搜索法.md)
|
||||
* [动态规划](动态规划.md)
|
||||
* [贪心算法](贪心算法.md)
|
||||
* [回溯法](回溯法.md)
|
||||
* [分治算法](分治算法.md)
|
||||
* [递归](递归.md)
|
||||
* [贪心算法](贪心算法.md)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +29,6 @@
|
||||
## 参考
|
||||
|
||||
《算法设计与分析基础》 Anany Levitin
|
||||
http://www.chinaunix.net/old_jh/23/437639.html
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
|
||||
分治算法常用`递归`实现
|
||||
|
||||
1) 问题缩小的小规模可以很容易解决
|
||||
2) 问题可以分解为规模较小相同问题
|
||||
3) 子问题的解可以合并为该问题的解
|
||||
4) 各个子问题相互独立,(如果这条不满足,转为`动态规划`求解)
|
||||
1)问题缩小的小规模可以很容易解决
|
||||
2)问题可以分解为规模较小相同问题
|
||||
3)子问题的解可以合并为该问题的解
|
||||
4)各个子问题相互独立,(如果这条不满足,转为`动态规划`求解)
|
||||
|
||||
分治法的步骤:
|
||||
|
||||
1. 分解
|
||||
2. 解决
|
||||
3. 合并
|
||||
@@ -24,6 +25,6 @@
|
||||
|
||||
#### 其它案例
|
||||
|
||||
快速排序
|
||||
归并排序
|
||||
最大子数组和
|
||||
* 快速排序
|
||||
* [归并排序](../6%20Sort/README.md)
|
||||
* 最大子数组和
|
||||
|
||||
@@ -49,7 +49,8 @@ DP通常基于一个递推公式及一个(或多个)初始状态,当前子问
|
||||
|
||||
### DP VS 分治法
|
||||
|
||||
与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。
|
||||
与[分治法](分治算法.md)不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。
|
||||
若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
在 `递推` 阶段,将大的问题分解成小的问题
|
||||
在 `回归` 阶段,获得最简单问题的解后,逐级返回,依次得到稍微复杂情况的解,知道获得最终的结果
|
||||
|
||||
1) 确定递归公式
|
||||
1) 确定递归公式 , 比如 斐波那契数列 问题中的 `fib(n)=fib(n-1)+fib(n-2)`
|
||||
2) 确定边界条件
|
||||
|
||||
> 自顶向下的递归,自底向上是迭代
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Hash映射,分而治之
|
||||
|
||||
这里的`Hash映射`是指通过一种映射散列的方式,将海量数据均匀分布在对应的内存或更小的文件中
|
||||
|
||||
使用hash映射有个最重要的特点是: `hash值相同的两个串不一定一样,但是两个一样的字符串hash值一定相等`。哈希函数如下:
|
||||
|
||||
```
|
||||
int hash = 0;
|
||||
for (int i=0;i<s.length();i++){
|
||||
hash = (R*hash +s.charAt(i)%M);
|
||||
}
|
||||
```
|
||||
|
||||
大文件映射成多个小文件。具体操作是,比如要拆分到100(M)个文件:
|
||||
|
||||
1. 对大文件中的每条记录求hash值,然后对M取余数,即 `hash(R)%M`,结果为K
|
||||
2. 将记录R按结果K分配到第K个文件,从而完成数据拆分
|
||||
|
||||
这样,两条相同的记录肯定会被分配到同一个文件。
|
||||
|
||||
Reference in New Issue
Block a user