动态2

来源:互联网 发布:大数据清洗工具 编辑:程序博客网 时间:2024/06/07 06:22

374. Guess Number Higher or Lower

要求:跟定一个数的最大值,每次得到大还是小或者相等
思路:二分

375. Guess Number Higher or Lower II

要求:给定一个数,猜错要交钱,最小花多少钱
思路: dfs +memo,需要遍历小的数到大的数

322. Coin Change

找零钱问题
要求:找零钱,给定总额,给定货币的种类,输出最小的硬币个数
思路:这个跟数组可否恰好二分,背包问题本质上是同一种问题,就是可选可不选的状态
错误:初始化都是Integer.MAX_VALUE,然后对硬币进行遍历,没有对 i - j 判断是否是Integer.MAX_VALUE
ac

486. Predict the Winner

要求:与海盗分金子题目要求类似,一堆金子两头取
思路:也可以采用Math.min();The dp[i][j] saves how much more scores that the first-in-action player will get from i to j than the second player. First-in-action means whomever moves first. You can still make the code even shorter but I think it looks clean in this way.

       // 海盗分金子的问题    public boolean PredictTheWinner(int[] nums) {        if (nums == null || nums.length <= 1) return true;        int[] sum = new int[nums.length + 1];        sum[0] = 0;        int len = nums.length;        for (int i = 1; i <= len; i++) {            sum[i] = sum[i - 1] + nums[i - 1];        }        int[][] dp = new int[len + 1][len + 1];        for (int i = 1; i <= len; i++) {            dp[i][i] = nums[i - 1];        }        for (int l = 1; l < len; l++) {            for (int i = 1; i <= len - l; i++) {                int j = i + l;                dp[i][j] = sum[j] - sum[i - 1] - Math.min(dp[i + 1][j] , dp[i][j - 1]);             }        }        return 2 * dp[1][len] >= sum[len];    }     //海盗分金问题的另外一个解法         public static int getMoney(int[] nums) {         // if         int m = nums.length;         int[][][] memo = new int[m + 1][m + 1][2];         int[] resu =  dfs(memo,nums, 0, m - 1, 0 );         System.out.println(Arrays.toString(resu));         return resu[0];     }     public static int[] dfs(int[][][] memo, int [] nums, int le, int ri, int num) {         int[] resu = new int[2];         if (le == ri) {             if (num == 0) {                 resu[0] = nums[le];                  resu[1] = 0;              } else {                 resu[0] = 0;                  resu[1] = nums[le];              }             return resu;         }         if (memo[le][ri][num] > 0) {             return memo[le][ri];         }         if (num == 0) {             int temp1[] = dfs(memo, nums, le + 1, ri, 1);             int max1 = temp1[0] + nums[le];             int temp2[] = dfs(memo, nums, le, ri - 1, 1);             int max2 = temp1[0] + nums[ri];             if (max1 >  max2) {                 temp1[0] = temp1[0] + nums[le];                 memo[le][ri] = temp1;                 return temp1;             } else {                 temp2[0] = temp2[0] + nums[ri];                 memo[le][ri] = temp2;                 return temp2;             }         }         if (num == 1) {             int temp1[] = dfs(memo, nums, le + 1, ri, 0);             int max1 = temp1[1] + nums[le];             int temp2[] = dfs(memo, nums, le, ri - 1, 0);             int max2 = temp1[1] + nums[ri];             if (max1 >  max2) {                 temp1[1] = temp1[1] + nums[le];                 memo[le][ri] = temp1;                 return temp1;             } else {                 temp2[1] = temp2[1] + nums[ri];                 memo[le][ri] = temp2;                 return temp2;             }         }         return null;     }

486. Can I Win

思路:dfs加缓存,注意本次调用help函数,要取反

474. Ones and Zeroes

要求:给定0的个数以及1的个数,判定最多可以选择的组成的字符串的个数
思路:这个是0-1背包问题的类似问题,其实考试那个也是0- 1背包问题,这个是复杂版本的,背包定义dp[i][j],代表的是如果前i个占用j大的空间,转移方程为用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
此处定义的dp[i][j]为占用的0 与1的个数,这里面有两个限制参数,时间复杂度为O(n立方)

// 背包问题,都是从包来进行考虑的   public int findMaxForm(String[] strs, int m, int n) {        int[][] dp = new int[m+1][n+1];        for (String s : strs) {            int[] count = count(s);            for (int i=m;i>=count[0];i--)                 for (int j=n;j>=count[1];j--)                     dp[i][j] = Math.max(1 + dp[i-count[0]][j-count[1]], dp[i][j]);        }        return dp[m][n];    }    public int[] count(String str) {        int[] res = new int[2];        for (int i=0;i<str.length();i++)            res[str.charAt(i) - '0']++;        return res;     }

416. Partition Equal Subset Sum

要求:数组里面元素的和能否组成一个特定的数
思路:可以优化的背包问题的

// 核心代码, 比上面少了一维度  for (int n : nums) {            for (int i = sum; i>= n; i--) {                dp[i] = dp[i] || dp[i - n];            }        }

120. Triangle

要求:给定一个三角形,输出从根节点到叶子节点的类累加和最小的值
思路:三角形动态规划问题,如果涉及到路径的问题,可以采用pre缓存
每一个子节点从两个父节点继承

376. Wiggle Subsequence

要求:输出摇摆子序列的长度
思路:缓存两个, up, down,初始化的时候up和down都记为1,然后上升跟新up,下降更新do
输出:up和do大的那个

二叉查找树的题目

96. Unique Binary Search Trees

要求:给定一个数n,求1到n的n个数,可以组成多少种完全不同的二叉查找树
思路:G(n) = F(1, n) + F(2, n) + … + F(n, n). G(0)=1, G(1)=1. F(i, n) = G(i-1) * G(n-i) 1 <= i <= n
F 函数表示为以第i个结点为根节点,n个数的而查找树的个数 G(n) = G(0) * G(n-1) + G(1) * G(n-2) + … + G(n-1) * G(0)
ac:dp,注意下下标的范围,一般来讲,根据简单的demo进行测试即可

95. Unique Binary Search Trees II

要求:给定一个数n,输出组成不同的二叉查找树
思路:跟上一个 一样 采用 dfs,需要注意的是, 函数返回的是树的集合

377. Combination Sum IV

要求:给定目标值,数组里面有多少种可能结果集合
思路;这个是完全背包问题,与coinchange类似,只不过转移方程一个是最小的硬币数量,一个是最多的组合数量,不是0,1背包的问题 01背包,物品在外, 完全背包, 目标值在外(cionchange)

39. Combination Sum

要求:给定目标值,得出所有无重复的,数组中数的和等于当前值的目标值
思路:dfs+ backtracking, 一般结果输出型的,都得利用backtracking,
trick:因为是数,并且要求结果无重复,就要放一个start,下一次只能从start以及start的右侧进行选取,否则会出现重复

一般的题目,都是拐一个弯。注意下trick点,对比。

0 0