打家劫舍

47 阅读8分钟

打家劫舍

有N栋房子排成一排,每栋房子都有一些现金。小偷要偷走这些房子中的现金,但他不能偷窃相邻的两栋房子,因为被盗房子的主人会告诉他的左右两侧的邻居。任务是找出小偷最多可以盗走多少现金。

例子:

输入:hval[] = {6, 7, 1, 3, 8, 2, 4}
输出:19
解释: 小偷将从房子里偷走 6、1、8 和 4。

输入:hval[] = {5, 3, 4, 11, 2}
输出:16
解释:小偷会偷走 5 和 11

动态规划(自上而下的方法):

请按照以下步骤实施该想法:

  • 创建一个大小为 n+1、值为 -1 的 DP 数组,变量 pick 和 not pick。
  • 创建一个递归函数 maxLoot
    • 如果 n < 0,则返回 0。
    • 如果n = 0,则返回 hval[0]。
    • 如果 DP[n] != -1,则返回 DP[n]。
    • 如果第 n 个房子被偷, 那么 第 n-1 个房子必不能偷,只能从第 n-2 个 房子起偷,所以 pick = hval[n] + maxLoot(hval, n-2, DP)
    • 如果第 n 个房子没有被偷,那么 notPick = maxLoot(hval, n-1, DP)。
    • 设置 Dp[n] = max(pick, notPick) 并返回 DP[n]。

下面是上述方法的实现:

C++

// CPP program to find the maximum stolen value 
#include <bits/stdc++.h> 
using namespace std; 
  
// calculate the maximum stolen value 
int maxLoot(int *hval, int n, vector<int> &dp){ 
    
   // base case 
   if(n < 0){ 
           return 0 ; 
   } 
     
   if(n == 0){ 
           return hval[0] ; 
   } 
   // If the subproblem is already solved 
   // then return its value 
   if(dp[n] != -1 ){ 
          return dp[n] ; 
   } 
    
   //if current element is pick then previous cannot be picked 
   int pick = hval[n] +  maxLoot(hval, n-2, dp) ; 
   //if current element is not picked then previous element is picked 
   int notPick = maxLoot(hval, n-1, dp)  ; 
    
   // return max of picked and not picked 
   return dp[n] = max(pick, notPick) ; 
    
} 
  
// Driver to test above code 
int main() 
{ 
    int hval[] = {6, 7, 1, 3, 8, 2, 4}; 
    int n = sizeof(hval)/sizeof(hval[0]); 
    // Initialize a dp vector 
    vector<int> dp(n+1, -1) ; 
    cout << "Maximum loot possible : "
        << maxLoot(hval, n-1, dp); 
    return 0; 
} 

Java

/*package whatever //do not write package name here */
  
// Java program to find the maximum stolen value 
import java.io.*; 
import java.util.Arrays; 
  
class GFG { 
  // Function to calculate the maximum stolen value 
  static int maxLoot(int hval[], int n, int dp[]) 
  { 
    // base case 
    if (n < 0) { 
      return 0; 
    } 
  
    if (n == 0) { 
      return hval[0]; 
    } 
    // If the subproblem is already solved 
    // then return its value 
    if (dp[n] != -1) { 
      return dp[n]; 
    } 
  
    // if current element is pick then previous cannot 
    // be picked 
    int pick = hval[n] + maxLoot(hval, n - 2, dp); 
    // if current element is not picked then previous 
    // element is picked 
    int notPick = maxLoot(hval, n - 1, dp); 
  
    // return max of picked and not picked 
    return dp[n] = Math.max(pick, notPick); 
  } 
  
  // Driver program 
  public static void main(String[] args) 
  { 
    int hval[] = { 6, 7, 1, 3, 8, 2, 4 }; 
    int n = hval.length; 
    int dp[] = new int[n + 1]; 
    Arrays.fill(dp, -1); 
    System.out.println("Maximum loot possible : "
                       + maxLoot(hval, n - 1, dp)); 
  } 
} 
  

Python

# Python3 program to find the maximum stolen value 
  
