常见的几个算法
Posted yjk923
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常见的几个算法相关的知识,希望对你有一定的参考价值。
今天主要说一下常见的算法 ,于是我百度了一下点进那 “ 牛逼 ” 的知乎看了一眼 ,完蛋了 ,这都是些神马 ??? 我怎么一个都不会呢 ,我要的可是那种很常见的算法啊 ,好吧 ,无形中又被深深的伤了一刀 ,好在我迅速调节状态 。管他呢 ,我就按照自己 low 的来吧 。进入正题 ,我要说的几种算法就是二分法查找 ,冒泡排序和选择排序 。以数组为例 ,谈谈它们在 Java 中的实现 。
二分法查找 ,举个例子说明一下 ,我们在玩猜数字游戏的时候经常会用到 。小明给出数的范围 ,0 ~ 100 ,我们猜 50 ,小明回答说 “ 大了 ” ,那我们会接着猜 25 ,就这样我们一次次的逼近了真相 。这就是二分法的思想 。也可以说是分治的思想 ,分而治之 ,逐一攻破 。我们同样也可以将这种思想应用到有序数组的查找上 。我们可以拿数组中间的数和待查找元素进行比较 ,其过程类似与猜数字 ,变得就是 “ 中间 ” 位的那个数 。最终我们可以找到目标元素 。方法实现 :
private static int binarySearch(int[] list,int target) { int low = 0; int high = list.length - 1; //直到low>high时还没找到关键字就结束查找,返回-1 while(low<=high){ int mid = (low+high) / 2; if(target < list[mid]){ high = mid - 1; } else if(target > list[mid]){ low = mid + 1; } else if(target == list[mid]){ return mid; } } return -1; }
冒泡排序 ,想象一下鱼儿在水中吐了一个泡 ,在向上的过程中 ,是不是在越变越大 。其实冒泡排序的思想也就是这样的 。给你 n 个数 ,我们用第一个数和第二个数进行比较 ,大的那个就放第二位 ,然后第二位和第三位比较 ,大的那个放在第三位 ,依次比下去 ,待到和最后一个比较结束 ,我们就能得到这 n 个数中最大的那个 ,且放在最后一个位置上 。( 这要是不明白就回头再读一遍 ) 这样一轮比较结束我们得到一个最大的数 ,第二轮我们再进行比较 ,同理 ,可以得到剩余 n - 1 个数中最大的数 。且放在倒数第二位 ,这就就是内层 for 循环条件 - 1 的原因 ,因为没必要和上一轮的最后一个数进行比较嘛 。方法实现 :
public static void bubbleSort(int[] arr) { /* * 外面的for循环决定一个长度为 n 的数据要比较多少轮才能完成排序。 * 里面的for循环决定每次一轮循环中要做多少次才能结束。 */ for(int i = 0; i < arr.length - 1; i++) { for(int j = 0; j < arr.length - 1 - i; j++){ //从小到大,大的值放后面位置。 if (arr[j] > arr[j+1]){ int temp = arr[j] arr[j] = arr[j + 1] arr [j + 1] = temp } } } }
PS . 只需要换一个符号 ,就可以得到从大到小的序列 。
快速排序 ,快速排序是对冒泡排序的一种改进 。它的基本思想是将要排序的数据分割成独立的两部分 ,其中一部分的所有数据都比另外一部分的所有数据都要小 。然后在按照此方法对两部分数据分别进行快速排序 ,最终得到一个有序的序列 。需要说明的是 ,快速排序的平均时间复杂度是 O(nlogn) 。但是时间复杂度还是 O(n^2) ,因为时间复杂度是按照最坏结果来计算的 。为了方便理解 ,使用一组数据模拟一下排序的过程 。
假设要排的数组为:int[] a = { 5 2 8 9 2 3 4 9 }; 选择 key = 5, 开始时 i = 0,j = 7 下标 0 1 2 3 4 5 6 7 开始 5 2 8 9 2 3 4 9 i j 第一次找 5 2 8 9 2 3 4 9 i j 交换: 5 2 4 9 2 3 8 9 i j 第二次找 5 2 4 9 2 3 8 9 i j 交换: 5 2 4 3 2 9 8 9 i j 第三次找 5 2 4 3 2 9 8 9 ij 调整key: 2 5 4 3 5 9 8 9 ij
方法实现 :
private static void quickSort(int[] a, int low, int high) { //找到递归算法的出口 if( low > high) { return; } int i = low; int j = high; //默认 key int key = a[low]; //开始一趟排序 while( i < j) { //先从右往左找到第一个小于 key 的数 , //这么做是因为在与 key 值交换的时候,保证了交换的数小于现有的 key 值 //若是大于的话,j 指针就会继续向左移动 。 while(i<j && a[j] > key){ j--; } //从左往右找到第一个大于等于 key 的数 while( i<j && a[i] <= key) { i++; } //交换,达到以 key “分治” 的效果 if(i<j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } } // 当 i = j 时,调整 key 的值为 a[i] == a[j] int temp = a[i]; a[i] = a[low]; a[low] = temp; //对 key 左边的数快速排序 quickSort(a, low, i-1 ); //对 key 右边的数快速排序 quickSort(a, i+1, high); }
后记 :不得不说 ,这些简单的算法我都没有很熟悉 ,只能是那种原理清楚 ,但是实现起来却是磕磕绊绊的状态 。还有 ,以上给出的实现是可以进一步优化的 ,记得之前在面试的时候被问到过冒泡排序的问题 ,现场也被问到过如何优化 。
以上是关于常见的几个算法的主要内容,如果未能解决你的问题,请参考以下文章