算法记录

java程序的递归算法,列出某个目录下的所有子目录和文件

import java.io.*;

class DiGui
{
 static void getDir(String strPath) throws Exception
 {
  try
  {
   File f=new File(strPath);
   if(f.isDirectory())
   {
    File[] fList=f.listFiles();
    for(int j=0;j<fList.length;j++)
    {
     if(fList[j].isDirectory())
     {
      System.out.println(fList[j].getPath());
      getDir(fList[j].getPath()); //在getDir函数里面又调用了getDir函数本身       
     }
    }
    for(int j=0;j<fList.length;j++)
    {
     if(fList[j].isFile())
     {
      System.out.println(fList[j].getPath());
     }

    }
   }
  }
  catch(Exception e)
  {
   System.out.println("Error: " + e);
  }
 
 } 
 
 public static void main(String[] args)
 {
  String strPath="e://cqq";
  System.out.println(strPath);

  try
  {
   getDir(strPath);
  }
  catch(Exception e)
  {
  
  }
 }
}

爬楼梯问题

package forward.somethingTry;

/**
 * TODO
 *
 * @author Redamancy
 * @version 1.0
 * @date 2020/9/7 - 13:22
 * @since jdk 1.8
 * 算法练习之爬楼梯
 */
public class day_01 {
    /**
     * 假设你正在爬楼梯,需要n阶才能到达楼顶
     * 每次可以爬 1 或 2 个台阶,问有多少种方法爬到楼顶
     * 输入: 3
     * 输出: 3
     * 解释: 有三种方法可以爬到楼顶。
     * 1.  1 阶 + 1 阶 + 1 阶
     * 2.  1 阶 + 2 阶
     * 3.  2 阶 + 1 阶
     */
    //滚动数组法 O(n)
    public static int climbStaire1(int n){
        //r1 r2 分别代表当前位置的前两个数
        int r1 = 1,r2 = 2,res = n;
        for(int i = 3;i <= n;i++){
            res = r1 + r2;
            r1 = r2;
            r2 = res;
        }
        return res;
    }

    //自底向上动态规划法
    public static int climbStair2(int n){
        //存储每一个台阶的方法数
        int[] num = new int[n+1];
        //0号位是多余的,故数组要分配 n+1 项
        num[0] = 1;
        num[1] = 1;
        for(int i = 2;i <= n;++i){
            num[i] = num[i-1] + num[i-2];
        }
        return num[n];
    }

    public static void main(String[] args) {
        int result = climbStaire1(8);
        System.out.println(result);

        int result1 = climbStair2(2);
        System.out.print(result1);
    }

}

0-1背包

/**
	 * 0-1背包问题
	 * @param V	背包容量
	 * @param N	物品种类
	 * @param weight 物品重量
	 * @param value	物品价值
	 * @return
	 */
	public static String ZeroOnePack(int V,int N,int[] weight,int[] value){
		
		//初始化动态规划数组
		int[][] dp = new int[N+1][V+1];
		//为了便于理解,将dp[i][0]和dp[0][j]均置为0,从1开始计算
		for(int i=1;i<N+1;i++){
			for(int j=1;j<V+1;j++){
				//如果第i件物品的重量大于背包容量j,则不装入背包
				//由于weight和value数组下标都是从0开始,故注意第i个物品的重量为weight[i-1],价值为value[i-1]
				if(weight[i-1] > j)
					dp[i][j] = dp[i-1][j];
				else
					dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-weight[i-1]]+value[i-1]);
			}
		}
		//则容量为V的背包能够装入物品的最大值为
		int maxValue = dp[N][V];
		//逆推找出装入背包的所有商品的编号
		int j=V;
		String numStr="";
		for(int i=N;i>0;i--){
			//若果dp[i][j]>dp[i-1][j],这说明第i件物品是放入背包的
			if(dp[i][j]>dp[i-1][j]){
				numStr = i+" "+numStr;
				j=j-weight[i-1];
			}
			if(j==0)
				break;
		}
		return numStr;	
	}

参考

买股票

package forward.somethingTry;

/**
 * TODO
 *
 * @author Redamancy
 * @version 1.0
 * @date 2020/9/7 - 13:40
 * @since jdk 1.8
 * 算法练习之买卖股票最佳时机
 */
