1.给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案
package algorithm.dtgh;
/**
* @version BiTeWei.java, v 0.1 2022年01月27日 16:09
* 给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。
* 输入:n = 2
* 输出:[0,1,1]
* 解释:
* 0 --> 0
* 1 --> 1
* 2 --> 10
*/
public class BiTeWei {
public static int[] countBits(int n) {
//动态规划
int[] bits = new int[n + 1];
for (int i = 1; i <= n; i++) {
bits[i] = bits[i & (i - 1)] + 1;
}
return bits;
}
public static int[] countBits1(int n) {
int[] bits = new int[n + 1];
for (int i = 0; i <= n; i++) {
bits[i] = Integer.bitCount(i^0);
}
return bits;
}
public static void main(String[] args) {
int[] ints = countBits(4);
for (int anInt : ints) {
System.out.println(anInt);
}
System.out.println("------------------");
int[] ints1 = countBits1(4);
for (int anInt : ints1) {
System.out.println(anInt);
}
}
}
2.给定一个数组 prices ,它的第i 个元素prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润
package algorithm.dtgh;
/**
* @version BuyStocks.java, v 0.1 2022年01月27日 15:08
*给定一个数组 prices ,它的第i 个元素prices[i] 表示一支给定股票第 i 天的价格。
* 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润
* 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
*/
public class BuyStocks {
public static int maxProfit(int[] prices) {
int maxProfit = 0;
int min = prices[0];
for (int price : prices) {
if(price < min){
min = price;
}else{
maxProfit = Math.max(maxProfit, price - min);
}
}
return maxProfit;
}
public static void main(String[] args) {
int[] arry = new int[]{7,1,5,3,6,4};
int[] arry1 = new int[]{1,1,5,3,6,10};
System.out.println(maxProfit(arry1));
}
}
取的最大利润 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
3. 爬楼梯 ,假设你正在爬楼梯。需要 n阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
package algorithm.dtgh;
/**
* @version ClimbStairs.java, v 0.1 2022年01月26日 16:07
* 爬楼梯
* 假设你正在爬楼梯。需要 n阶你才能到达楼顶。
* 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
* 示例 1:
* 输入:n = 2
* 输出:2
* 解释:有两种方法可以爬到楼顶。
* 1. 1 阶 + 1 阶
* 2. 2 阶
* 示例 2:
* 输入:n = 3
* 输出:3
* 解释:有三种方法可以爬到楼顶。
* 1. 1 阶 + 1 阶 + 1 阶
* 2. 1 阶 + 2 阶
* 3. 2 阶 + 1 阶
*
* 思路:
* 动态规划
* n = 1: case = 1
* n = 2: case = 2
* n = 3: case = (1+2) = 3
* n = 4: case = (2+3) = 5
* n = 5: case = (3+5) = 8
*/
public class ClimbStairs {
public static int climbStairs(int n) {
if(n <=2) return n;
int count = 1;
int pre1 = 2;
int pre2 = 1;
for(int i = 3 ; i <= n; i++){
count = pre1 + pre2;
pre2 = pre1;
pre1 = count;
}
return count;
}
public static int climbStairs1(int n) {
int[] arr = new int[n];
if(n <=2) return n;
arr[0] = 1;
arr[1] = 2;
for(int i = 2 ; i < n; i++){
arr[i] = arr[i-1] + arr[i-2];
}
return arr[n-1];
}
public static void main(String[] args) {
//System.out.println(climbStairs(3));
System.out.println(climbStairs1(5));
}
}
4.给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
package algorithm.dtgh;
/**
* @version CostClimbingStairs.java, v 0.1 2022年01月29日 10:07
* 给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
* 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。
- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15
输入:cost = [10,15,20,3,44,5,1,3,2]
*/
public class CostClimbingStairs {
public static int minCostClimbingStairs(int[] cost) {
//动态规划
int pre1 = cost[0];
int pre2 = cost[1];
int curr = 0;
for(int i = 2 ; i < cost.length ; i++){
curr = cost[i]+Math.min(pre1,pre2);
pre1 = pre2;
pre2 = curr;
}
return Math.min(pre1,pre2);
}
public static void main(String[] args) {
System.out.println(minCostClimbingStairs(new int[]{1,100,1,1,1,100,1,1,100,1}));
}
}
5.小扣打算给自己的 VS code 安装使用插件,初始状态下带宽每分钟可以完成 1 个插件的下载。假定每分钟选择以下两种策略之一: 使用当前带宽下载插件 将带宽加倍(下载插件数量随之加倍) *请返回小扣完成下载 n 个插件最少需要多少分钟。 注意:实际的下载的插件数量可以超过 n 个
package algorithm.dtgh;
/**
* @version DownLoadPlugin.java, v 0.1 2022年01月26日 14:40
* 小扣打算给自己的 VS code 安装使用插件,初始状态下带宽每分钟可以完成 1 个插件的下载。假定每分钟选择以下两种策略之一:
* 使用当前带宽下载插件
* 将带宽加倍(下载插件数量随之加倍)
* 请返回小扣完成下载 n 个插件最少需要多少分钟。
* 注意:实际的下载的插件数量可以超过 n 个
* 示例 1:
* 输入:n = 2
* 输出:2
* 解释:
* 以下两个方案,都能实现 2 分钟内下载 2 个插件
* 方案一:第一分钟带宽加倍,带宽可每分钟下载 2 个插件;第二分钟下载 2 个插件
* 方案二:第一分钟下载 1 个插件,第二分钟下载 1 个插件
未用动态规划方法 直接用的数学方法
*/
public class DownLoadPlugin {
public static int leastMinutes(int n) {
int loadNum = 1;
int times = 0;
while(loadNum < n){
loadNum = 2*loadNum;
times ++;
}
times += 1;
return times;
}
public static void main(String[] args) {
System.out.println(leastMinutes(5));
}
}
6.斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1
package algorithm.dtgh;
/**
* @version Fib.java, v 0.1 2022年01月28日 17:38
* 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是
* F(0) = 0,F(1) = 1
* F(n) = F(n - 1) + F(n - 2),其中 n > 1
* 输入:n = 2
* 输出:1
* 解释:F(2) = F(1) + F(0) = 1 + 0 = 1
*/
public class Fib {
public static int fib(int n) {
//递归
if( n == 0 ){
return 0;
}else if(n == 1){
return 1;
}else{
return fib(n-1) + fib(n -2);
}
}
public static int fib1(int n) {
//使用动态规划
if(n < 2){
return n;
}
int pre1 = 0 ;
int pre2 = 0 ;
int result = 1;
for(int i = 2 ; i <= n ; i++){
pre2 = pre1;
pre1 = result;
result = pre1 + pre2;
}
return result;
}
public static void main(String[] args) {
System.out.println(fib(6));
System.out.println(fib1(6));
}
}
7.输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6 连续子数组 [4,-1,2,1] 的和最大,为 6 。
package algorithm.dtgh;
/**
* @version MaxSubarraySum.java, v 0.1 2022年01月26日 15:19
* 输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
* 输出:6
* 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
* 动态规划:动态规划求出的是最优状态,所以必然也是针对状态的操作,
* 而状态自然可以出现在最优解中,也可以不出现——这便是决策的特性(布尔性)
* 动态规划也有无后效性,即每个当前状态会且仅会决策出下一状态,而不直接对未来的所有状态负责
*/
public class MaxSubarraySum {
public static int maxSubArray(int[] nums) {
int max = nums[0];
int sum = max;
for (int num : nums) {
if(sum > 0 ){
sum +=num;
}else{
sum = num;
}
max = Math.max(max,sum);
}
return max;
}
public static void main(String[] args) {
System.out.println(maxSubArray(new int[]{-2,1,-3}));
}
}
8.给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
package algorithm.dtgh;
/**
* @version Subsequence.java, v 0.1 2022年01月28日 16:50
* 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
* 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
* 进阶:
* 如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码
* 输入:s = "abc", t = "ahbgdc"
* 输出:true
*
* 输入:s = "axc", t = "ahbgdc"
* 输出:false
*需要使用双指针的方式
*/
public class Subsequence {
public static boolean isSubsequence(String s, String t) {
int i = 0 ;
int j = 0;
int sLen = s.length();
int tLen = t.length();
while(i < sLen && j < tLen){
if(s.charAt(i) == t.charAt(j)){
i++;
}
j++;
}
return i == sLen;
}
public static void main(String[] args) {
System.out.println(isSubsequence("ace", "abcde"));
}
}
9.在「杨辉三角」中,每个数是它左上方和右上方的数的和。 输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]
package algorithm.dtgh;
import java.util.ArrayList;
import java.util.List;
/**
* @version YangHuiSanJiao.java, v 0.1 2022年01月26日 17:00
* 给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。
*
* 在「杨辉三角」中,每个数是它左上方和右上方的数的和。
* 输入: numRows = 5
* 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]
* 动态规划:下一步的操作基于上一步 所以叫动态规划吗 ??
* 1、动态规划类似数学的已知fn-1求fn;
* 2、已知f1 = 1,每一行第一个和最后一个数为1,中间数为其左上方和右上方的数的和;
* 3、求得的fn记得添加到result中。
*/
public class YangHuiSanJiao {
public static List<List<Integer>> generate(int numRows) {
List<List<Integer>> result = new ArrayList<>();
for (int i = 0 ; i < numRows ;i++){
List<Integer> list = new ArrayList<>();
for(int j = 0 ; j <= i ; j++){
if(j == 0 || j == i){
list.add(1);
}else{
list.add(result.get(i -1).get(j-1)+result.get(i-1).get(j));
}
}
result.add(list);
}
return result;
}
public static void main(String[] args) {
List<List<Integer>> result = generate(8);
result.forEach(integers -> System.out.println(integers));
}
}
10.
给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和
package algorithm.dtgh;
import java.util.ArrayList;
import java.util.List;
/**
* @version YangHuiSanJiao1.java, v 0.1 2022年01月27日 14:31
* 给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。
* 在「杨辉三角」中,每个数是它左上方和右上方的数的和。
* 输入: rowIndex = 3
* 输出: [1,3,3,1]
*
* 输入: rowIndex = 1
* 输出: [1,1]
*/
public class YangHuiSanJiao1 {
public static List<Integer> getRow(int rowIndex) {
int[] dp = new int[rowIndex];
for(int i = 0 ;i < rowIndex ; i++){
for(int j = i;j >= 0; j--){ //防止覆盖,选择从右到左填入值
if(j == 0 || j == i){
dp[j] = 1;
}else{
dp[j] = dp[j-1] + dp[j];
}
}
}
//转换返回值
List<Integer> res = new ArrayList<>(dp.length);
for(int n: dp){
res.add(n);
}
return res;
}
public static void main(String[] args) {
System.out.println(getRow(4));
System.out.println(getRow1(4));
}
public static List<Integer> getRow1(int rowIndex) {
List<List<Integer>> result = new ArrayList<>();
for (int i = 0 ; i < rowIndex ;i++){
List<Integer> list = new ArrayList<>();
for(int j = 0 ; j <= i ; j++){
if(j == 0 || j == i){
list.add(1);
}else{
list.add(result.get(i -1).get(j-1)+result.get(i-1).get(j));
}
}
result.add(list);
}
return result.get(rowIndex-1);
}
}