1. 程式人生 > 實用技巧 >常用技巧:位運算的奇技淫巧

常用技巧:位運算的奇技淫巧

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

示例:

輸入: [-2,1,-3,4,-1,2,1,-5,4]
輸出: 6
解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。

class Solution:
    #定義一個函式f(n),以第n個數為結束點的子數列的最大和,存在一個遞推關係f(n) = max(f(n-1) + A[n], A[n]);
    def f(self,n,nums):
        if n==0:
            return nums[0]
        return max(self.f(n-1,nums)+nums[n],nums[n])
        
    
#將這些最大和儲存下來後,取最大的那個就是,最大子陣列和。 def maxSubArray(self, nums): nums_len=len(nums) result=float("-inf") for i in range(0,nums_len):#從0開始 result=max(self.f(i,nums),result) return result

2. 一個有名的按摩師會收到源源不斷的預約請求,每個預約都可以選擇接或不接。
在每次預約服務之間要有休息時間,因此她不能接受相鄰的預約。
給定一個預約請求序列,替按摩師找到最優的預約集合(總預約時間最長),返回總的分鐘數。

注意:本題相對原題稍作改動

示例 1:

輸入: [1,2,3,1]
輸出: 4
解釋: 選擇 1 號預約和 3 號預約,總時長 = 1 + 3 = 4。

示例 2:

輸入: [2,7,9,3,1]
輸出: 12
解釋: 選擇 1 號預約、 3 號預約和 5 號預約,總時長 = 2 + 9 + 1 = 12。

示例 3:

輸入: [2,1,4,5,3,1,1,3]
輸出: 12
解釋: 選擇 1 號預約、 3 號預約、 5 號預約和 8 號預約,總時長 = 2 + 4 + 3 + 3 = 12。

方法一:設計二維狀態變數
第 1 步:設計狀態

「狀態」這個詞可以理解為「記錄了求解問題到了哪一個階段」。

由於當前這一天有按摩師有兩種選擇:(1)接預約;(2)不接預約。但根據題意,今天是否接預約,是受到昨天影響的。為了消除這種影響,我們在狀態陣列要設定這個維度。

dp[i][0] 表示:區間 [0,i] 裡不接受預約請求,並且下標為 i 的這一天不接受預約的最大時長;
dp[i][1] 表示:區間 [0,i] 裡接受預約請求,並且下標為 i 的這一天接受預約的最大時長。

今天只和昨天的狀態相關,依然是分類討論:

今天不接受預約:或者是昨天不接受預約,或者是昨天接受了預約,取二者最大值,即:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);
今天接受預約:只需要從昨天不接受預約轉移而來,加上今天的時常,即:dp[i][1] = dp[i - 1][0] + nums[i]。

第 3 步:考慮初始化

從第 2 天開始,每天的狀態值只與前一天有關,因此第 1 天就只好老老實實算了。好在不難判斷:dp[0][0] = 0 與 dp[0][1] = nums[0];

class Solution:
       
    def massage(self, nums):
        nums_len = len(nums)
        if nums_len == 0:
            return 0
        if nums_len == 1:
            return nums[0]
        dp = [[0 for i in range(2)] for j in range(nums_len)]


        dp[0][0] = 0
        dp[0][1] = nums[0]
        
        for i in range(nums_len):
            # 今天不接受預約
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1])
            # 今天接受預約
            dp[i][1] = dp[i - 1][0] + nums[i]
        return max(dp[nums_len - 1][0], dp[nums_len - 1][1])