算法--更新中

算法

  1. 排序算法
    • 冒泡排序
    • 插入排序
    • 希尔排序
    • 快速排序
    • 选择排序
    • 归并排序
    • 基数排序
    • 堆排序
    • 桶排序
    • 大数据排序
  2. 查找算法
    • 二分查找
    • 快排查找
  3. 树的遍历
    • 二叉树的镜像遍历
    • 二叉树的前中后序、层次遍历
  4. 最大子数组和算法
  5. 最长公共子序算法
  6. 最短路径算法
  7. 最小生成树算法
  8. 动态规划
  9. 贪心算法
  10. 分治算法
  11. 回溯算法
  12. KMP算法
  13. LRU算法
  14. Manacher算法
  15. BEPRT算法

一、递归

思路步骤:

  1. 分析问题,找出递归关系
  2. 找出停止条件
  3. 设计递归算法、确定参数,即构建递归体。
经典题目
  1. 斐波那契数列:

经典数学问题之一;斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、……

递归关系:

f(0) = 1

f(1) = 1

f(n) = f(n-1)+f(n-2)

public class Solution {
	public int Fibonacci(int n) {
    	if(n==0)
    	    return 0;
    	if(n==1)
    	     return 1;
    	else
    	    return Fibonacci(n-2)+Fibonacci(n-1);
	}
}
  1. 青蛙跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

递归关系:

f(1) = 1

f(2) = 2

f(n) = f(n-1)+f(n-2)
public class Solution {
public int JumpFloor(int target) {
if(target == 1)
return 1;
if(target == 2)
return 2;
else
return JumpFloor(target-1)+JumpFloor(target-2);
}
}

  1. 变态跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

递归关系:

f(n)=f(n-1)+f(n-2)+…+f(1)

f(n-1)=f(n-2)+f(n-3)+…+f(1)

得出:

f(1)=1

f(n)=2*f(n-1) n>=2

public class Solution {
	public int JumpFloorII(int target) {
	    if(target == 1)
	        return 1;
	    else
	        return 2*JumpFloorII(target-1);
	}
}

动态规划

动态规划的核心思想:

动态规划其实质上是通过开辟记录表,记录已求解过的结果,当再次需要求解的时候,可以直接到那个记录表中去查找,从而避免重复计算子问题来达到降低时间复杂度的效果。算法的关键在于解决冗余,实际上是一个空间换时间的算法。

动态规划的求解步骤:

  1. 分析最优解的性质,并刻画其最优子结构特征;
  2. 递归地定义最优值
  3. 自底向上的方式计算出最优值,并记录相关信息
  4. 根据计算最优值时得到的信息,构造最优解

动态规划的基本要素:

  1. 最优子结构性质
  2. 子问题重叠性质
  3. 自底向上的求解方法

总结:建立记录表,自下而上,递归关系式;

最大连续子数组和(动态规划)

递归关系式:
| 0 i=0
d[i] = | array[i] d[i-1]<0
| d[i-1]+array[i] d[i-1]>0

class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
    vector<int> dp(array.size(),0);//记录表
    dp[0]=array[0];
    int max_dp=INT_MIN;
    for (int i = 1; i <= array.size()-1; ++i)
    {
        if(dp[i-1]<=0)     //判断上一个子问题的解是否小于0
            dp[i]=array[i];
        else
            dp[i]=array[i]+dp[i-1];
        if(dp[i]>max_dp)
            max_dp=dp[i];
    }
    return max_dp;
}

};

斐波那契数列

import java.util.*;
public class Solution {
public int Fibonacci(int n) {
       List<Integer> list = new ArrayList<Integer>();//记录表
       return  Fibonacci(n,list);
}
public int Fibonacci(int n,List<Integer> list){
    if(n == 0){
       if(list.size()==n)
            list.add(0);
       return  0;
    }
    if(n == 1 ){
      if(list.size()==n)
            list.add(1);
      return 1;
    }
    if(list.size()>=n){                           //记录添加条件
        if(list.size()==n){
           list.add(list.get(n-1)+list.get(n-2)); //将已经求得和记录进数组表中
        }
        return list.get(n); 
    }
    else 
       return Fibonacci(n-1,list)+Fibonacci(n-2,list);
}

}

最长公共子序列

import java.lang.String;
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    while(in.hasNext()) {
        String str1 = in.nextLine();
        String str2 = in.nextLine();
        System.out.println(new Main().maxSubSequence(str1,str2).length() > 0 ? new Main().maxSubSequence(str1,str2):-1);
    }
}

public  StringBuilder maxSubSequence(String str1,String str2) {
    int M = str1.length();
    int N = str2.length();
    //多添加一行一列便于初始化
    int[][] dp = new int[M+1][N+1];//dp[i][j] 表示 str1[0~i-1] 与 str2[0~j-1] 的最长公共子序列的长度
    int[][] re = new int[M+1][N+1];
           
    StringBuilder maxSubSequence = new StringBuilder();
    for(int i = 1;i < M+1;i++){
        for(int j = 1;j < N+1;j++){
            if(str1.charAt(i-1) == str2.charAt(j-1)){
                dp[i][j] = dp[i-1][j-1] + 1;
                re[i][j] = 1;
            }else if(dp[i-1][j]>dp[i][j-1]){
                dp[i][j] = dp[i-1][j];
                re[i][j] = 2;
            }else{
                dp[i][j] = dp[i][j-1];
                re[i][j] = 3;
            }                   
        }
    }
    lcs(M,N,str1,re,maxSubSequence);
    return maxSubSequence;
}
public static void lcs(int i,int j,String str1,int[][] re,StringBuilder out){
    if(i == 0||j == 0) return;
    if(re[i][j] == 1){
        lcs(i-1,j-1,str1,re,out);
        out.append(str1.charAt(i-1));
    }
    else if(re[i][j] == 2){
        lcs(i-1,j,str1,re,out);
    }else
        lcs(i,j-1,str1,re,out);
}

}


分治法

基本思想:
分治法的设计思想:将一个难以直接解决的规模较大的问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。例如大规模的数据排序…

分治法所能解决的问题一般具有以下几个特征:
I. 该问题的规模缩小到一定的程度就可以容易地解决;
II. 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质
III. 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
IV. 利用该问题分解出的子问题的解可以合并为该问题的解;

二分查找

快排

归并排序


贪心算法

基本思想:

贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,他的选取应该满足局部优化的条件。若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加算法停止 。

求解步骤:

  1. 建立数学模型来描述问题;
  2. 把求解的问题分成若干个子问题;
  3. 对每一子问题求解,得到子问题的局部最优解;
  4. 把子问题的解局部最优解合成原来解问题的一个解。

基本要素:

  1. 最优子结构
  2. 贪心选择

贪心算法与动态规划算法的主要区别:

  1. 贪心算法是自上而下的求解,从初始解出发,逐渐减小问题的规模;动态规划则是自下而上的求解
  2. 动态规划有子问题重叠性质
  3. 都有最优子结构性质

总结:贪心算法,从初始解出发,根据贪心选择,每走一步,问题的规模就会减少。

最大连续子数组和(贪心算法)

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        int largest=-1;
        int sum=0;
        for(int i=0;i<array.length;i++){
            sum=sum+array[i];
            if(sum>largest)
                largest = sum;
            if(sum<0)
                sum=0;
        }
        return largest;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值