动态规划题解集合(Java)

简介: 动态规划题解集合(Java)

持续更新中(解题思路写在代码注释里)



1、爬楼梯


假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。


示例 1:

输入: 2

输出: 2

解释: 有两种方法可以爬到楼顶。

1.  1 阶 + 1 阶

2.  2 阶


示例 2:

输入: 3

输出: 3

解释: 有三种方法可以爬到楼顶。

1.  1 阶 + 1 阶 + 1 阶

2.  1 阶 + 2 阶

3.  2 阶 + 1 阶


public static int climbStairs(int n) {
    /**
     * 爬楼梯的方案数为爬到n-1阶的方案数(只剩一步到楼顶)加上爬到n-2阶的方案数(只剩一次两步到楼顶)
     * 可知符合方案数 dp[n] = dp[n-1] + dp[n-2]
     * dp[0]=0, dp[1]=1,dp[2]=2
     */
    if(n == 1){
            return 1;
        }
        int []dp = new int[n+1];
    dp[0] = 0;
    dp[1] = 1;
    dp[2] = 2;
    for (int i = 3; i <= n; i++) {
      dp[i] = dp[i-1] + dp[i-2];
    }
    return dp[n];
    }


2、最大子序列


给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。


示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]

输出:6

解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。


示例 2:

输入:nums = [1]

输出:1


示例 3:

输入:nums = [0]

输出:0


示例 4:

输入:nums = [-1]

输出:-1


示例 5:

输入:nums = [-100000]

输出:-100000

 

提示:

1 <= nums.length <= 3 * 104

-105 <= nums[i] <= 105


public static int maxSubArray(int[] nums) {
        /**
         * 方法一: 暴力枚举
         */
        //  int n = nums.length;
        //  int big = nums[0];
        //  int index1 = 0;
        //  int index2 = 0;
        //  int temp = nums[0];
        //  
        //  for(int i=0;i<n;i++) {
        //    temp = nums[i];
        //    if(temp>big) {
        //      big=temp;
        //    }
        //    index1=i;
        //    index2=i;
        //    for(int j=i+1;j<n;j++) {
        //      temp = temp+nums[j];
        //      if(temp > big) {
        //        index2 = j;
        //        big = temp;
        //      }
        //    }
        //  }
        //  
        //  System.out.println(big);
        /**
       * 方法二: 动态规划
       * 
       * dp[i]表示以nums[i]结尾的最大序列和
       * 当i=0时,dp[0] = nums[0]
       * 当i>0时,dp[i] = max{ (dp[i-1]+nums[i]) , nums[i] }
       * 
       * 再找出dp[]中最大即可
       */
      int []dp = new int[nums.length];
      dp[0] = nums[0];
      for(int i=1;i<nums.length;i++) {
        dp[i] = Math.max((dp[i-1]+nums[i]), nums[i]);
      }
      int big = dp[0];
      for(int i=1;i<dp.length;i++) {
        if(dp[i] > big) {
          big = dp[i];
        }
      }
          return big;
      }


3、杨辉三角


给定一个非负整数 numRows生成「杨辉三角」的前 numRows行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。


示例 1:

输入: numRows = 5

输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]


示例 2:

输入: numRows = 1

输出: [[1]]


提示:

1 <= numRows <= 30


class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> a = new ArrayList<List<Integer>>();
    for(int i=0; i<numRows; i++) {
      List<Integer> row = new ArrayList<Integer>();
      for(int j=0; j <= i; j++) {
        if(j==0 || j==i) {
          row.add(1);
        } else {
          row.add(a.get(i-1).get(j-1) + a.get(i-1).get(j));         
        }
      }
      a.add(row);
    }
    return a;
    }
}



4、杨辉三角II


给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。


示例 1:

输入: rowIndex = 3

输出: [1,3,3,1]


示例 2:

输入: rowIndex = 0

输出: [1]


示例 3:

输入: rowIndex = 1

输出: [1,1]

 

提示:

0 <= rowIndex <= 33


class Solution {
    public List<Integer> getRow(int rowIndex) {
        int [][] a = new int[34][34];
        List<Integer> row = new ArrayList<>();
        for(int i=0; i<= rowIndex; i++) {
          for(int j=0; j<=i; j++) {
            if(j==0 || j==i) {
              a[i][j] = 1;
            } else {
              a[i][j] = a[i-1][j-1] + a[i-1][j];
            }
          }
        }
        for(int i=0; i<=rowIndex; i++) {
          row.add(a[rowIndex][i]);
        }
        return row;
    }
}


5、买股票的最佳时机


给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。


返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。


示例 1:

输入:[7,1,5,3,6,4]

输出:5

解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。

   

注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。


示例 2:


输入:prices = [7,6,4,3,1]

输出:0

解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

 

提示:


1 <= prices.length <= 105

0 <= prices[i] <= 104


class Solution {
    //dp[i]表示在第i天卖出的价值最大值,它等于当天价值减去之前所有天的最小值
    int []dp = new int[prices.length];
    //用于保存最小值
    int small = prices[0];
    for(int i=1; i<prices.length; i++) {
      //如果第i-1天的价值比前面所有天的价值小,那么最小价值更新为prices[i-1]
      if(prices[i-1] < small) {
        small = prices[i-1];
      }
      dp[i] = prices[i] - small;
    }
    //再找出dp[]中最大值,即为股票的最大价值
    int big = dp[0];
    for (int i = 1; i < dp.length; i++) {
      if(dp[i] > big) {
        big = dp[i];
      }
    }
    return big;
}



相关文章
|
29天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
38 3
|
9天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
18 2
|
8天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
13天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
13天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
13天前
|
Java 开发者
|
25天前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
52 5
|
27天前
|
安全 Java 程序员
Java集合之战:ArrayList vs LinkedList,谁才是你的最佳选择?
本文介绍了 Java 中常用的两个集合类 ArrayList 和 LinkedList,分析了它们的底层实现、特点及适用场景。ArrayList 基于数组,适合频繁查询;LinkedList 基于链表,适合频繁增删。文章还讨论了如何实现线程安全,推荐使用 CopyOnWriteArrayList 来提升性能。希望帮助读者选择合适的数据结构,写出更高效的代码。
50 3
|
13天前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
12 0
|
18天前
|
Java API Apache
java集合的组内平均值怎么计算
通过本文的介绍,我们了解了在Java中计算集合的组内平均值的几种方法。每种方法都有其优缺点,具体选择哪种方法应根据实际需求和场景决定。无论是使用传统的循环方法,还是利用Java 8的Stream API,亦或是使用第三方库(如Apache Commons Collections和Guava),都可以有效地计算集合的组内平均值。希望本文对您理解和实现Java中的集合平均值计算有所帮助。
23 0