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];
}
}