[198].打家劫舍

 


題目

你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。

給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。

示例 1:

輸入: [1,2,3,1]
輸出: 4
解釋: 偷竊 1 號房屋 (金額 = 1) ,然後偷竊 3 號房屋 (金額 = 3)。
     偷竊到的最高金額 = 1 + 3 = 4

示例 2:

輸入: [2,7,9,3,1]
輸出: 12
解釋: 偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接着偷竊 5 號房屋 (金額 = 1)。
     偷竊到的最高金額 = 2 + 9 + 1 = 12

 


函數原型

C 的函數原型:

int rob(int* nums, int numsSize){}

 


邊界判斷

int rob(int* nums, int numsSize){
	if( nums == NULL || numsSize == 0 )
		return 0;
}

 


算法設計:遞歸

inline int max(int a, int b){
    return a > b ? a : b;
}

int __rob(int *nums, int numsSize, int index){
    if( index >= numsSize )
        return 0;
    
    int max_ans = 0;
    for(int i=index; i<numsSize; i++)
        max_ans = max( max_ans, nums[i] + __rob(nums, numsSize, i + 2) );

    return max_ans;
}

int rob(int* nums, int numsSize){
    if( nums == NULL || numsSize == 0 )
		return 0;

    return __rob(nums, numsSize, 0);
}

遞歸的複雜度:

  • 時間複雜度:Θ(2n)\Theta(2^{n})
  • 空間複雜度:Θ(n)\Theta(n)
     

算法設計:遞歸+記憶化搜索

int memo[1<<10];    // 左移10位,相當於乘10個2
inline int max(int a, int b){
    return a > b ? a : b;
}

int __rob(int *nums, int numsSize, int index){
    if( index >= numsSize )
        return 0;
    if( memo[index] )
        return memo[index];

    int max_ans = 0;
    for(int i=index; i<numsSize; i++)
        max_ans = max( max_ans, nums[i] + __rob(nums, numsSize, i + 2) );

    memo[index] = max_ans;
    return max_ans;
}

int rob(int* nums, int numsSize){
    if( nums == NULL || numsSize == 0 )
		return 0;

    return __rob(nums, numsSize, 0);
}

遞歸+記憶化搜索的複雜度:

  • 時間複雜度:Θ(n)\Theta(n)
  • 空間複雜度:Θ(n)\Theta(n)
     

算法設計:動態規劃

從前往後遞推…

狀態轉移方程:dp[i]=max(dp[i1],dp[i2]+nums[i])dp[i] = max(dp[i-1], dp[i-2] + nums[i])

inline int max(int a, int b){
    return a > b ? a : b;
}

int rob(int* nums, int numsSize){
    int n = numsSize;
    if( n == 0 )
        return 0;
    if( n == 1)
        return nums[0];

    int memo[1<<10];
    memset(memo, 0, sizeof(int) * 1024);
    memo[0] = nums[0];
    memo[1] = max(nums[0], nums[1]);

	for(int i=2; i<n; i++)
		memo[i] = max(memo[i-1], (memo[i-2]+nums[i]));

    return memo[n-1];
}

or

從後往前遞推:

inline int max(int a, int b){
    return a > b ? a : b;
}

int rob(int* nums, int numsSize){
    int n = numsSize;
    if( n == 0 )
        return 0;

    int memo[1<<10];
    memset(memo, 0, sizeof(int) * 1024);
    memo[n-1] = nums[n-1];

    for(int i=n-2; i>=0; i--)
        for(int j=i; j<n; j++)
            memo[i] = max( memo[i] , nums[j] + (j + 2 < n ? memo[j+2] : 0) );

    return memo[0];
}

動態規劃的複雜度:

  • 時間複雜度:Θ(n)\Theta(n)
  • 空間複雜度:Θ(n)\Theta(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章