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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[Leedcode][JAVA][按摩师][动态规划]

發(fā)布時(shí)間:2023/12/10 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Leedcode][JAVA][按摩师][动态规划] 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【問題描述】

一個(gè)有名的按摩師會(huì)收到源源不斷的預(yù)約請(qǐng)求,每個(gè)預(yù)約都可以選擇接或不接。在每次預(yù)約服務(wù)之間要有休息時(shí)間,因此她不能接受相鄰的預(yù)約。給定一個(gè)預(yù)約請(qǐng)求序列,替按摩師找到最優(yōu)的預(yù)約集合(總預(yù)約時(shí)間最長(zhǎng)),返回總的分鐘數(shù)。注意:本題相對(duì)原題稍作改動(dòng)示例 1:輸入: [1,2,3,1] 輸出: 4 解釋: 選擇 1 號(hào)預(yù)約和 3 號(hào)預(yù)約,總時(shí)長(zhǎng) = 1 + 3 = 4。 示例 2:輸入: [2,7,9,3,1] 輸出: 12 解釋: 選擇 1 號(hào)預(yù)約、 3 號(hào)預(yù)約和 5 號(hào)預(yù)約,總時(shí)長(zhǎng) = 2 + 9 + 1 = 12。 示例 3:輸入: [2,1,4,5,3,1,1,3] 輸出: 12 解釋: 選擇 1 號(hào)預(yù)約、 3 號(hào)預(yù)約、 5 號(hào)預(yù)約和 8 號(hào)預(yù)約,總時(shí)長(zhǎng) = 2 + 4 + 3 + 3 = 12。

【解答思路】

1. 動(dòng)態(tài)規(guī)劃 二維狀態(tài)變量 由前往后 想清楚每一步

