日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面试必备算法题集之「动态规划」Ⅰ

發布時間:2025/3/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试必备算法题集之「动态规划」Ⅰ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目來源:LeetCode-騰訊-動態規劃
題庫鏈接:LeetCode傳送門

前言

這份題集來源于 LeetCode-騰訊-動態規劃 ,懷著想學習動態規劃的心(帶著害怕面試被問到的恐懼 )做了第一份DP題集,希望可以志同道合的伙伴可以共同進步。

文章目錄

  • 前言
  • 1. 爬樓梯
  • 2. 最大子序列和
  • 3. 買賣股票的最佳時機
  • 4. 買賣股票的最佳時機 II
  • 5. 不同路徑
  • 6. 子集
  • 總結

1. 爬樓梯

假設你正在爬樓梯。需要 n 階你才能到達樓頂。

每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢?

注意:給定 n 是一個正整數。

示例 1:
輸入: 2
輸出: 2

示例 2:

輸入: 3
輸出: 3

狀態轉移方程:dp[i]=dp[i?1]+dp[i?2]dp[i] = dp[i-1]+dp[i-2]dp[i]=dp[i?1]+dp[i?2]

class Solution {public int climbStairs(int n) {if (n == 1) {return 1;} else if (n == 2) {return 2;}int a = 1, b = 2;for (int i = 2; i < n; i++) {b = a + b;a = b - a;}return b;} }

2. 最大子序列和

給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。

示例:
輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6

解釋: 連續子數組 [4,-1,2,1] 的和最大,為 6。

狀態轉移方程:dp[i]=max(dp[i?1]+nums[i],nums[i])dp[i]=max(dp[i-1]+nums[i], nums[i])dp[i]=max(dp[i?1]+nums[i],nums[i])
PS: dp[i]dp[i]dp[i] 表示的是以nums[i]nums[i]nums[i]結尾的子序列的最大值

class Solution {public int maxSubArray(int[] nums) {int n = nums.length;int dp = 0, ans = Integer.MIN_VALUE;for (int i = 0; i < n; i++) {dp = Math.max(dp + nums[i], nums[i]);ans = Math.max(dp, ans);}return ans;} }

3. 買賣股票的最佳時機

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。

如果你最多只允許完成一筆交易(即買入和賣出一支股票一次),設計一個算法來計算你所能獲取的最大利潤。

注意:你不能在買入股票前賣出股票。

示例 1:
輸入: [7,1,5,3,6,4]
輸出: 5
解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。

示例 2:
輸入: [7,6,4,3,1]
輸出: 0
解釋: 在這種情況下, 沒有交易完成, 所以最大利潤為 0。

狀態轉移方程:dp[i]=max(dp[i?1],prices[i]?minPrice)dp[i] = max(dp[i-1],prices[i]-minPrice)dp[i]=max(dp[i?1],prices[i]?minPrice)
PS:其中 minPriceminPriceminPrice 表示 i 天前的最低價格。

class Solution {public int maxProfit(int[] prices) {int dp = 0, minPrice = Integer.MAX_VALUE;//計算狀態轉移方程,通過滾動變量的形式優化空間復雜度for (int i = 0; i < prices.length; i++) {minPrice = Math.min(prices[i], minPrice);dp = Math.max(dp, prices[i] - minPrice);}return dp;} }

4. 買賣股票的最佳時機 II

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。

設計一個算法來計算你所能獲取的最大利潤。你可以盡可能地完成更多的交易(多次買賣一支股票)。

注意:你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。

示例 1:
輸入: [7,1,5,3,6,4]
輸出: 7
解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 3 天(股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。隨后,在第 4 天(股票價格 = 3)的時候買入,在第 5 天(股票價格 = 6)的時候賣出, 這筆交易所能獲得利潤 = 6-3 = 3 。


狀態轉移方程(根據上面的樹形圖推導):
dp[i][0]=max(dp[i?1][0],dp[i?1][1]+prices[i])dp[i][1]=max(dp[i?1][1],dp[i?1][0]?prices[i])dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])\\ dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]) dp[i][0]=max(dp[i?1][0],dp[i?1][1]+prices[i])dp[i][1]=max(dp[i?1][1],dp[i?1][0]?prices[i])
PS:dp[i][0]dp[i][0]dp[i][0]表示第 i 天持有的現金的最大利潤,dp[i][1]dp[i][1]dp[i][1]表示第 i 天持有的股票的最大利潤。

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

可以看一下這篇題解:暴力搜索、貪心算法、動態規劃
(明明貪心就很好做……)

5. 不同路徑

一個機器人位于一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。

機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。

問總共有多少條不同的路徑?

示例 1:
輸入: m = 3, n = 2
輸出: 3
解釋:
從左上角開始,總共有 3 條路徑可以到達右下角。

  • 向右 -> 向右 -> 向下
  • 向右 -> 向下 -> 向右
  • 向下 -> 向右 -> 向右
  • 示例 2:
    輸入: m = 7, n = 3
    輸出: 28

    狀態轉移方程:dp[i][j]=dp[i?1][j]+dp[i][j?1]dp[i][j] = dp[i - 1][j] + dp[i][j-1]dp[i][j]=dp[i?1][j]+dp[i][j?1]

    class Solution {public int uniquePaths(int m, int n) {int[][] dp = new int[n][m];for (int i = 0; i < n; i++) {dp[i][0] = 1;}for (int i = 0; i < m; i++) {dp[0][i] = 1;}for (int i = 1; i < n; i++) {for (int j = 1; j < m; j++) {dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[n - 1][m - 1];} }

    (明明排列組合更加方便……)

    6. 子集

    給定一組不含重復元素的整數數組 nums,返回該數組所有可能的子集(冪集)。
    說明:解集不能包含重復的子集。

    示例:
    輸入: nums = [1,2,3]
    輸出:
    [
    [3],
    [1],
    [2],
    [1,2,3],
    [1,3],
    [2,3],
    [1,2],
    []
    ]

    狀態轉移方程:set[k]=set[j]+nums[i]set[k] = set[j] + nums[i]set[k]=set[j]+nums[i]
    PS:其中 set[k]set[k]set[k] 表示新找的一個集合, set[j]set[j]set[j] 表示原先找到的集合, nums[i]nums[i]nums[i] 表示新的數字。

    class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> ans = new ArrayList<>();// 首先添加空集ans.add(new ArrayList<>());for (int i = 0; i < nums.length; i++) {// 由于下面過程會改變容量,所以要先保存int tSize = ans.size();// 遍歷已經找到的集合for (int j = 0; j < tSize; j++) {List<Integer> temp = new ArrayList<>(ans.get(j));// 在已經找到的集合的基礎上加上新的數字就是新的集合了temp.add(nums[i]);ans.add(temp);}}return ans;} }

    不知道為啥這道題在動態規劃題單里面……(大霧 )


    總結

    終于寫完了,感覺很多題就用不著去DP,直接貪心就好了,強行DP做到我裂開。由于時間緊迫,題解也沒有寫得很詳細,就將就著看吧,有問題可以留言提出來哦~

    總結

    以上是生活随笔為你收集整理的面试必备算法题集之「动态规划」Ⅰ的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。