auto commit
This commit is contained in:
parent
0494398a34
commit
df394162f9
|
@ -31,10 +31,10 @@
|
|||
|
||||
待排序的元素需要实现 Java 的 Comparable 接口,该接口有 compareTo() 方法,可以用它来判断两个元素的大小关系。
|
||||
|
||||
研究排序算法的成本模型时,统计的是比较和交换的次数。
|
||||
|
||||
使用辅助函数 less() 和 swap() 来进行比较和交换的操作,使得代码的可读性和可移植性更好。
|
||||
|
||||
排序算法的成本模型是比较和交换的次数。
|
||||
|
||||
```java
|
||||
public abstract class Sort<T extends Comparable<T>> {
|
||||
|
||||
|
@ -54,7 +54,7 @@ public abstract class Sort<T extends Comparable<T>> {
|
|||
|
||||
# 选择排序
|
||||
|
||||
选择出数组中的最小元素,将它与数组的第一个元素交换位置。再从剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置。不断进行这样的操作,直到将整个数组排序。
|
||||
从数组中选择最小元素,将它与数组的第一个元素交换位置。再从数组剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置。不断进行这样的操作,直到将整个数组排序。
|
||||
|
||||
选择排序需要 \~N<sup>2</sup>/2 次比较和 \~N 次交换,它的运行时间与输入无关,这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作。
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class Selection<T extends Comparable<T>> extends Sort<T> {
|
|||
|
||||
从左到右不断交换相邻逆序的元素,在一轮的循环之后,可以让未排序的最大元素上浮到右侧。
|
||||
|
||||
在一轮循环中,如果没有发生交换,就说明数组已经是有序的,此时可以直接退出。
|
||||
在一轮循环中,如果没有发生交换,那么说明数组已经是有序的,此时可以直接退出。
|
||||
|
||||
<div align="center"> <img src="https://gitee.com/CyC2018/CS-Notes/raw/master/docs/pics/31550398353573.gif"/> </div><br>
|
||||
|
||||
|
@ -93,12 +93,12 @@ public class Bubble<T extends Comparable<T>> extends Sort<T> {
|
|||
@Override
|
||||
public void sort(T[] nums) {
|
||||
int N = nums.length;
|
||||
boolean hasSorted = false;
|
||||
for (int i = N - 1; i > 0 && !hasSorted; i--) {
|
||||
boolean isSorted = false;
|
||||
for (int i = N - 1; i > 0 && !isSorted; i--) {
|
||||
hasSorted = true;
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (less(nums[j + 1], nums[j])) {
|
||||
hasSorted = false;
|
||||
isSorted = false;
|
||||
swap(nums, j, j + 1);
|
||||
}
|
||||
}
|
||||
|
@ -113,14 +113,12 @@ public class Bubble<T extends Comparable<T>> extends Sort<T> {
|
|||
|
||||
对于数组 {3, 5, 2, 4, 1},它具有以下逆序:(3, 2), (3, 1), (5, 2), (5, 4), (5, 1), (2, 1), (4, 1),插入排序每次只能交换相邻元素,令逆序数量减少 1,因此插入排序需要交换的次数为逆序数量。
|
||||
|
||||
插入排序的复杂度取决于数组的初始顺序,如果数组已经部分有序了,逆序较少,那么插入排序会很快。
|
||||
插入排序的时间复杂度取决于数组的初始顺序,如果数组已经部分有序了,那么逆序较少,需要的交换次数也就较少,时间复杂度较低。
|
||||
|
||||
- 平均情况下插入排序需要 \~N<sup>2</sup>/4 比较以及 \~N<sup>2</sup>/4 次交换;
|
||||
- 最坏的情况下需要 \~N<sup>2</sup>/2 比较以及 \~N<sup>2</sup>/2 次交换,最坏的情况是数组是倒序的;
|
||||
- 最好的情况下需要 N-1 次比较和 0 次交换,最好的情况就是数组已经有序了。
|
||||
|
||||
以下演示了在一轮循环中,将元素 2 插入到左侧已经排序的数组中。
|
||||
|
||||
<div align="center"> <img src="https://gitee.com/CyC2018/CS-Notes/raw/master/docs/pics/51550399426594.gif"/> </div><br>
|
||||
|
||||
```java
|
||||
|
|
|
@ -26,7 +26,7 @@ N<sup>3</sup>/6-N<sup>2</sup>/2+N/3 \~ N<sup>3</sup>/6。使用 \~f(N) 来表示
|
|||
|
||||
## 2. 增长数量级
|
||||
|
||||
N<sup>3</sup>/6-N<sup>2</sup>/2+N/3 的增长数量级为 O(N<sup>3</sup>)。增长数量级将算法与它的实现隔离开来,一个算法的增长数量级为 O(N<sup>3</sup>) 与它是否用 Java 实现,是否运行于特定计算机上无关。
|
||||
N<sup>3</sup>/6-N<sup>2</sup>/2+N/3 的增长数量级为 O(N<sup>3</sup>)。增长数量级将算法与它的具体实现隔离开来,一个算法的增长数量级为 O(N<sup>3</sup>) 与它是否用 Java 实现,是否运行于特定计算机上无关。
|
||||
|
||||
## 3. 内循环
|
||||
|
||||
|
@ -40,7 +40,7 @@ N<sup>3</sup>/6-N<sup>2</sup>/2+N/3 的增长数量级为 O(N<sup>3</sup>)。增
|
|||
|
||||
## 1. 大常数
|
||||
|
||||
在求近似时,如果低级项的常数系数很大,那么近似的结果就是错误的。
|
||||
在求近似时,如果低级项的常数系数很大,那么近似的结果是错误的。
|
||||
|
||||
## 2. 缓存
|
||||
|
||||
|
@ -56,7 +56,7 @@ N<sup>3</sup>/6-N<sup>2</sup>/2+N/3 的增长数量级为 O(N<sup>3</sup>)。增
|
|||
|
||||
## 5. 均摊分析
|
||||
|
||||
将所有操作的总成本除于操作总数来将成本均摊。例如对一个空栈进行 N 次连续的 push() 调用需要访问数组的次数为 N+4+8+16+...+2N=5N-4(N 是向数组写入元素的操作次数,其余的都是调整数组大小时进行复制需要的访问数组次数),均摊后访问数组的平均次数为常数。
|
||||
将所有操作的总成本除于操作总数来将成本均摊。例如对一个空栈进行 N 次连续的 push() 调用需要访问数组的次数为 N+4+8+16+...+2N=5N-4(N 是向数组写入元素的次数,其余都是调整数组大小时进行复制需要的访问数组次数),均摊后访问数组的平均次数为常数。
|
||||
|
||||
# ThreeSum
|
||||
|
||||
|
@ -94,7 +94,7 @@ public class ThreeSumSlow implements ThreeSum {
|
|||
|
||||
## 2. ThreeSumBinarySearch
|
||||
|
||||
通过将数组先排序,对两个元素求和,并用二分查找方法查找是否存在该和的相反数,如果存在,就说明存在三元组的和为 0。
|
||||
将数组进行排序,对两个元素求和,并用二分查找方法查找是否存在该和的相反数,如果存在,就说明存在和为 0 的三元组。
|
||||
|
||||
应该注意的是,只有数组不含有相同元素才能使用这种解法,否则二分查找的结果会出错。
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user