【剑指offer - C++/Java】10、矩形覆盖

在线题目链接:矩形覆盖

文章目录

  • 1 题目描述
  • 2 题目分析
  • 3 代码
    • 3.1 递归方法
      • 3.11 Java代码
      • 3.12 C++代码
    • 3.2 动态规划算法
    • 3.2 动态规划
      • 3.21 Java代码
      • 3.22 C++代码
    • 3.3 循环方法
      • 3.31 Java代码
      • 3.32 C++代码
  • 4、总结

1 题目描述

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

2 题目分析

乍一看感觉无从下手!!!其实如果我们使用归纳方法的话,总能够总结出规律来。

假设下面是一个2*n的大矩形:

在这里插入图片描述

我们要使用下面这样的2*1的小矩形来填满上述的大矩形:
在这里插入图片描述

我们假设将2*n的矩形填满需要f(n)种方法

那么填充的方法可以有下面的两种方法:

  1. 如下图:2*1的矩形竖着放,那么还剩下2*(n-1)大小的矩形需要填,也就是剩下的矩形还有f(n-1)的方法填满

在这里插入图片描述

  1. 如下图:2*1的矩形横着放,那么由于它下面的也只能横这放,所以还剩下2*(n-2)个矩形,也就是剩下的矩形需要有f(n-2)种方法填满。

在这里插入图片描述

很明显,到这里我们就可以列出一个公式:

  • f(n)=f(n-1)+f(n-2)

这个公式我们太熟悉了,这就是斐波那契数列,我们看下面三篇文章的算法题都是这个公式的应用:

  • 斐波那契数列
  • 跳台阶
  • 变态跳台阶

综上以及题目要求,我们得出综合公式(n=0时f(n)=0):
在这里插入图片描述

由此可以写出三种不同的代码:递归,动态规划,循环

3 代码

3.1 递归方法

递归方法很简单,直接利用公式即可。

3.11 Java代码

