[Likou Brush Questions | Sixteenth Question]

Table of contents

Foreword:

198. Robbery - LeetCode

213. House Robbery II - LeetCode

 Summarize:


Foreword:

We continue to brush up on dynamic programming questions today, and I hope everyone can stick with me.

198. Robbery - LeetCode

You are a professional thief planning to steal houses along the street. There is a certain amount of cash hidden in each room. The only restrictive factor that affects your theft is that the adjacent houses are equipped with interconnected anti-theft systems. If two adjacent houses are broken into by thieves on the same night, the system will automatically call the police.

Given an array of non-negative integers representing the amount stored in each house, calculate the maximum amount you can steal in one night without triggering the alarm.

 Problem-solving ideas: We need to quickly determine the problem-solving direction of this problem. After reading the problem, we found that whether the current room is stolen or not depends on whether the previous room has been stolen. Therefore, we can determine that there is such a recursive relationship between rooms, so we determined the idea of ​​​​dynamic programming. Since it is dynamic programming, we strictly follow the five steps of dynamic programming:

1. Determine the meaning of the dp array and the meaning of the subscript : dp[i] represents the sum of the largest gold coins he can steal in this room.

2. Recursive formula: Let's use the picture as an example, assuming that we want to judge the maximum number of gold coins when we reach the last room

In fact, we discuss the two states in categories:

1. Steal the last room:

 Since room 5 is decided to steal, room 4 must not be stolen , then the maximum gold coin dp[5] that can be obtained at this time is actually equal to nums[5]+dp[3]. We need to understand the meaning of the dp array correctly before we can understand this formula.

The subscripts here are just for easy understanding. In fact, when we build, the dp array starts from 0, that is to say, dp[0] is the maximum number of gold coins that can be stolen in the first room.

2. Don't steal the last room:

Since room 5 is not stolen, then the largest gold coin dp[5]=dp[4]  that can be obtained at this time , our question returns to discussing dp[4], that is, discussing whether to steal or not to steal room 4 again.

After this explanation, I believe that everyone’s recursive thinking on the problem of house robbery has become clear: every time we compare the number of gold coins obtained by stealing and not stealing this room, we choose the larger one as the element of the dp array, and continue to recurse in this way, and finally return the element of the dp array corresponding to the last room.

公式为: dp[i]=max(nums[i]+dp[i-2],dp[i-1]);

 3. Initialization of dp array: According to the recursive formula, we can know that we only need to initialize the values ​​of dp[0] and dp[1]. In fact, the initialization of the two is easy to understand:
        dp[0]: contains the maximum number of gold coins in the first room from the beginning, so there is currently only one room, and if you want to get the maximum number of gold coins, you must steal this room, that is dp[0]=nums[0].

        dp[1]: The maximum number of gold coins from the beginning to the second room, because we cannot steal two adjacent rooms, so if we want to get the maximum number of gold coins, we can only steal 1 or 2, and choose the largest steal. Then it is dp[1]=max(dp[0],dp[1]).

4. Traversal order: According to the formula, it can be deduced from front to back, and the traversal order is naturally from front to back.

After our detailed analysis, the framework of the code has actually been built, and all we have to do is to complete the framework.

class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.size()==1)
        {
            return nums[0];
        }
        else if(nums.size()==2)
        {
            return max(nums[0],nums[1]);
        }
       vector<int>dp(nums.size());
       dp[0]=nums[0];
       dp[1]=max(nums[0],nums[1]);
       for(int i=2;i<nums.size();i++)
       {
           dp[i]=max(nums[i]+dp[i-2],dp[i-1]);
       }       
       return dp[nums.size()-1];
    }
};

213. House Robbery II - LeetCode

You are a professional thief planning to rob houses along the street, each of which has a certain amount of cash hidden in it. All the houses in this place are arranged in a circle, which means that the first house and the last house are right next to each other. At the same time, adjacent houses are equipped with interconnected anti-theft systems. If two adjacent houses are broken into by thieves at the same night, the system will automatically call the police.

Given an array of non-negative integers representing the amount of money stored in each house, calculate the maximum amount you can steal tonight without setting off the alarm.

 In fact, this question is to change the structure of the room, so that the end to end is connected, and the room structure is changed from linear to circular.

In fact, it is a category discussion:

Because the first and last elements are connected at this time, we only have two possibilities when choosing:

1. Must not steal the tail.

2. Must not steal the head.

 

After clarifying the logic, the code is very clear:

class Solution {
public:
    int rob(vector<int>& nums) {

        if (nums.size() == 0) 
        {
            return 0;
        }
        if (nums.size() == 1)
        { 
            return nums[0];
        }
        int result1 = getmax(nums, 0, nums.size() - 2); //不对首进行考虑
        int result2 = getmax(nums, 1, nums.size() - 1); //不对尾进行考虑
        return max(result1, result2);
    }
    
    int getmax(vector<int>& nums, int start, int end) {
        if (end == start) return nums[start];
        vector<int> dp(nums.size());
        dp[start] = nums[start];
        dp[start + 1] = max(nums[start], nums[start + 1]);
        for (int i = start + 2; i <= end; i++) {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        return dp[end];
    }
};    

Let's explain the changes: the purpose of this function is to calculate the maximum sum obtained by adding numbers selected in the range [start, end], where each number can only be selected once. The implementation process of the function is as follows:

1. If the start position and the end position are equal, then directly return the number whose subscript is start in the array as the maximum sum.
2. First, we define a dp array with the same size as the original array, and dp[i] represents the maximum sum obtained by selecting numbers in the range [0,i].
3. Then, we initialize dp[0] to be nums[0] and dp[1] to be max(nums[0], nums[1]), since choosing the largest of the numbers in the first and second positions ensures that we get the maximum sum.
4. Next, we start from the third position (ie start+2) and loop through the entire array. At each position i, we have two choices:

  • Select the number at the current position i, then the maximum sum is dp[i-2]+nums[i];
  • The number at the current position i is not selected, and the maximum sum is dp[i-1].

5. Take the max of the results of the two choices and update dp[i].
6. Finally, return dp[end] as the maximum sum obtained by adding the selected numbers in the range [start,end].

It should be noted that the time complexity of this algorithm is O(N), where N is the length of the array.

 Summarize:

        The algorithm idea provided to us in the type of house robbery is really exciting, and it is indeed a classic example of dynamic programming.

If my content is helpful to you, please like, comment and bookmark . Creation is not easy, everyone's support is my motivation to persevere!

 


 

Guess you like

Origin blog.csdn.net/fckbb/article/details/131408214