# calculate the maximum stolen value 
  
  
def maxLoot(hval, n, dp): 
  
    # base case 
    if(n < 0): 
        return 0
  
    if(n == 0): 
        return hval[0] 
  
   # If the subproblem is already solved 
   # then return its value 
    if(dp[n] != -1): 
        return dp[n] 
  
    # if current element is pick then previous cannot be picked 
    pick = hval[n] + maxLoot(hval, n-2, dp) 
  
    # if current element is not picked then previous element is picked 
    notPick = maxLoot(hval, n-1, dp) 
  
    # return max of picked and not picked 
    dp[n] = max(pick, notPick) 
    return dp[n] 
  
  
# Driver to test above code 
hval = [6, 7, 1, 3, 8, 2, 4] 
n = len(hval) 
  
# Initialize a dp vector 
dp = [-1 for i in range(n+1)] 
print("Maximum loot possible : "+str(maxLoot(hval, n-1, dp))) 
  

C#

// C# program to find the maximum stolen value 
using System; 
public class GFG { 
  
    // Function to calculate the maximum stolen value 
    static int maxLoot(int[] hval, int n, int[] dp) 
    { 
        
        // base case 
        if (n < 0) { 
            return 0; 
        } 
  
        if (n == 0) { 
            return hval[0]; 
        } 
        // If the subproblem is already solved 
        // then return its value 
        if (dp[n] != -1) { 
            return dp[n]; 
        } 
  
        // if current element is pick then previous cannot 
        // be picked 
        int pick = hval[n] + maxLoot(hval, n - 2, dp); 
        
        // if current element is not picked then previous 
        // element is picked 
        int notPick = maxLoot(hval, n - 1, dp); 
  
        // return max of picked and not picked 
        return dp[n] = Math.Max(pick, notPick); 
    } 
  
    static public void Main() 
    { 
  
        // Code 
        int[] hval = { 6, 7, 1, 3, 8, 2, 4 }; 
        int n = hval.Length; 
        int[] dp = new int[n + 1]; 
        Array.Fill(dp, -1); 
        Console.WriteLine("Maximum loot possible : "
                          + maxLoot(hval, n - 1, dp)); 
    } 
} 
  

Javascript

<script> 
  
// JavaScript program to find the maximum stolen value 
  
// calculate the maximum stolen value 
function maxLoot(hval,n,dp){ 
    
   // base case 
   if(n < 0){ 
        return 0 ; 
   } 
     
   if(n == 0){ 
        return hval[0] ; 
   } 
   // If the subproblem is already solved 
   // then return its value 
   if(dp[n] != -1 ){ 
        return dp[n] ; 
   } 
    
   //if current element is pick then previous cannot be picked 
   let pick = hval[n] +  maxLoot(hval, n-2, dp) ; 
   //if current element is not picked then previous element is picked 
   let notPick = maxLoot(hval, n-1, dp)  ; 
    
   // return max of picked and not picked 
   return dp[n] = Math.max(pick, notPick) ; 
    
} 
  
// Driver to test above code 
let hval = [6, 7, 1, 3, 8, 2, 4]; 
let n = hval.length; 
// Initialize a dp vector 
let dp = new Array(n+1).fill(-1) ; 
document.write("Maximum loot possible : ",maxLoot(hval, n-1, dp),"</br>"); 
  
</script>

输出

Maximum loot possible : 19

时间复杂度:O(n)。只需要对原始数组进行一次遍历。所以时间复杂度是O(n)
空间复杂度:O(n)。

动态规划(自下而上方法):

请按照以下步骤实施该想法:

  • 创建一个额外空间的DP数组来存储子问题。
  • 处理以下基本情况,
    • 如果数组长度为0,则打印0。
    • 如果数组长度为1,则打印第一个元素。
    • 如果数组长度为2,则打印两个元素中的较大值。
  • 将 dp[0] 更新为 array[0],将 dp[1] 更新为 array[0] 和 array[1] 中的最大值
  • 从第二个元素(第二个索引)遍历数组到数组末尾。
  • 对于每个索引,将 dp[i] 更新为 dp[i-2] + array[i] 和 dp[i-1] 中的最大值,此步骤定义了两种情况:如果选择了一个元素,则前一个元素不能被选择,如果未选择,则可以选择前一个元素。
  • 打印值 dp[n-1]