時(shí)間復(fù)雜度:O(N) 空間復(fù)雜度:O(N)

  • 設(shè)計(jì)狀態(tài)
    • dp[i][0] 表示:區(qū)間 [0,i] 里接受預(yù)約請(qǐng)求,并且下標(biāo)為 i 的這一天不接受預(yù)約的最大時(shí)長(zhǎng);
    • dp[i][1] 表示:區(qū)間 [0,i] 里接受預(yù)約請(qǐng)求,并且下標(biāo)為 i 的這一天接受預(yù)約的最大時(shí)長(zhǎng)。
  • 狀態(tài)轉(zhuǎn)移方程
    • 今天不接受預(yù)約:或者是昨天不接受預(yù)約,或者是昨天接受了預(yù)約,取二者最大值,即:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);
    • 今天接受預(yù)約:只需要從昨天不接受預(yù)約轉(zhuǎn)移而來,加上今天的時(shí)常,即:dp[i][1] = dp[i - 1][0] + nums[i]。

    3.初始化
    dp[0][0] = 0 與 dp[0][1] = nums[0];

    public int massage(int[] nums) {int len = nums.length;if (len == 0) {return 0;}if (len == 1) {return nums[0];}// dp[i][0]:區(qū)間 [0, i] 里接受預(yù)約請(qǐng)求,并且下標(biāo)為 i 的這一天不接受預(yù)約的最大時(shí)長(zhǎng)// dp[i][1]:區(qū)間 [0, i] 里接受預(yù)約請(qǐng)求,并且下標(biāo)為 i 的這一天接受預(yù)約的最大時(shí)長(zhǎng)int[][] dp = new int[len][2];dp[0][0] = 0;dp[0][1] = nums[0];for (int i = 1; i < len; i++) {dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1]);dp[i][1] = dp[i - 1][0] + nums[i];}return Math.max(dp[len - 1][0], dp[len - 1][1]);}

    優(yōu)化:狀態(tài)數(shù)組多設(shè)置一行,以避免對(duì)極端用例進(jìn)行討論

    public class Solution {public int massage(int[] nums) {int len = nums.length;// dp 數(shù)組多設(shè)置一行,相應(yīng)地定義就要改變,遍歷的一些細(xì)節(jié)也要相應(yīng)改變// dp[i][0]:區(qū)間 [0, i) 里接受預(yù)約請(qǐng)求,并且下標(biāo)為 i 的這一天不接受預(yù)約的最大時(shí)長(zhǎng)// dp[i][1]:區(qū)間 [0, i) 里接受預(yù)約請(qǐng)求,并且下標(biāo)為 i 的這一天接受預(yù)約的最大時(shí)長(zhǎng)int[][] dp = new int[len + 1][2];// 注意:外層循環(huán)從 1 到 =len,相對(duì) dp 數(shù)組而言,引用到 nums 數(shù)組的時(shí)候就要 -1for (int i = 1; i <= len; i++) {dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1]);dp[i][1] = dp[i - 1][0] + nums[i - 1];}return Math.max(dp[len][0], dp[len][1]);} }

    優(yōu)化 [滾動(dòng)數(shù)組] 三個(gè)變量 時(shí)間復(fù)雜度:O(N) 空間復(fù)雜度:O(1)

    public class Solution {public int massage(int[] nums) {int len = nums.length;if (len == 0) {return 0;}if (len == 1) {return nums[0];}// dp[i & 1][0]:區(qū)間 [0, i] 里接受預(yù)約請(qǐng)求,并且下標(biāo)為 i 的這一天不接受預(yù)約的最大時(shí)長(zhǎng)// dp[i & 1][1]:區(qū)間 [0, i] 里接受預(yù)約請(qǐng)求,并且下標(biāo)為 i 的這一天接受預(yù)約的最大時(shí)長(zhǎng)int[][] dp = new int[2][2];dp[0][0] = 0;dp[0][1] = nums[0];for (int i = 1; i < len; i++) {dp[i & 1][0] = Math.max(dp[(i - 1) & 1][0], dp[(i - 1) & 1][1]);dp[i & 1][1] = dp[(i - 1) & 1][0] + nums[i];}return Math.max(dp[(len - 1) & 1][0], dp[(len - 1) & 1][1]);} }

    ?###### 2. 動(dòng)態(tài)規(guī)劃 一維狀態(tài)變量 由前往后 想清楚每一步
    時(shí)間復(fù)雜度:O(N) 空間復(fù)雜度:O(N)

    public int massage(int[] nums) {int len = nums.length;if (len == 0) {return 0;}if (len == 1) {return nums[0];}// dp[i]:區(qū)間 [0, i] 里接受預(yù)約請(qǐng)求的最大時(shí)長(zhǎng)int[] dp = new int[len];//初始化狀態(tài)dp[0] = nums[0];dp[1] = Math.max(nums[0], nums[1]);for (int i = 2; i < len; i++) {// 今天在選與不選中,選擇一個(gè)最優(yōu)的dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);}return dp[len - 1];}

    優(yōu)化 [滾動(dòng)數(shù)組] 三個(gè)變量 時(shí)間復(fù)雜度:O(N) 空間復(fù)雜度:O(1)

    class Solution {public int massage(int[] nums) {int len = nums.length;if (len == 0) {return 0;}if (len == 1) {return nums[0];}// dp[i % 3]:區(qū)間 [0,i] 里接受預(yù)約請(qǐng)求的最大時(shí)長(zhǎng)int[] dp = new int[3];dp[0] = nums[0];dp[1] = Math.max(nums[0], nums[1]);for (int i = 2; i < len; i++) {// 今天在選與不選中,選擇一個(gè)最優(yōu)的dp[i % 3] = Math.max(dp[(i - 1) % 3], dp[(i - 2) % 3] + nums[i]);}return dp[(len - 1) % 3];} }

    【總結(jié)】

    1.動(dòng)態(tài)規(guī)劃流程

    • 第 1 步:設(shè)計(jì)狀態(tài)
    • 第 2 步:狀態(tài)轉(zhuǎn)移方程
    • 第 3 步:考慮初始化
    • 第 4 步:考慮輸出
    • 第 5 步:考慮是否可以狀態(tài)壓縮

    2.動(dòng)態(tài)規(guī)劃 自底向上 狀態(tài)轉(zhuǎn)移
    [一般編程] 自頂向下
    [記憶化遞歸」隨時(shí)可能面對(duì)新問題

    參考鏈接:https://leetcode-cn.com/problems/the-masseuse-lcci/solution/dong-tai-gui-hua-by-liweiwei1419-8/

    總結(jié)

    以上是生活随笔為你收集整理的[Leedcode][JAVA][按摩师][动态规划]的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。