public class Solution {public int RectCover(int target) {//递归if(target<3)return target;return RectCover(target-1)+RectCover(target-2);}
}

3.12 C++代码

class Solution {
public:int rectCover(int number) {//递归if(number<3)return number;return rectCover(number-1)+rectCover(number-2);}
};

我们都知道这种递归解法会有很多重复的计算,就像下面的,假设我们要计算f(10):
在这里插入图片描述

计算f(10),要重复计算两次f(8),三次f(7),三次f(6),这种重复计算,对于数据比价大的时候,开销是非常大的。所以我们经常说,递归虽然好写,但是不建议在实现算法的时候使用递归算法。

3.2 动态规划算法

3.2 动态规划

凡是能用递归写出的代码,一定能够用动态规划写出来。

我们知道递归是为了求某一个值,而必须先知道另外的几个值后才能求出来。而想要求那另外的几个值,还需要再求另外的另外的值,就像上面的递归二叉树,想要先求f(10),必须知道f(9)和发(8)。想要知道f(9)又得知道f(8)和f(7)…

上面递归是想要计算总体值,需要求局部的值,想要求局部的值,又要求局部的局部的值。

动态规划不是这样,动态规划是先从递归的终止条件开始计算,也就是说,动态规划先计算局部的值,然后根据局部的值的累积,最终得到整体要求的值。也就是与递归反过来了。

比如针对上面的求f(10),我们先求f(1),f(2),f(3)…最终肯定会求得f(10)。这样我们就没有进行重复的计算。每一项都是只计算一次。

看代码就能明白上面说的是什么意思了。下面的ret数组,ret[i]代表斐波那契数组的第i项。我们要求得第n项,最后求到ret[n]直接返回即可。

3.21 Java代码

public class Solution {public int RectCover(int target) {//这同样是斐波那契数列 f(n)=f(n-1)+f(n-2)//动态规划if(target<=2)return target;int[] ret=new int[target+1];ret[1]=1;ret[2]=2;int i;for(i=3;i<=target;i++){ret[i]=ret[i-1]+ret[i-2];}return ret[target];}
}

3.22 C++代码

class Solution {
public:int rectCover(int number) {//这同样是斐波那契数列 f(n)=f(n-1)+f(n-2)//动态规划//if(number<=2)return number;int ret[number+1];ret[0]=0;ret[1]=1;ret[2]=2;int i;for(i=3;i<=number;i++){ret[i]=ret[i-1]+ret[i-2];}return ret[number];}
};

3.3 循环方法

所有的递归都可以写成动态规划,同理所有的动态规划,也一定能写成循环。只不过有的动态规划不好写成循环而已。本题是非常好写成循环的。

循环比动态规划好的原因在于,循环只用几个变量,循环使用它们得到最终结果,不保存之前的计算结果,动态规划却需要开辟一个数组,将所有计算过的结果保存,这很浪费空间。

3.31 Java代码

public class Solution {public int RectCover(int target) {//循环if(target<3)return target;int r1=1,r2=2,ret=0;int i;for(i=3;i<=target;i++){ret=r1+r2;r1=r2;r2=ret;}return ret;}
}

当然,上面使用三个变量,我们还可以再减少一个变量,使用两个变量:

public class Solution {public int RectCover(int target) {//循环,更加单的写法if(target<3)return target;int r1=1,r2=2;int i;for(i=3;i<=target;i++){r2+=r1;r1=r2-r1;}return r2;}
}

3.32 C++代码

三个变量

class Solution {
public:int rectCover(int number) {//循环if(number<3)return number;int r1=1,r2=2,ret=0;int i;for(i=3;i<=number;i++){ret=r1+r2;r1=r2;r2=ret;}return ret;}
};

两个变量

class Solution {
public:int rectCover(int number) {//循环,更加单的写法if(number<3)return number;int r1=1,r2=2;int i;for(i=3;i<=number;i++){r2+=r1;r1=r2-r1;}return r2;}
};

4、总结

注意学会递归,动态规划,循环三者时间的关系

探讨学习加:
个人qq:1126137994
个人微信:liu1126137994

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/422941.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【剑指offer - C++/Java】12、数值的整数次方

在线题目链接&#xff1a;数值的整数次方 文章目录1 题目描述2 题目分析2.1 方法1 循环2.11 Java代码2.12 C代码2.2 方法2 递归2.21 Java代码2.22 C代码3 总结1 题目描述 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 2 题目分析 2.1 方…

【剑指offer - C++/Java】14、链表中倒数第k的节点

在线题目链接&#xff1a;链表中倒数第k的节点 文章目录1 题目描述2 题目分析2.1 Java代码2.2 C代码3 总结1 题目描述 输入一个链表&#xff0c;输出该链表中倒数第k个结点。 2 题目分析 这道题比较简单。常规做法是先求出链表的总的节点个数n&#xff0c;然后再从头开始找第n-…

beta:scrum5

今天的工作 周一的工作 困难 王佳磊 收集数据&#xff0c;build了online的数据库, 38934 38939&#xff0c;收集更多数据&#xff0c;在新的API环境下&#xff0c;逐步发现并fix掉以前姓名到ID映射的bug. API的改动&#xff0c;ID的合并 肖巍&#xff0c;兰翠玲 等待测…

【软件开发底层知识修炼】十三 链接器-如何写出不依赖C库函数的代码

本文将综合以下4篇文章&#xff0c;学习如何写出不依赖libc库的程序&#xff1a; 【软件开发底层知识修炼】九 链接器-可重定位文件与可执行文件【软件开发底层知识修炼】十 链接器-main函数不是第一个被执行的函数【软件开发底层知识修炼】十一 链接器-链接脚本【软件开发底层…

前端学习(218):属性选择器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>属性选择器&…

【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用

前面几篇文章学习了链接器相关的内容。现在开始来学习GDB调试。我们的目的是通过这几篇文章将GDB调试完全学会。 文章目录1 为什么需要GDB2 GDB 的常规应用3 GDB调试程序实例4 总结1 为什么需要GDB 什么是GDB&#xff1f; GNU项目中的调试器&#xff08;gnu debuger&#xff0…

前端学习(219):css伪类选择器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS伪类<…

【软件开发底层知识修炼】十五 快速学习GDB调试二 使用GDB进行断点调试

上一篇文章我们学习了使用GDB的最基本方法&#xff1a;【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用 本篇文章将学习GDB的断点调试。断点调试是一种非常重要的调试方法。 文章目录1 断点类型2 GDB软件断点调试相关操作2.1 通过函数名设置断点2.2 通过文件名行号…

Informix IDS 11体系操持(918测验)认证指南,第 4 部门: 机能调优(1)

对 IBM Informix Dynamic Server (IDS) 和它的分比如子体系举行调优&#xff0c;以失掉最佳机能。在一个冗长的概述之后&#xff0c;本教程给出了一些关于怎样检查数据库做事器及其子体系的例子。本文是这个分 8 部门的 系列教程 的第 4 部门&#xff0c;这个教程可以帮手您筹办…

前端学习(220):伪元素选择器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS伪元素&l…

【软件开发底层知识修炼】十六 快速学习GDB调试三 使用GDB的数据断点监测变量是否改变

上一篇文章我们学习了如何使用GDB进行软件断点调试和硬件断点调试&#xff1a;【软件开发底层知识修炼】十五 快速学习GDB调试二 使用GDB进行断点调试本篇文章继续上一篇文章的学习&#xff0c;如何使用GDB的数据断点监测内存中的变量是否被改变 文章目录1 GDB的数据断点1.1 利…

AllTray-将办法最小化到琐细托盘

Toy Posted in AppsAllTray 是一个很有效的小办法&#xff0c;操纵它你可以将办法的窗口最小化到琐细托盘&#xff0c;从而腾出桌面空间以作它用。此办法主要为那些没有原生供给最小化到琐细托盘成效的办法而预备的。今朝&#xff0c;AllTray 可以在 GNOME、KDE、Xfce、Fluxbox…

【软件开发底层知识修炼】十七 快速学习GDB调试四 使用GDB进行函数调用栈的查看

上一篇文章学习了如何使用GDB数据断点进行内存监测&#xff1a;【软件开发底层知识修炼】十五 快速学习GDB调试三 使用GDB的数据断点监测变量是否改变本篇文章继续上一篇文章的学习&#xff1a;如何使用GDB进行函数调用栈的查看 文章目录1 backtrace和frame2 使用GDB进行函数调…

前端学习(221):字体属性

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS字体属性…

前端学习(222):文本属性

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS文本属性…

【软件开发底层知识修炼】十八 快速学习GDB调试五 使用GDB进行调试的一些小技巧

上一篇文章学习了如何使用GDB进行函数调用栈的查看&#xff1a;【软件开发底层知识修炼】十六 快速学习GDB调试四 使用GDB进行函数调用栈的查看本篇文章是GDB调试快速学习系列的最后一篇。将综合前几篇文章做一个小的总结以及介绍一些在调试中使用的小技巧 文章目录1 调试中的小…

MongoDB学习笔记(一) MongoDB介绍及安装

系列目录 MongoDB学习笔记(一) MongoDB介绍及安装MongoDB学习笔记(二) 通过samus驱动实现基本数据操作MongoDB学习笔记(三) 在MVC模式下通过Jqgrid表格操作MongoDB数据MongoDB学习笔记(四) 用MongoDB的文档结构描述数据关系MongoDB学习笔记(五) MongoDB文件存取操作MongoDB…

前端学习(224):iconfont矢量库

矢量库 一、如何下载iconfont图标。 在iconfont-阿里巴巴矢量图标库中有多种图标供你选择。比如我们选择其中的一个作为示例。 鼠标悬浮上后会出现三种选择&#xff1a; 1.添加入库&#xff1a;功能和淘宝中的购物…

如何转载别人的博客

前言 对于喜欢逛CSDN的人来说&#xff0c;看别人的博客确实能够对自己有不小的提高&#xff0c;有时候看到特别好的博客想转载下载&#xff0c;但是不能一个字一个字的敲了&#xff0c;这时候我们就想快速转载别人的博客&#xff0c;把别人的博客移到自己的空间里面&#xff0c…

【软件开发底层知识修炼】二十 深入理解可执行程序的结构

上一篇文章记录了GDB调试从入门到熟练掌握的学习全过程。点击链接查看&#xff1a;【软件开发底层知识修炼】十九 GDB调试从入门到熟练掌握超级详细实战教程学习目录 还记得在以前的学习Binutils工具的时候&#xff0c;学习了很多工具来查看可执行程序的结构&#xff0c;那个时…