0. 算法是什么
算法是针对具体的问题设计解决问题的具体流程,并且有评价该处理流程的可量化的指标。
1. 算法分类
算法也有很多的分类,简单来说的话,可以分为明确具体的流程,和明确尝试的具体的流程两类。
- 明确具体的流程(a+b)
- 明确尝试的具体流程(a的所有的素数)
2. 入门级别的算法题目
题目一:1!+2!+3!+...+n! 的结果
- 算法思路:
1! = 1
2! = 1 2
3! = 1 2 3
......
n! = 1 2 3 ... n
所以,1!+2!+3!+...+n! = 1 + 1 2 + 1 2 3 + ... + 1 2 3 ... n
此时,我们假设每一个数字是 i, 一共有n个数,我们分别求得i的阶乘,然后想加起来。循环n遍即可得。
代码如下:
public static void factorial1(int n){
int sum = 0;
//从1~n个数
for(int i = 1; i <= n; i++){
int curSum = 1;
//对每个i的数字求其阶乘,1 * 2 * ...i
for(int j = 1; j <= i; j++){
curSum *= j;
}
sum += curSum;
}
System.out.println(sum);
}
这个算法思路解决了我们的问题,那我们看一下这个代码,有两个for循环,复杂度偏高,有没有再优化一下的思路呢。我们观察,后一个的阶乘是建立在前一个阶乘的结果之上的。
- 优化思路:
2! = 1! 2
3! = 2! 3
...
n! = (n-1)! n
那么我们就不必重复去求得前一个数的阶乘了,保存下来即可。
优化代码:
public static void factorial(int n){
int sum = 0;
int facNum = 1;
for (int i = 1; i <= n; i++){
facNum *= i;
sum += facNum;
}
System.out.println(sum);
}
这个代码可以清楚地看到我们少了一个for循环,复杂度大大下降。
至此,求阶乘的问题已经解决了,很多时候,我们拿到问题时,都不能一下子想到那个最优解,没关系,我们可以慢慢来,一步步分析,先做到有那个最不优的算法,然后再观察,看是否可以进一步优化即可。
题目二:选择排序
算法思路:
在0~n-1位置找最小值,交换放在0号位置;
在1~n-1位置找最小值,交换放在1号位置;
...
在n-2~n-1位置找最小值,交换放在n-2位置;
每轮都选出最小值,然后放在相应的位置。
image.png
image.png
最终,这个数组就会被每轮选择最小值然后交换,成为从小到大的有序数组。
代码如下:
public static void selectSort(int[] arr){
if(null == arr || arr.length < 2){
return;
}
for(int i = 0; i < arr.length -1 ; i++){
int minValueIndex = i;
for(int j = i + 1; j < arr.length; j++){
minValueIndex = arr[j] < arr[minValueIndex] ? j : minValueIndex;
}
swap(arr, i, minValueIndex);
}
}
题目三:冒泡排序
算法思路:两两比较,较大的数向右移。
在0~n-1 边比较边右移,将大的数向右沉;(最大的数在n-1位置)
在0~n-2 边比较边右移... (第二大的数在n-2位置)
...
image.png
image.png
一轮轮的比较交换比较交换后,数组就会成为从小到大的有序数组。
代码如下:
public static void bubbleSort(int[] arr){
if(null == arr || arr.length <2){
return;
}
for(int end = arr.length-1; end >= 0; end --){
for(int start = 0; start < end; start ++){
if(arr[start] > arr[start+1]){
swap(arr, start, start+1);
}
}
}
}
题目四:插入排序
算法思路:局部形成有序,来一个数,进行从右向左的比较,将它插入在合适的位置。
在0位置有序;
在0~1位置有序;
在0~2位置有序;
...
image.png
代码如下:
public static void insertSort(int[] arr){
if(null == arr || arr.length < 2){
return;
}
for(int i = 1; i < arr.length; i++){
for(int j = i-1; j >= 0 && arr[j] > arr[j+1]; j--){
swap(arr, j, j+1);
}
}
}
3. 总结
算法就是解决问题的处理流程。
我们可以看到选择排序,冒泡排序,插入排序都是复杂度为o(),且频繁交换或者频繁比较,说明这三个排序并不算是性能最好的排序,但是它们易于理解和代码编写,算是新手入门的最佳例题。
网友评论