打家劫舍+數字範圍按位與

守望精靈發表於2020-10-05

目錄

 

Leetcode213 打家劫舍

LeetCode201數字範圍按位與


Leetcode213 打家劫舍

解題思路:

在不構成環的情況下,狀態轉移方程為:

d[n] = max(dp[n-1], dp[n-2]+num)

環狀排列意味著 第一個房子和最後一個房子只能選擇一個偷竊,因此可以把此環狀排列問題約化為兩個單排排列房間子問題

  • 1. 在不偷竊第一個房子的情況下(即nums[1:]),最大金額是p_1
  • 2. 在不偷竊最後一個房子的情況下(l即nums[:n-1]),最大金額是p_2

綜合偷竊最大金額:以上兩種情況的較大值,即(max(p_1, p_2))

程式碼如下

class Solution {
    public int rob(int[] nums) {
        if(nums == null || nums.length == 0){
            return 0;
        }
        if(nums.length == 1){
            return nums[0];
        }
        if(nums.length == 2){
            return Math.max(nums[0], nums[1]);
        }
        int res1 = myRob(Arrays.copyOfRange(nums, 0, nums.length - 1));
        int res2 = myRob(Arrays.copyOfRange(nums, 1, nums.length));
        return Math.max(res1, res2);
    
    }
    public int myRob(int[] nums){
        int pre = 0;
        int cur = 0;
        for(int num : nums){
            int tmp = cur;
            cur = Math.max(pre + num, cur);
            pre = tmp;
        }
        return cur;
    }
}

LeetCode201數字範圍按位與

解題思路

例如m = 9 n = 11

先對範圍內的每個數字用二進位制的字串表示,例如9 = 00001001,然後將每個二進位制字串的位置對齊

 

得出所有數字按位與運算的結果是所有二進位制字串的公共字首再用零補上後面的剩餘位。證明如下:

假設對所有的這些二進位制,前i位均相同,第i+1位開始不同,因為[m,n]連續,所以第i+1[m,n]的數字範圍從小到大列舉出來一定是前面全部是0,後面全部是1,上圖中對應的[9,11]全是0,[12,12]全是1.並且一定存在連續的兩個數xx+1,滿足x的第i+1位為0,後面全為1,x+1的第i+1位為1,後面全為0。對應上圖中的例子11和12.這種形如0111...和1000...的二進位制的按位與的結果一定為0000...,因此第i+1位開始的剩餘均為0,前i位因為都相同,按位與結果也保持不變。最後的答案為二進位制字串的公共字首再用零補上後面的剩餘位。如何求呢?採用位移操作。

將兩個數字不斷向右移動,直到數字相等,即數字被壓縮減為它們的公共字首。然後通過將公共字首向左移動,將零新增到公共字首的右邊以獲得最終結果。

程式碼如下

class Solution {
    public int rangeBitwiseAnd(int m, int n) {
        int shift = 0;
        while(m < n){
            m >>= 1;
            n >>= 1;
            shift ++;
        }
        return m << shift;
    }
}

 

相關文章