public class day_02 {
    /**
     * 给定一个数组,他的第 i 个元素是某股票第一天的价格
     * 如果你最多只允许完成一笔交易
     * 即买入和卖出一只股票一次
     * 设计一个算法来计算你能获取的最大利润
     * 注意:不能买入前 卖出
     *输入: [7,1,5,3,6,4]
     * 输出: 5
     * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     *      注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
     *
     * 记录【今天之前买入的最小值】
     * 计算【今天之前最小值买入,今天卖出的获利】,也即【今天卖出的最大获利】
     * 比较【每天的最大获利】,取最大值即可
     */
    //记录第几天卖出
    public static int date;
    /**
     * 计算卖出股票的最佳日期
     * @param prices 原始数组
     * @return 最佳卖出的日期--数组第几个元素(从1开始)
     */
    public static int maxProfit(int[] prices){
        int L = prices.length;
        if(L == 0){
            return 0;
        }
        //min表示当前位置之前的最小值
        int min = prices[0];
        //maxProfit表示当前位置之前的最大利润
        int maxProfit = 0;
        for(int i = 1;i < L;++i){
            /**
             *prices[i]-min :当前位置抛售可获得的最大利润
             *注意只能是当天减去之前的 min ,而不能 之前的 减去当天
             * 例如 20 1 7
             * 最大是 7 - 1,而不是 1 - 20
             */
            maxProfit = Math.max(maxProfit,prices[i]-min);
            min = Math.min(prices[i],min);
            date=i+1;
        }
        return maxProfit;
    }



    public static void main(String[] args) {
        int money = maxProfit(new int[]{26,4,12,8,16,89,12});
        System.out.println("在第 "+date+"天卖出利润最大,可赚 "+money+" 万元!!");
    }
}

买股票2.0

package forward.somethingTry;

/**
 * TODO
 *
 * @author Redamancy
 * @version 1.0
 * @date 2020/9/7 - 14:01
 * @since jdk 1.8
 * 算法练习之买卖股票最佳时机 含冷冻期
 * 此题目,未有最优解法
 */
public class day_02_2 {
    /**
     * 给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​
     *
     * 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
     *
     * 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
     * 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
     *输入: [1,2,3,0,2]
     * 输出: 3
     * 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
     *
     * 思想:
     * 注意状态是指每一天结束时的状态。
     * 三种状态:无操作(冷冻或不持股),刚卖出,持股(买入)。
     * 如果前一天“无操作”,今天可选择买入或不买入,分别转化为“持股”和“无操作”;
     * 如果前一天“刚卖出”,今天必须进入冷冻,即转化为“无操作”状态;
     * 如果前一天“持股”,今天可选择卖出或不卖出,分别可转化为“刚卖出”和“持股”;
     * 这样状态转移方程就可以写出来了:
     *
     * dp[i][0] = Math.max(dp[i-1][1],dp[i-1][0]);
     * dp[i][1] = dp[i-1][2] + prices[i];
     * dp[i][2] = Math.max(dp[i-1][2],dp[i-1][0] - prices[i]);
     */
    public static int maxProfit(int[] prices){
        if(prices.length==0){
            return 0;
        }
        int[] buy = new int[prices.length];
        int[] sell = new int[prices.length];
        int[] lock = new int[prices.length];
        for(int i = 0;i < prices.length;i++){
            buy[i] = Integer.MIN_VALUE;
        }
        for(int i = 0;i < prices.length;i++){
            if(i==0){
                //第一天只要买入就是亏钱
                buy[i] = -prices[i];
            }else{
                //其中buy[i-1]表示截至昨天最后一个操作是买入且今天啥也不干
                // lock[i-1] - prices[i]表示截至昨天最后一个操作是冷冻且今天买入
                //比较两次买入操作哪次 花费较少(买入是负数,哪个大表示低价买入)
                buy[i] = Math.max(buy[i-1],lock[i-1]-prices[i]);
                //用今天的价钱去抵消前一天的亏损(即买入所用费用)
                sell[i] = buy[i-1] + prices[i];
                //当天冻结带来的收益
                //即比较如果前一天不操作,跟前一天卖出收益大
                lock[i] = Math.max(lock[i-1],sell[i-1]);
            }
        }
        //其中buy[i-1]表示截至昨天最后一个操作是买入且今天啥也不干
        //即直到最后前一天买入且今天不做操作
        int result = buy[prices.length - 1];
        //判断今天卖出 跟 不操作哪个收益大
        if(sell[prices.length-1] > result){
            result = sell[prices.length-1];
        }
        //判断在上面比较中的收益,今天如果不操作能否更不亏
        if(lock[prices.length-1] > result){
            result = lock[prices.length-1];
        }
        return result;
    }


