算法分析与设计总复习


前言

提示:转载链接☟
算法复习


一、算法引论

1、算法的四个性质

输入:零个或多个
输出:至少一个
确定性:每条指令清晰无歧义
有限性:每条指令执行次数有限,且执行时间有限

2、程序

程序是算法用某种程序设计语言的具体实现
程序不一定满足有限性

3、描述算法三种形式

自然语言:易懂但易产生歧义
程序流程图:直观形象,但难以绘制及修改
伪代码:易懂易改易转化为程序代码,但难以规范

4、算法复杂性分析

算法复杂性高低体现在运行该算法所需要的计算机资源的多少上
算法的时间复杂度T(n),所需的时间资源
算法的空间复杂度S(n),所需的空间资源
算法分析:分析算法复杂度的过程
空间复杂度分析较为简单,一般分析时间复杂度
一般用空间换时间

5、算法复杂性在渐进意义下的阶(记号):

O:大于等于当前函数(f)的函数(g)(上界),f的阶不高于g的阶
Ω:小于等于当前函数(f)的函数(g)(下界),f的阶不低于g的阶
θ:同阶
o:f的阶低于g的阶
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!)
常见使用O


二、递归

1、知识点

递归调用:一个函数的调用过程中直接或间接的调用该函数本身,称为函数>的递归调用,这种函数称为递归函数

直接递归:p->p
间接递归:p->q,q->p

递归要素:递归表达式(递归方程),递归结束条件(边界条件)

优点:结构清晰,可读性强,可证明
缺点:算法运行效率低

可用递归解决问题应满足的条件:
问题可转化为一个或多个子问题进行求解,且子问题和原问题求解方法相同,仅数量规模不同。
必须有结束递归的条件终止递归。

何时使用递归:
定义是递归的(阶乘,斐波那契数列)
数据结构是递归的(二叉树,单链表)
问题求解方法是递归的(hanoi塔,回溯法)

2、阶乘函数

import java.util.Scanner;

public class Main {
   

	public static void main(String[] args) {
   
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
   
			int result = sc.nextInt();
			System.out.println(f(result));
		}
	}

	public static int f(int n) {
   
		// TODO Auto-generated method stub
		return n==0?1:f(n-1)*n;
	}
}

3、斐波那契数列

import java.util.Scanner;

public class Main {
   

	public static void main(String[] args) {
   
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
   
			int result = sc.nextInt();
			System.out.println(fibonacci(result));
		}
	}

	public static int fibonacci(int n) {
   
		// TODO Auto-generated method stub
		return (n==0||n==1)?1:fibonacci(n-1)+fibonacci(n-2);
	}
}

4、汉诺塔问题

import java.util.Scanner;

public class Main {
   

	static int step=0;
	public static void main(String[] args) {
   
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
   
			step=0;
			int n = sc.nextInt();
			hanoi(n,'A','B','C');
		}
	}

	public static void hanoi(int n,char a,char b,char c) {
   
		// TODO Auto-generated method stub
		if(n>0){
   
			hanoi(n-1,a,c,b);//将第n-1个从A经过C运到B
			move(n,a,c);	 //将第n个从A移到C(上面的在B,可以直接移动)
			hanoi(n-1,b,a,c);//将第n-1个从B经过A运到C
		}
	}

	public static void move(int n, char a, char c) {
   
		// TODO Auto-generated method stub
		System.out.println(++step+" : "+n+" from "+a+" to "+c);
	}
}

5、全排列问题

import java.util.Scanner;

public class Main {
   
	
	static int total = 0;

