返回

高手窃金无须碰:高超Go&Java算法之打家劫舍

后端

Go语言实现

func rob(nums []int) int {
	if len(nums) == 0 {
		return 0
	}
	dp := make([]int, len(nums))
	dp[0] = nums[0]
	dp[1] = max(nums[0], nums[1])
	for i := 2; i < len(nums); i++ {
		dp[i] = max(dp[i-1], dp[i-2]+nums[i])
	}
	return dp[len(nums)-1]
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

Java语言实现

public class HouseRobber {
    public int rob(int[] nums) {
        if (nums.length == 0) {
            return 0;
        }
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        for (int i = 2; i < nums.length; i++) {
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
        }
        return dp[nums.length - 1];
    }

    public static void main(String[] args) {
        HouseRobber hr = new HouseRobber();
        int[] nums = {1, 2, 3, 1};
        System.out.println(hr.rob(nums)); // 4
    }
}

算法原理

打家劫舍算法的核心思想是动态规划。动态规划是一种用于解决最优子结构和无后效性问题的算法。在打家劫舍问题中,子结构是指一个子问题的最优解,而无后效性是指子问题的最优解不依赖于其后面的子问题的解。

在打家劫舍问题中,我们可以定义一个状态dp[i],表示抢劫到第i间房子时,偷到的最大金额。我们可以利用以下递推关系来计算dp[i]:

  • dp[0] = nums[0]
  • dp[1] = max(nums[0], nums[1])
  • dp[i] = max(dp[i-1], dp[i-2] + nums[i])

复杂度分析

打家劫舍算法的时间复杂度为O(n),其中n是房子的数量。空间复杂度为O(n),因为我们需要存储每个子问题的最优解。

总结

打家劫舍算法是一个经典的动态规划问题。它可以用来解决许多其他问题,例如最大子数组和、最长公共子序列等。希望本文对您理解打家劫舍算法有所帮助。