赞
踩
- 总结:
- 时间复杂度:衡量算法快慢的标准刻度
- 在CPU单位时间运行指令数恒定的情况下,求算法运行指令数和数据规模n的关系 F(n)
- 不求甚解
-
- 大O渐进法:
- 1)只保留最高次项
- 2)最高次项的系数化为1
- 时间复杂度不是绝对意义上的快慢,运行时间的变化趋势。
-
- 常见的时间复杂度:
- O(1) O(log(n)) O(n) O(n*log(n)) O(n^2)
-
- 特殊的时间复杂度:
- 二分查找
- 递归函数--画框框、数框框 了解
-
-
- 空间复杂度
- 大O渐进表示法
- 数据规模是n的情况下,
- 1)额外使用的空间大小(不考虑输入/输出中用到的空间)
- 2)常见形式
- i. int[] array=new int[和n的关系];
- int[] array=new int[255]; S(n)=O(n)
- ii.递归函数 调用栈
数据结构:存储、组织数据的形式。
算法:一系列步骤。
1.含义
是衡量算法好坏的刻度尺(标杆)
2.衡量的角度:
快/慢--时间复杂度 ****
使用空间的角度(内存)--空间复杂度
如:快慢:冒泡排序 其它排序
3.拿运行时间衡量怎么样?
不好 原因:1)事后衡量 2)影响因素太多(如当时系统上打开程序的多少)
4.衡量算法快慢的标准
是算法运行的指令个数(基本指令)。这里有个前提,即:CPU每秒运行的指令数是恒定的。
5.大O渐进法
数据规模 n
for(int i=0;i<n;i++){}
运行指令个数F(n) 和数据规模n有关。n越大,F(n)越大。
衡量算法好坏,不需要精确衡量。-->大O渐进表示法
O(F(n))=
1)只保留最高次项
2)最高次项的系数变为1
- //在array数组中查找value
- int search(int[] array,int value){
- for(int i=0;i<array.length;i++){
- if(array[i]==value){
- return i;
- }
- }
- return -1;//没有找到
- }
- 3 5 2 7 9 6 4
- 最好 平均 最坏
- 用平均/最坏来衡量
6.两个例子
- 例1:
- void count(int m,int n){
- int count=0;
- for(int i=0;i<m;i++){
- count++;
- }
- for(int i=0;i<n;i++){
- count++;
- }
- System.out.println(count);
- }
- O(n)=O(m+n)
- 例2:
- int String.indexOf(int ch);
- 数据规模:String的长度 O(n)
7.常见的时间复杂度
O(1)
O(log(n))
O(n)
O(n*log(n))
O(n^2)
8.递归函数的时间复杂度
做法:画框框,找框框的个数
- 例1:n的阶乘
- long Factorial(int n){
- return n>2?Factorial(n-1)*n:n;
- }
- 这个递归函数有两个出口:
- 1)n=1或n=2-->返回1或2
- 2)n>2-->求(n-1)! 递归n次。
- 因此,T(n)=O(n)
-
- 例2 斐波那契数列
- long Fabonacci(int N){
- return N<2?N:Fabonacci(N-1)+Fabonacci(N-2);
- }
- 两个出口:
- 1)N=1-->返回1
- 2)N>=2-->求Fabonacci(N-1)+Fabonacci(N-2)
举例说明:
冒泡过程:两个相邻的数依次比较,保证大的数在后面。
减治算法:每次处理都减少一个数,剩下的数用同样的方式处理。冒泡的过程就相当于减治算法。
外部循环表示比较的轮数,共比较array.length次。更优化的方式是array.length-1。
- //冒泡排序
- public static void bubbleSort(int[] array) {
- for (int i = 0; i < array.length; i++) {
- for (int j = 0; j < array.length - 1 - i; j++) {
- //保证相邻的两个数,最大的在后面。
- if (array[j] > array[j + 1]) {
- int temp = array[j];
- array[j + 1] = array[j];
- array[j] = temp;
- }
- }
- }
- }
时间复杂度:F(n)=(n-1)+(n-2)+....+1=(n-1+1)(n-1)/2=(n^2-n)/2,因此冒泡排序的时间复杂度为O(n)=n^2。
冒泡排序的优化
每次冒泡之前,假设数组已经有序。如:2 3 4 5 6 7 9。可以在每轮排序前设置标志位假设已经是有序的,经过一轮排序后,如果标志位未发生变化,则说明整个数组是有序的,就不必进行后面的排序了。
- for(int i=0;i<array.length;i++){
- //每次冒泡之前,假设数组已经有序。
- int sorted=true;
- //一次冒泡的过程,保证最大的数被推到最后。
- for(int j=0;j<array.length-1-i;j++){
- //保证相邻的两个数,最大的在后面。
- if(arr[j]>arr[j+1]){
- int temp=arr[j];
- arr[j+1]=arr[j];
- arr[j]=temp;
- sorted=false;
- }
- }
- //如果过程一次交换都没有发生过,假设有序成立。
- if(sorted==true){
- break;
- }
- }
前提:数组有序
查找方式:两种方式:[left,right) [left,right](其中, left=区间的左边界 right=区间的右边界)
中间位置的下标:int m=(left+right)/2
[left,right) 区间内只有一个数:right=left+1 没有数 left==right
- //二分查找
- [left,right]
- public static int binarySearch1(int[] array, int value) {
- int left = 0;
- int right = array.length - 1;//5 []
-
- while (left <= right) {
- int mid = left + (right - left) / 2;
- if (array[mid] == value) {
- return mid;
- }
- //说明value在(mid,right],那么left=mid+1
- if (array[mid] < value) {
- left = mid + 1;
- }
- //说明value在[left,mid),那么right=mid-1
- if (array[mid] > value) {
- right = mid-1;
- }
- }
- return -1;
- }
- //[left,right)
- public static int binarySearch2(int[] array,int value){
- int left=0;
- int right=array.length;
- //区间内还有一个数,就继续找,没有数就可以停下。
- while(left<right){
- int m=left+(right-left)/2;
- if(value==array[m]){
- return m;
- }
- if(value>array[m]){
- left=m+1;
- }
- if(value<array[m]){
- right=m;
- }
- }
- return -1;
- }
二分查找的时间复杂度:
长度变化:n n/2 n/4 ..... 1
1*2*2*2*...*2=n ->2^a=n-->a=log(n)
二分查找的时间复杂度T(n)=O(log(n))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。