	public static void main(String[] args) {
   
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
   
			int n = sc.nextInt();
			int[] a = new int[n+1];
			total = 0;
			for(int i=1;i<=n;i++)
				a[i] = i;
			perm(1,n,a);
			System.out.println("总共有" + total + "种");
		}
	}
	
	public static void perm(int k, int n,int[] a) {
   
		// TODO Auto-generated method stub
		if(k==n){
   
	        for(int i=1;i<=n;i++){
   
	            System.out.print(a[i]+" ");
	        }
	        System.out.println();
	        total++;
	    }
		else {
   
			//轮流做第k个
		    for(int i=k;i<=n;i++){
   
		        int t=a[i];a[i]=a[k];a[k]=t;
		        perm(k+1,n,a);
		        //排序完之后需要恢复原来的数组,方便下一个元素继续
		        t=a[i];a[i]=a[k];a[k]=t;
		    }
		}
	}
}

6、整数划分问题

import java.util.Scanner;

public class Main {
   
	
	public static void main(String[] args) {
   
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
   
			int n = sc.nextInt();
			System.out.println(q(n,n));
		}
	}

	public static int q(int n, int m) {
   
		// TODO Auto-generated method stub
		if(n==1||m==1) return 1;
		if(n<m) return q(n,n);
		if(n==m) return q(n,m-1)+1;
		return q(n-m,m)+q(n,m-1);
	}
}

三、分治

1、知识点

定义:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之

自顶向下分解,自底向上求解

可解决的问题:
规模缩小到一定程度
具有最优子结构性质(问题可分解为若干个规模较小的相同问题)
子问题的解可合并为该问题的解
各个子问题相互独立

用分治法设计算法时,最好使子问题规模大致相同(平衡子问题思想)

分治法时间复杂度分析(主定理)
T(n) = aT(n/b) + f(n) //将规模为n的问题分解为a个大小为n/b的子问题,f(n)是合并为原问题的解所需要的时间。
= a*[aT(n/b^2) + f(n/b) ] + f(n)
= a2*T(n/b2) + a*f(n/b) + f(n)
=…
总结:①当f(n)=c,a=1时 T(n) = O(logbn)
当f(n)=c,a!=1时 T(n) = O(n^(logba))
②当f(n)=cn,a<b时 T(n) = O(n)
当f(n)=cn,a=b时 T(n) = O(nlogbn)
当f(n)=cn,a>b时 T(n) = O(n^(logba))

2、二分查找

import java.util.Scanner;

public class Main{
   
	
	public static void main(String[] args) {
   
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		while(sc.hasNext()){
   
			int n = sc.nextInt();
			int key = sc.nextInt();
			int[] a = new int[n];
			for(int i=0;i<n;i++){
   
				a[i] = sc.nextInt();
			}
			int rel = binarySearch(a,key,0,n-1);
			if(rel == -1)
				System.out.println("No Solution");
			else
				System.out.println(rel+1);
			
		}		
	}

	public static int binarySearch(int[] a,int key, int low, int high) {
   
		// TODO Auto-generated method stub
		if(low>high) {
   
			return -1;
		}
		int mid = (low+high)/2;
		if(key==a[mid]) {
   
			return mid;
		}
	    else if(key<a[mid])
	        return binarySearch(a,key,low,mid-1);
	    else
	        return binarySearch(a,key,mid+1,high);
	}
}

3、快速排序

最好情况:T(n) = O(nlogn)
最坏情况:T(n) = O(nl^2)
平均情况:T(n) = O(nlogn)
稳定性:不稳定

import java.util.Scanner;

public class Main{
   
	
	public static void main(String[] args) {
   
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		while(sc.hasNext()){
   
			int n = sc.nextInt();
			int[] a = new int[n];
			for(int i=0;i<n;i++){
   
				a[i] = sc.nextInt();
			}
			quickSort(a,0,n-1);
			for(int i = 0;i<n;i++) {
   
				System.out.print(a[i]+" ");
			}
			System.out.println();
		}
	}
	
	//分区方法  返回分区的基准位置
	public static int partition(int[] a,int p,int q) {
   
		int x = a[p];
		int i = p,j;
		for(j = p+1;j<=q;j++) {
   
			if(a[j]<=x) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值