代码随想录Day_48打卡

这篇具有很好参考价值的文章主要介绍了代码随想录Day_48打卡。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

①、打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

事例:

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。

思路:

        使用动态规划,对于每个房间,只有两种选择,偷还是不偷,若选择偷的话,则只能加上前两个房间偷取的最大金额,即上一个房间不偷,若不偷,则为从第一个房间到前一个房间偷取的最大金额,两者取最大值即可。

动态规划:

        dp定义及含义:dp[j]表示从第一个房间到第j个房间能偷取的最大金额

        状态转移方程:dp[j] = Math.max(dp[j - 1],dp[j - 2] + nums[j])

        初始化:dp[0] = nums[0] 只能投第一个房间 dp[1] = Math.max(nums[0],num[1]),前两个房间就选个钱多的。

        遍历顺序:房间从小到大遍历

        dp[nums.length - 1]即为答案。

代码:

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

②、打家劫舍Ⅱ

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

事例:

输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。

思路:

        与上一题类似,只是首尾多了个环形判断,需要进行解环操作。可以将环截成两个链,如对第一家到最后第二家进行打劫,然后再从头开始,对第二家到最后一家进行打劫,最后返回两个打劫的最大值即可。打劫代码跟上题一致。

代码:

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

③、打家劫舍Ⅲ

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。

除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。

事例:代码随想录Day_48打卡,算法

输入: root = [3,2,3,null,3,null,1]
输出: 7 
解释: 小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7

思路:

        这道题的社区结构变成了树形,对于树,我们得选择一种遍历方式,打劫该结点与否取决于左右孩子是否打劫的金额最大值,故可以采用递归,返回值为处理左右孩子的数据,以便后续判断,故选择后序遍历。

递归:

        使用后序遍历

        返回值:int[],约定int[0]为该不打劫该节点,int[1]为打劫该结点,返回参数可以直接给根结点构造成新参数,层层返回到最终结果。

        最后返回root[0],root[1]中的最大值即为答案。

动态规划:

        dp定义及含义:dp其实就是递归函数的返回值,其中dp[0]表示不打劫当前结点的最大金额,dp[1]表示打劫当前结点的最大金额。

        状态转移方程:构造dp数组,dp[0] = Math.max(leftDp[0],left[1]) + Math.max(rightDp[0],rightDp[1]),dp[1] = root.val + leftDp[0] + rightDp[1]

        初始化:遇到空节点时,返回new int[]{0,0}

        遍历顺序:后序遍历,因为根节点是否打劫需要根据左右孩子是否打劫

        最终返回的值为:根节点是否打劫的最大金额,返回其中的最大值即可。

代码:

public int rob(TreeNode root) {
        int[] resDp = dpRoot(root);
        int res = Math.max(resDp[0],resDp[1]);
        return res;
    }

    public int[] dpRoot(TreeNode root){
        if(root == null) return new int[]{0,0};
        int[] leftDp = dpRoot(root.left);
        int[] rightDp = dpRoot(root.right);
        int value1 = root.val + leftDp[0] + rightDp[0];
        int value0 = Math.max(leftDp[0],leftDp[1]) + Math.max(rightDp[0],rightDp[1]);
        return new int[]{value0,value1};
    }

参考:代码随想录 (programmercarl.com)文章来源地址https://www.toymoban.com/news/detail-677722.html

到了这里,关于代码随想录Day_48打卡的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 代码随想录day24 开启回溯算法

    感觉回溯算法其实和递归很像,也是用递归的做法,也有三部曲,但又不太一样的地方是递归中类似二叉树,只有纵向遍历(一层层往下遍历,没有横向遍历),而回溯算法中多的for循环就是横向遍历,说实话这一点我没有理解的太深,只是知道它类似于两个for循环中的第一

    2024年01月16日
    浏览(33)
  • 代码随想录算法训练DAY27|回溯3

    力扣题目链接 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的数字可以无限制重复被选取。 说明: 所有数字(包括 target)都是正整数。 解集不能包含重复的组合。 示例 1: 输入:candidates = [2,3,6,

    2024年01月23日
    浏览(30)
  • 代码随想录算法训练DAY25|回溯2

    力扣题目链接 找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。 说明: 所有数字都是正整数。 解集不能包含重复的组合。 示例 1: 输入: k = 3, n = 7 输出: [[1,2,4]] 示例 2: 输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]

    2024年01月22日
    浏览(45)
  • 代码随想录算法训练day4 | 链表

    目录 24. 两两交换链表节点 19. 删除链表倒数第n个节点 方法一:普通写法 方法二:双指针法 面试题:找链表相交节点 142. 判断环形链表 虚拟头节点的本质意义在于减少了特殊情况的处理。不用判断该节点是否在链表的第一位。 定义快慢两个指针。 fast先走n步,再让fast和s

    2024年02月04日
    浏览(38)
  • 代码随想录算法练习Day1:二分查找

    题目链接:704. 二分查找 卡哥视频讲解:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找 二分法概述: 二分法(Binary Search)是一种在有序数组或列表中查找目标元素的算法。 二分法使用前提 : 有序数组或列表 :二分法要求在查找的数据结

    2024年04月23日
    浏览(32)
  • 【代码随想录打卡】快慢指针

    力扣链接: 力扣 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

    2024年02月12日
    浏览(29)
  • 代码随想录Day20 回溯算法 LeetCode77 组合问题

    以下内容更详细解释来自于:代码随想录 (programmercarl.com) 回溯法也叫回溯搜索法,是搜索法的一种,我们之前在二叉树中也经常使用到回溯来解决问题,其实 有递归就有回溯 ,有的时候回溯隐藏在递归之下,我们不容易发觉,今天我们来详细介绍一下什么是回溯,它能解决哪些问题.

    2024年02月08日
    浏览(32)
  • 代码随想录打卡第35天

    2024年02月12日
    浏览(23)
  • 代码随想录打卡第34天

    2024年02月11日
    浏览(77)
  • 代码随想录补打卡 56 合并区间

    56 合并区间  代码如下 func merge(intervals [][]int) [][]int {         sort.Slice(intervals,func(i,j int)bool{  //将数组按左边界的大小排序         return intervals[i][0]intervals[j][0]     })     res := make([][]int,0) //定义一个目标数组     res = append(res,intervals[0])  //先将数组的第

    2024年02月02日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包