下面是上述方法的实现:

C++

// CPP program to find the maximum stolen value 
#include <iostream> 
using namespace std; 
  
// calculate the maximum stolen value 
int maxLoot(int* hval, int n) 
{ 
    if (n == 0) 
        return 0; 
    if (n == 1) 
        return hval[0]; 
    if (n == 2) 
        return max(hval[0], hval[1]); 
  
    // dp[i] represent the maximum value stolen 
    // so far after reaching house i. 
    int dp[n]; 
  
    // Initialize the dp[0] and dp[1] 
    dp[0] = hval[0]; 
    dp[1] = max(hval[0], hval[1]); 
  
    // Fill remaining positions 
    for (int i = 2; i < n; i++) 
        dp[i] = max(hval[i] + dp[i - 2], dp[i - 1]); 
  
    return dp[n - 1]; 
} 
  
// Driver to test above code 
int main() 
{ 
    int hval[] = { 6, 7, 1, 3, 8, 2, 4 }; 
    int n = sizeof(hval) / sizeof(hval[0]); 
    cout << "Maximum loot possible : " << maxLoot(hval, n); 
    return 0; 
} 
  

C

// C program to find the maximum stolen value 
#include <stdio.h> 
  
// Find maximum between two numbers. 
int max(int num1, int num2) 
{ 
    return (num1 > num2) ? num1 : num2; 
} 
  
// calculate the maximum stolen value 
int maxLoot(int* hval, int n) 
{ 
    if (n == 0) 
        return 0; 
    if (n == 1) 
        return hval[0]; 
    if (n == 2) 
        return max(hval[0], hval[1]); 
  
    // dp[i] represent the maximum value stolen 
    // so far after reaching house i. 
    int dp[n]; 
  
    // Initialize the dp[0] and dp[1] 
    dp[0] = hval[0]; 
    dp[1] = max(hval[0], hval[1]); 
  
    // Fill remaining positions 
    for (int i = 2; i < n; i++) 
        dp[i] = max(hval[i] + dp[i - 2], dp[i - 1]); 
  
    return dp[n - 1]; 
} 
  
// Driver to test above code 
int main() 
{ 
    int hval[] = { 6, 7, 1, 3, 8, 2, 4 }; 
    int n = sizeof(hval) / sizeof(hval[0]); 
    printf("Maximum loot possible : %d", maxLoot(hval, n)); 
    return 0; 
} 
  

Java

// Java program to find the maximum stolen value 
import java.io.*; 
  
class GFG { 
    // Function to calculate the maximum stolen value 
    static int maxLoot(int hval[], int n) 
    { 
        if (n == 0) 
            return 0; 
        if (n == 1) 
            return hval[0]; 
        if (n == 2) 
            return Math.max(hval[0], hval[1]); 
  
        // dp[i] represent the maximum value stolen 
        // so far after reaching house i. 
        int[] dp = new int[n]; 
  
        // Initialize the dp[0] and dp[1] 
        dp[0] = hval[0]; 
        dp[1] = Math.max(hval[0], hval[1]); 
  
        // Fill remaining positions 
        for (int i = 2; i < n; i++) 
            dp[i] 
                = Math.max(hval[i] + dp[i - 2], dp[i - 1]); 
  
        return dp[n - 1]; 
    } 
  
    // Driver program 
    public static void main(String[] args) 
    { 
        int hval[] = { 6, 7, 1, 3, 8, 2, 4 }; 
        int n = hval.length; 
        System.out.println("Maximum loot possible : " + maxLoot(hval, n)); 
    } 
} 
  

Python

# Python3 program to find the maximum stolen value 
  
# calculate the maximum stolen value 
def maximize_loot(hval, n): 
    if n == 0: 
        return 0
    if n == 1: 
        return hval[0] 
    if n == 2: 
        return max(hval[0], hval[1]) 
  
    # dp[i] represent the maximum value stolen so 
    # for after reaching house i. 
    dp = [0]*n 
  
    # Initialize the dp[0] and dp[1] 
    dp[0] = hval[0] 
    dp[1] = max(hval[0], hval[1]) 
      
    # Fill remaining positions 
    for i in range(2, n): 
        dp[i] = max(hval[i]+dp[i-2], dp[i-1]) 
  
    return dp[-1] 
  