    public static void main(String[] args) {
        int maxfit = maxProfit(new int[]{2,4,9,3,8,10});
        System.out.println(maxfit);
    }
}

最长回文子串

package forward.somethingTry;

/**
 * TODO
 *
 * @author Redamancy
 * @version 1.0
 * @date 2020/9/7 - 21:47
 * @since jdk 1.8
 * 算法练习之最长回文子串
 * 回文子串:即正反念都一样,121,434,aba,bab,1234321
 */
public class day_03 {
    /**
     *给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
     *输入: "babad"
     * 输出: "bab"
     * 注意: "aba" 也是一个有效答案。
     *
     * 动态规划,用boolean[][] dp记录每一对字符是否相等;
     * 双循环遍历所有子串情况,每次遍历时,当前子串首尾相等且内层-1字符串dp值为true,则记录dp值为true;全部遍历完,取最长,即为最长子串;
     * 临界条件很复杂,最好在循环之前把长度小于2的情况剔除;条件中有一个i-j<3,因为小于3且首尾相等的子串一定是回文串,不需要再往内层再判断dp。
     */
    public static String longestPalindrome(String s) {

        int len = s.length();
        boolean[][] dp = new boolean[len][len];
        int i,j,max=0,m=0,n=0;
        if(len<2){
            return s;
        }
        for(i=0;i<len;++i){
            for(j=0;j<=i;++j){
                if(s.charAt(i) == s.charAt(j)&&(i-j<3||dp[j+1][i-1])){
                    dp[j][i]=true;
                    if(i-j>max){
                        max = i-j;
                        m=j;n=i;
                    }
                }else{
                    dp[j][i]=false;
                }
            }
        }
        return s.substring(m,n+1);
    }


    public static void main(String[] args) {
        String s = longestPalindrome("asksfskbkbkbk");
        System.out.print(s);

    }
}

//暴力法
 class Solution {

    public String longestPalindrome(String s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }

        int maxLen = 1;
        String res = s.substring(0, 1);

        // 枚举所有长度大于等于 2 的子串
        for (int i = 0; i < len - 1; i++) {
            for (int j = i + 1; j < len; j++) {
                if (j - i + 1 > maxLen && valid(s, i, j)) {
                    maxLen = j - i + 1;
                    res = s.substring(i, j + 1);
                }
            }
        }
        return res;
    }

    private boolean valid(String s, int left, int right) {
        // 验证子串 s[left, right] 是否为回文串
        while (left < right) {
            if (s.charAt(left) != s.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

最长上升子字符串

public class Test300 {
    public static void main(String[] args) {
        int[] nums = {10,9,2,5,3,7,101,18};
        System.out.println(lengthOfLIS(nums));
    }
    public static int lengthOfLIS(int[] nums) {
        int[] dp = new int[nums.length];
        dp[0] = 1;
            int max = dp[0];
            for(int i = 1;i < nums.length;i++) {
                dp[i] = 1;
                for(int j = 0;j <= i-1;j++) {
                    if(nums[i] > nums[j] && dp[j]+1 > dp[i]){
                        dp[i] = dp[j]+1;
                    }
                }
                if(max < dp[i]){
                max = dp[i];
            }
        }
        return max;
    }
}

打家劫舍

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        if (n == 0) {
			return 0;
		}
        
		int[] f = new int[n];
		if (n == 1) {
			return nums[0];
		}
        
		int a = Math.max(nums[0], nums[1]);
		if (n == 2) {
			return a;
		}
		
		f[0] = nums[0];
		f[1] = a;
		
		for (int i = 2; i < f.length; i++) {
			f[i] = Math.max(f[i - 2] + nums[i], f[i -1]);
		}
		return f[n - 1];
    }
}

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值