zoukankan      html  css  js  c++  java
  • [leetcode] 213. House Robber II

    You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

    Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

    Example 1:

    Input: [2,3,2]
    Output: 3
    Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2),
                 because they are adjacent houses.
    

    Example 2:

    Input: [1,2,3,1]
    Output: 4
    Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
                 Total amount you can rob = 1 + 3 = 4.


    这题跟“ House Robber I”类似,只是房子练成了一个圈,即第一间房和最后一间房是相邻的,不能同时偷。因此,现在第一间和最后一间就只能二选一,或者两者都不选。
    所以可以将其分别删掉第一间房和最后一间房,然后通过“House Robber I”分别算出两种情况的最大值,之后选择两值中大值即可。
    此时需要思考的是,去掉第一个元素和最后一个元素,再分别用"House Robber I"求出分别的最大值得到的答案,是否能涵盖所有的答案。
    分析如下:
      最优答案必然是X----------√ 
             √----------X
             X----------X
      之中的一种,而不选第一个的最大值的答案为X----------√或X----------X中的最大值
             不选最后一个个的最大值的答案为√----------X或X----------X的最大值
      因此是涵盖了所有的答案。
    public class Solution {
    	public int rob(int[] nums) {
    		if (nums == null || nums.length == 0) {
    			return 0;
    		}
    		if (nums.length == 1) {
    			return nums[0];
    		}
    		int[] removeFirst = new int[nums.length - 1];
    		int[] removeLast = new int[nums.length - 1];
    		for (int i = 1; i < nums.length; i++) {
    			removeFirst[i - 1] = nums[i];
    		}
    		for (int i = 0; i < nums.length - 1; i++) {
    			removeLast[i] = nums[i];
    		}
    		return Math.max(rob1(removeFirst), rob1(removeLast));
    	}
    	/**
    	 * HouseRobberI
    	 * @param nums
    	 * @return
    	 */
    	public int rob1(int[] nums) {
    		// 共有n家
    		int n = nums.length;
    		if (n == 0) {
    			return 0;
    		}
    		// res[i]表示到第i家止,可以劫到最多的钱
    		int[] res = new int[n + 1];
    		res[0] = 0;
    		res[1] = nums[0];
    
    		for (int i = 2; i < n + 1; i++) {
    			// 劫到第i家能劫得最多的钱,
    			// 1.劫第i家,则说明没劫第i-1家,则此时最多为劫到第i-2家的最多前+第i家的前 = res[i-2] + nums[i-1]
    			// 2.不劫第i家,则劫得最多的钱为劫到第i-1家得到的最多前 res[i-1]
    			res[i] = Math.max(res[i - 2] + nums[i - 1], res[i - 1]);
    		}
    
    		return res[n];
    	}
    }
    

      



  • 相关阅读:
    新式类、经典类与多继承
    实现抽象类之方式二
    实现抽象类之方式一
    re模块
    28个高频Linux命令
    Git使用教程
    编程语言介绍
    编码
    进制
    操作系统简史
  • 原文地址:https://www.cnblogs.com/zebinlin/p/9803958.html
Copyright © 2011-2022 走看看