# Driver to test above code  
def main(): 
  
    # Value of houses 
    hval = [6, 7, 1, 3, 8, 2, 4] 
  
    # number of houses 
    n = len(hval) 
    print("Maximum loot possible : {}". 
        format(maximize_loot(hval, n))) 
  
if __name__ == '__main__': 
    main() 

C#

// C# program to find the  
// maximum stolen value 
using System; 
          
class GFG  
{ 
   // Function to calculate the  
   // maximum stolen value 
    static int maxLoot(int []hval, int n) 
    { 
        if (n == 0) 
        return 0; 
        if (n == 1) 
            return hval[0]; 
        if (n == 2) 
            return Math.Max(hval[0], hval[1]); 
  
        // dp[i] represent the maximum value stolen 
        // so far after reaching house i. 
        int[] dp = new int[n]; 
  
        // Initialize the dp[0] and dp[1] 
        dp[0] = hval[0]; 
        dp[1] = Math.Max(hval[0], hval[1]); 
  
        // Fill remaining positions 
        for (int i = 2; i<n; i++) 
            dp[i] = Math.Max(hval[i]+dp[i-2], dp[i-1]); 
  
        return dp[n-1]; 
    } 
      
    // Driver program 
    public static void Main ()  
    { 
        int []hval = {6, 7, 1, 3, 8, 2, 4}; 
        int n = hval.Length; 
        Console.WriteLine("Maximum loot possible : " +  
                                 maxLoot(hval, n)); 
    } 
} 
  

PHP

<?php 
// PHP program to find  
// the maximum stolen value 
  
// calculate the maximum 
// stolen value 
function maxLoot($hval, $n) 
{ 
    if ($n == 0) 
        return 0; 
    if ($n == 1) 
        return $hval[0]; 
    if ($n == 2) 
        return max($hval[0],  
                   $hval[1]); 
  
    // dp[i] represent the maximum  
    // value stolen so far after  
    // reaching house i. 
    $dp = array(); 
  
    // Initialize the  
    // dp[0] and dp[1] 
    $dp[0] = $hval[0]; 
    $dp[1] = max($hval[0],  
                 $hval[1]); 
  
    // Fill remaining positions 
    for ($i = 2; $i < $n; $i++) 
        $dp[$i] = max($hval[$i] +  
                      $dp[$i - 2],  
                      $dp[$i - 1]); 
  
    return $dp[$n - 1]; 
} 
  
// Driver Code 
$hval = array(6, 7, 1,  
              3, 8, 2, 4); 
$n = sizeof($hval); 
echo "Maximum loot possible : ", 
             maxLoot($hval, $n); 
      
?> 

Javascript

<script> 
  
    // Javascript program to find  
    // the maximum stolen value 
      
    // Function to calculate the  
       // maximum stolen value 
    function maxLoot(hval, n) 
    { 
        if (n == 0) 
            return 0; 
        if (n == 1) 
            return hval[0]; 
        if (n == 2) 
            return Math.max(hval[0], hval[1]); 
    
        // dp[i] represent the maximum value stolen 
        // so far after reaching house i. 
        let dp = new Array(n); 
    
        // Initialize the dp[0] and dp[1] 
        dp[0] = hval[0]; 
        dp[1] = Math.max(hval[0], hval[1]); 
    
        // Fill remaining positions 
        for (let i = 2; i<n; i++) 
            dp[i] = Math.max(hval[i]+dp[i-2], dp[i-1]); 
    
        return dp[n-1]; 
    } 
      
    let hval = [6, 7, 1, 3, 8, 2, 4]; 
    let n = hval.length; 
    document.write( 
    "Maximum loot possible : " + maxLoot(hval, n) 
    ); 
      
</script>

输出

Maximum loot possible : 19

时间复杂度:O(N)。只需要对原始数组进行一次遍历。所以时间复杂度是O(n)
辅助空间:O(N)。需要一个大小为 n 的数组,因此空间复杂度为 O(n)。

使用常数 空间:

