求一个非负整数数组中不相邻元素之和的最大值

该题来自leetcode,原题如下:

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that 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.

这是一道DP问题,首先该题符合“最优子结构”,该题的递推公式:dp(n) = max(dp(n-1), dp(n-2) + nums[n]),另外根据“重叠子问题”原则,如果仅仅使用简单的递归求解,则会有严重的重复计算,时间复杂度成指数增长,所以要额外开销一个数组来存储已经计算出来的dp(i)值。

方法一、递归法

    public int dpRob(int[] nums, int n, int[] array) {
        if (n < 0)
            return 0;if(array[n] == -1)
            array[n] = Math.max(dpRob(nums, n-1, array), dpRob(nums, n-2, array) + nums[n]);
        return array[n];
    }
    public int rob(int[] nums) {
        int[] array = new int[nums.length];
        Arrays.fill(array, -1); //此处数组元素要初始化为负数
        return dpRob(nums, nums.length-1, array);
    }

方法二:迭代法

    public int rob(int[] nums) {
        if(nums.length == 0) return 0;
        if(nums.length == 1) return nums[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-2] + nums[i], dp[i-1]);
        }
        return dp[nums.length-1];
    }        

进阶:

若这些房子成环形排列,即第一个房子和最后一个房子相邻,求此时和的最大值。

分析:可以把原数组nums分成两个子数组,转化为线性排列求解,一个数组nums1下标是从0到n-2,另一个数组nums2下标是从1到n-1,两个子数组求解结果中较大的结果为该题的解。

Java递归代码如下:

    int dpRob(int[] nums, int n, int[] array) {
        if (n < 0)
            return 0;
        if(array[n] == -1)
            array[n] = Math.max(dpRob(nums, n-1, array), dpRob(nums, n-2, array) + nums[n]);
        return array[n];
    }
    public int rob(int[] nums) {
        if (nums.length == 0)
            return 0;
        if (nums.length == 1)
            return nums[0];
        int[] nums1 = new int[nums.length-1];
        int[] nums2 = new int[nums.length-1];
        System.arraycopy(nums, 0, nums1, 0, nums.length-1);
        System.arraycopy(nums, 1, nums2, 0, nums.length-1);
        int[] array = new int[nums.length];
        Arrays.fill(array, -1);
        int result1 = dpRob(nums1, nums1.length-1, array);
        Arrays.fill(array, -1);
        int result2 = dpRob(nums2, nums2.length-1, array);
        return Math.max(result1, result2);
    }
时间: 2024-10-23 16:35:45

求一个非负整数数组中不相邻元素之和的最大值的相关文章

求数组中两个元素差的最大值

找到最大值找到最小值,然后相减即可. 1.如果是说,前面的减去后面的,差的最大值? 2.如果是说,后面的减去前面的,差的最大值? 这两个问题就不一样了. 基础的想法可以用暴力.但是有更好的方法. 针对1,从后往前遍历数组,记录遍历过的数组元素的最小值,用当前元素相减. 针对2,从前往后遍历数组,记录遍历过的数组元素的最小值,用当前元素相减.

求一个整数数组中最大子数组的和。

遍历一遍,找连续的正数求和,同时比较求和的大小,最后输出最大的和就可以. 源代码: #include <iostream>#include<time.h>using namespace std;int maxSum(int*a,int n){ int sum=0; int b=0; for(int i=0;i<n;i++) {  if(b<0)   b=a[i];  else   b+=a[i];  if(sum<b)   sum=b; } return sum;

【算法】求两个数组中相同的元素及其个数(C语言、Java实现)

简介: 方法1:(时间复杂度O(n^2)) public void getNum(String arr1, String arr2) { for (int i = 0; i < arr1.length; i++) { for () { } } }

php中计算二维数组中某一元素之和

[0] => array(5) { ["id"] => string(2) "11" ["name"] => string(5) "1.jpg" ["suffix"] => string(3) "jpg" ["url"] => string(29) "./Uploads/1/5292f55d208e8.jpg" [&q

《软件工程》课堂练习:返回一个整数数组中最大子数组的和

求一个整数数组中最大子数数组的和 实验步骤 从第一个元素开始,每两个相邻数字作为一个新数组,依次相加循环,当和赋值给最大即可求得 #include<stdio.h> int main(){ int a[10]; int b[5]; int i,j,t; printf("请输入10个数(相邻两个数字为一个新数组):\n"); for(i=0;i<10;i++) scanf("%d",&a[i]); getchar(); b[0]=a[0]+a

微软算法100题69 求旋转数组中的最小元素

69.求旋转数组中的最小元素.题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个排好序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1 思路: 1. 可以从左到右扫描整个数组,找出最小的那个,时间复杂度是o(n) 2. 也可以利用旋转数组本身的特性,即部分有序,然后借助二分查找的方法来解决,先找中间点mid = left + (right - left)/2, 如果a[le

题目:返回一个整数数组中最大子数组的和。(要求程序必须能处理1000 个元素)

1.题目:返回一个整数数组中最大子数组的和. 2.要求: 要求程序必须能处理1000 个元素: 每个元素是int32 类型的: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 3.设计思路: 将数组大小定义为1000,对于每个元素定义为int32类型,我们取数的时候对其进行了乘4294967296,使数组内的元素可以越界. 4.程序代码: 1 #include <iostream>

C语言 有一个整形数组a,有10个元素,要求输出数组中的全部元素

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">有一个整形数组a,有10个元素,要求输出数组中的全部元素</span> 解题思路:引用数组中各元素的值有3种方法:1.下标法,如a[3];2.通过数组名计算数组元素的地址,找出元素的值 3.用指针变量指向数组元素. //用指针变量指向数组元素 #include <std

输入6个人的成绩放入到一个一维数组中,然后打印出平均分,最后按成绩 从大到小打印。三个功能(输入是一个函数,求平均分是一个函数,排序是一个 函数)都用函数实现,最后在main方法中调用。

/*5.输入6个人的成绩放入到一个一维数组中,然后打印出平均分,最后按成绩从大到小打印.三个功能(输入是一个函数,求平均分是一个函数,排序是一个函数)都用函数实现,最后在main方法中调用.*/ #include <stdio.h> int inputScore(){ int score; scanf("%d",&score); return score;} double avg(int scores[],int length){ int i,score = 0;