仔细观察DP数组,可以看出在计算一个索引的值时,前两个索引的值很重要。可以用两个变量替换 DP 数组。

请按照以下步骤实施该想法:

  • 处理一些基本情况,如果数组长度为0,则打印0,如果数组长度为1,则打印第一个元素,如果数组长度为2,则打印两元素中的较大值。
  • 创建两个变量value1和value2,value1作为array[0],value2作为array[0]和array[1]的最大值,以及一个变量max_val来存储答案
  • 从第二个元素(第二个索引)遍历数组到数组末尾。
  • 对于每个索引,将 max_val 更新为 value1 + array[i] 和 value2 中的最大值,这一步定义了两种情况,如果一个元素被选择,则前一个元素不能被选择,如果一个元素没有被选择,则前一个元素可以选择。
  • 对于每个索引,更新 value1 = value2 且 value2 = max_val
  • 打印max_val的值

下面是上述方法的实现:

C++

// C++ program to find the maximum stolen value 
#include <iostream> 
using namespace std; 
  
// calculate the maximum stolen value 
int maxLoot(int* hval, int n) 
{ 
    if (n == 0) 
        return 0; 
  
    int value1 = hval[0]; 
    if (n == 1) 
        return value1; 
  
    int value2 = max(hval[0], hval[1]); 
    if (n == 2) 
        return value2; 
  
    // contains maximum stolen value at the end 
    int max_val; 
  
    // Fill remaining positions 
    for (int i = 2; i < n; i++) { 
        max_val = max(hval[i] + value1, value2); 
        value1 = value2; 
        value2 = max_val; 
    } 
  
    return max_val; 
} 
  
// Driver to test above code 
int main() 
{ 
    // Value of houses 
    int hval[] = { 6, 7, 1, 3, 8, 2, 4 }; 
    int n = sizeof(hval) / sizeof(hval[0]); 
    cout << "Maximum loot possible : " << maxLoot(hval, n); 
    return 0; 
} 
  

C

// C program to find the maximum stolen value 
#include <stdio.h> 
  
//Find maximum between two numbers. 
int max(int num1, int num2) 
{ 
  return (num1 > num2) ? num1 : num2; 
} 
  
// calculate the maximum stolen value 
int maxLoot(int* hval, int n) 
{ 
    if (n == 0) 
        return 0; 
  
    int value1 = hval[0]; 
    if (n == 1) 
        return value1; 
  
    int value2 = max(hval[0], hval[1]); 
    if (n == 2) 
        return value2; 
  
    // contains maximum stolen value at the end 
    int max_val; 
  
    // Fill remaining positions 
    for (int i = 2; i < n; i++) { 
        max_val = max(hval[i] + value1, value2); 
        value1 = value2; 
        value2 = max_val; 
    } 
  
    return max_val; 
} 
  
// Driver to test above code 
int main() 
{ 
    // Value of houses 
    int hval[] = { 6, 7, 1, 3, 8, 2, 4 }; 
    int n = sizeof(hval) / sizeof(hval[0]); 
    printf("Maximum loot possible : %d", maxLoot(hval, n)); 
    return 0; 
} 
  

Java

// Java program to find the maximum stolen value 
import java.io.*; 
  
class GFG { 
    // Function to calculate the maximum stolen value 
    static int maxLoot(int hval[], int n) 
    { 
        if (n == 0) 
            return 0; 
  
        int value1 = hval[0]; 
        if (n == 1) 
            return value1; 
  
        int value2 = Math.max(hval[0], hval[1]); 
        if (n == 2) 
            return value2; 
  
        // contains maximum stolen value at the end 
        int max_val = 0; 
  
        // Fill remaining positions 
        for (int i = 2; i < n; i++) { 
            max_val = Math.max(hval[i] + value1, value2); 
            value1 = value2; 
            value2 = max_val; 
        } 
  
        return max_val; 
    } 
  
    // driver program 
    public static void main(String[] args) 
    { 
        int hval[] = { 6, 7, 1, 3, 8, 2, 4 }; 
        int n = hval.length; 
        System.out.println("Maximum loot possible : "
                           + maxLoot(hval, n)); 
    } 
} 
  

Python

# Python3 program to find the maximum stolen value 
  
# calculate the maximum stolen value 
def maximize_loot(hval, n): 
    if n == 0: 
        return 0
  
    value1 = hval[0] 
    if n == 1: 
        return value1 
  
    value2 = max(hval[0], hval[1]) 
    if n == 2: 
        return value2 
  
    # contains maximum stolen value at the end 
    max_val = None
  
    # Fill remaining positions 
    for i in range(2, n): 
        max_val = max(hval[i]+value1, value2) 
        value1 = value2 
        value2 = max_val 
  
    return max_val 
  
# Driver to test above code  
def main(): 
  
    # Value of houses 
    hval = [6, 7, 1, 3, 8, 2, 4] 
  
    # number of houses 
    n = len(hval) 
    print("Maximum loot possible : {}".format(maximize_loot(hval, n))) 
  
if __name__ == '__main__': 
    main() 

C#

// C# program to find the  
// maximum stolen value 
using System; 
          
public class GFG  
{ 
    // Function to calculate the  
    // maximum stolen value 
    static int maxLoot(int []hval, int n) 
    { 
        if (n == 0) 
        return 0; 
  
        int value1 = hval[0]; 
        if (n == 1) 
            return value1; 
  
        int value2 = Math.Max(hval[0], hval[1]); 
        if (n == 2) 
            return value2; 
      
        // contains maximum stolen value at the end 
        int max_val = 0; 
  
        // Fill remaining positions 
        for (int i = 2; i < n; i++) 
        { 
            max_val = Math.Max(hval[i] + value1, value2); 
            value1 = value2; 
            value2 = max_val; 
        } 
  
        return max_val; 
    } 
      
    // Driver program 
    public static void Main ()  
    { 
        int []hval = {6, 7, 1, 3, 8, 2, 4}; 
        int n = hval.Length; 
        Console.WriteLine("Maximum loot possible : " + 
                                 maxLoot(hval, n)); 
    } 
} 
  

PHP

<?php 
// PHP program to find  
// the maximum stolen value 
  
// calculate the  
// maximum stolen value 
function maxLoot($hval, $n) 
{ 
    if ($n == 0) 
        return 0; 
  
    $value1 = $hval[0]; 
    if ($n == 1) 
        return $value1; 
  
    $value2 = max($hval[0],  
                  $hval[1]); 
    if ($n == 2) 
        return $value2; 
  
    // contains maximum  
    // stolen value at the end 
    $max_val; 
  
    // Fill remaining positions 
    for ($i = 2; $i < $n; $i++) 
    { 
        $max_val = max($hval[$i] +  
                       $value1, $value2); 
        $value1 = $value2; 
        $value2 = $max_val; 
    } 
  
    return $max_val; 
} 
  
// Driver code 
$hval = array(6, 7, 1, 3, 8, 2, 4); 
$n = sizeof($hval); 
echo "Maximum loot possible : ", 
          maxLoot($hval, $n); 
      
?> 

Javascript

<script> 
  
    // Javascript program to find the 
    // maximum stolen value 
      
    // Function to calculate the 
    // maximum stolen value 
    function maxLoot(hval, n) 
    { 
        if (n == 0) 
            return 0; 
   
        let value1 = hval[0]; 
        if (n == 1) 
            return value1; 
   
        let value2 = Math.max(hval[0], hval[1]); 
        if (n == 2) 
            return value2; 
       
        // contains maximum stolen value at the end 
        let max_val = 0; 
   
        // Fill remaining positions 
        for (let i = 2; i < n; i++) 
        { 
            max_val = Math.max(hval[i] +  
                               value1, value2); 
            value1 = value2; 
            value2 = max_val; 
        } 
   
        return max_val; 
    } 
      
    let hval = [6, 7, 1, 3, 8, 2, 4]; 
    let n = hval.length; 
    document.write("Maximum loot possible : " 
    + maxLoot(hval, n)); 
      
</script>

输出

Maximum loot possible : 19

时间复杂度:O(N),只需遍历一次原数组。所以时间复杂度是O(N)。
辅助空间:O(1),不需要额外的空间,所以空间复杂度是恒定的。