leetcode经典动态规划解题报告

<h3 id="leetcode70-爬楼梯"><a href="#leetcode70-爬楼梯" class="headerlink" title="leetcode70 爬楼梯"></a>leetcode70 爬楼梯</h3><p>题目描述<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">假设你正在爬楼梯。需要 n 阶你才能到达楼顶。</span><br><span class="line"></span><br><span class="line">每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?</span><br></pre></td></tr></table></figure></p> <p>解答:<br>递推公式:</p> <p>设f(n)为n阶楼梯的爬法<br><code>f(n)=f(n-1)+f(n-2) n&gt;2</code><br><code>f(n)=1 n=1</code><br><code>f(n)=2 n=2</code><br>到达第n阶楼梯,有两种方法,一种是从第n-1阶楼梯,走一步到;另一种是从n-2阶楼梯,走两步到。</p> <p>根据以上的递归公式,我们很容易写出下面的代码:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">climbStairs</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line"> <span class="keyword">if</span> (n&lt;<span class="number">3</span>)&#123;</span><br><span class="line"> <span class="keyword">return</span> n;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">int</span>[] dp=<span class="keyword">new</span> <span class="keyword">int</span>[n+<span class="number">1</span>];</span><br><span class="line"> dp[<span class="number">1</span>]=<span class="number">1</span>;</span><br><span class="line"> dp[<span class="number">2</span>]=<span class="number">2</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">3</span>;i&lt;=n;i++)&#123;</span><br><span class="line"> dp[i]=dp[i-<span class="number">1</span>]+dp[i-<span class="number">2</span>];</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> dp[n];</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure></p>

2020/9/10
阅读更多

Netty启动原理

<h2 id="典型的Netty服务端启动代码:"><a href="#典型的Netty服务端启动代码:" class="headerlink" title="典型的Netty服务端启动代码:"></a>典型的Netty服务端启动代码:</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyServer</span> </span>&#123;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception</span>&#123;</span><br><span class="line"></span><br><span class="line"> EventLoopGroup bossGroup = <span class="keyword">new</span> NioEventLoopGroup(<span class="number">1</span>);</span><br><span class="line"> EventLoopGroup workerGroup = <span class="keyword">new</span> NioEventLoopGroup();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"></span><br><span class="line"> ServerBootstrap serverBootstrap = <span class="keyword">new</span> ServerBootstrap();</span><br><span class="line"> serverBootstrap.group(bossGroup,workerGroup)</span><br><span class="line"> .channel(NioServerSocketChannel.class)</span><br><span class="line"> .childHandler(<span class="keyword">new</span> ChannelInitializer&lt;SocketChannel&gt;() &#123;</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">initChannel</span><span class="params">(SocketChannel ch)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line"> ChannelPipeline pipeline = ch.pipeline();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//入站编码处理器</span></span><br><span class="line"> pipeline.addLast(<span class="keyword">new</span> MyByteToLongDecoder());</span><br><span class="line"> <span class="comment">//出站的handler进行编码</span></span><br><span class="line"> pipeline.addLast(<span class="keyword">new</span> MyLongToByteEncoder());</span><br><span class="line"> <span class="comment">//自定义的handler 处理业务逻辑</span></span><br><span class="line"> pipeline.addLast(<span class="keyword">new</span> MyServerHandler());</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> &#125;);</span><br><span class="line"></span><br><span class="line"> ChannelFuture channelFuture = serverBootstrap.bind(<span class="number">7000</span>).sync();</span><br><span class="line"> channelFuture.channel().closeFuture().sync();</span><br><span class="line"></span><br><span class="line"> &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line"> bossGroup.shutdownGracefully();</span><br><span class="line"> workerGroup.shutdownGracefully();</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

2020/5/28
阅读更多

web安全基础知识一

<h2 id="常见网站应用攻击方式"><a href="#常见网站应用攻击方式" class="headerlink" title="常见网站应用攻击方式"></a>常见网站应用攻击方式</h2><h3 id="XSS攻击"><a href="#XSS攻击" class="headerlink" title="XSS攻击"></a>XSS攻击</h3><p>XSS攻击即跨站点脚本攻击(cross site script),指黑客通过篡改网页,注入恶意HTML脚本,在用户浏览网页时,控制用户浏览器进行恶意操作的一种攻击方式。<br>常见的XSS攻击的类型有两种:</p> <ul> <li>反射型:攻击者诱使用户点击一个嵌入恶意脚本的连接,达到攻击的目的。</li> <li>持久型:黑客提交包含恶意脚本的请求,保存在被攻击的web站点的数据库中,用户浏览网页时,恶意脚本就被包含在正常页面中,达到攻击的目的。</li> </ul>

2020/5/22
阅读更多

SpringBoot自动配置原理

<h2><span id="简介">简介</span></h2><p>SpringBoot相较于Spring的一大进步就是它简化了配置。SpringBoot遵循”约定优于配置”的原则,使用注解对一些常规的配置项做默认配置,减少或不使用xml配置。Springboot还提供了大量的

2020/5/21
阅读更多

跟踪SpringMVC请求过程

<h2 id="整体流程"><a href="#整体流程" class="headerlink" title="整体流程"></a>整体流程</h2><ol> <li>所有的请求都被拦截到<code>DispatcherServlet</code>,它也是一个<code>Servlet</code>,执行<code>doService</code></li> <li>快照请求中的所有的参数,将框架中的一些对象设置到<code>request</code>对象中。</li> <li>调用<code>doDispatch(request,response)</code>方法</li> <li>调用<code>getHandler</code>方法获取对应的<code>Handler</code></li> <li>调用<code>getHandlerAdapter</code>拿到对应的<code>HandlerAdapter</code></li> <li>应用拦截器的<code>PreHandler</code>,如果拦截器的<code>PreHandeler</code>返回false,则直接返回</li> <li>调用<code>HandlerAdapter</code>对象的<code>handler</code>得到<code>ModelAndView</code>对象</li> <li>应用拦截器的<code>postHandle</code>方法</li> <li>调用<code>processDispatchResult</code>对结果进行处理,其内部调用了拦截器的<code>afterCompletion</code>方法</li> </ol>

2020/5/20
阅读更多

Netty之ChannelHandler

<h2 id="Channel的生命周期"><a href="#Channel的生命周期" class="headerlink" title="Channel的生命周期"></a>Channel的生命周期</h2><p><code>Channel</code>包含4个状态:</p> <table> <thead> <tr> <th>ChannelUnregistered</th> <th>Channel已经被创建,但还未注册到EventLoop</th> </tr> </thead> <tbody> <tr> <td>ChannelRegistered</td> <td>Channel已经被注册到EventLoop</td> </tr> <tr> <td>ChannelActive</td> <td>Channel处于活动状态,它现在可以接受和发送数据了</td> </tr> <tr> <td>ChannelInactive</td> <td>Channel没有连接到远程节点</td> </tr> </tbody> </table>

2020/5/17
阅读更多

负载均衡的实现方式与算法

<h2 id="负载均衡的实现方式"><a href="#负载均衡的实现方式" class="headerlink" title="负载均衡的实现方式"></a>负载均衡的实现方式</h2><h3 id="HTTP重定向负载均衡"><a href="#HTTP重定向负载均衡" class="headerlink" title="HTTP重定向负载均衡"></a>HTTP重定向负载均衡</h3><p><img src="https://s1.ax1x.com/2020/05/18/YflQIK.png" alt="YflQIK.png"></p> <p>HTTP重定向负载均衡需要一台重定向服务器。它的功能就是根据用户的HTTP请求根据负载均衡算法选择一个真实的服务器地址,并将服务器地址信息写入到重定向响应中返回给用户浏览器。用户浏览器再获取到响应之后,根据返回的信息,重新发送一个请求到真实的服务器上。</p>

2020/5/17
阅读更多

Netty之ByteBuf

<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p><code>ByteBuf</code>是Netty的数据容器,它解决了JDK API的局限性,能为网络应用程序的开发者提供更好的API支持。<br><code>ByteBuf</code>API的优点如下:</p> <ul> <li>它可以被用户自定义的缓冲区类型拓展</li> <li>通过内置的复合缓冲区类型实现了透明的零拷贝。</li> <li>容量可以按需增长</li> <li>在读和写这两种模式下切换不需要调用<code>BuyteBuffer</code>的<code>flip()</code>方法</li> <li>读和写使用了不同的索引</li> <li>方式支持链式调用</li> <li>支持引用计数</li> <li>支持池化</li> </ul>

2020/5/17
阅读更多

Netty线程模型

<h2 id="Reactor线程模型"><a href="#Reactor线程模型" class="headerlink" title="Reactor线程模型"></a>Reactor线程模型</h2><p>Netty的线程模型实际上就是Reactor模型的一种实现。</p> <p>Reactor模型是基于事件驱动开发的,核心组成部分是一个Reactor和一个线程池,其中Reactor负责监听和分配事件,线程池负责处理事件。根据Reactor的数量有线程池的数量,又可以将Reactor分为三种模型:</p> <ul> <li>单线程模型(单Reactor,单线程)</li> <li>多线程模型(单Reactor,多线程)</li> <li>主从多线程模型(多Reactor,多线程)</li> </ul>

2020/5/16
阅读更多

段页式内存管理

<h2 id="内存管理需要解决的问题"><a href="#内存管理需要解决的问题" class="headerlink" title="内存管理需要解决的问题"></a>内存管理需要解决的问题</h2><p>内存管理无非就是解决三个问题:</p> <ul> <li>如何使进程的地址空间隔离</li> <li>如果提高内存的使用效率</li> <li>如何解决程序运行时的重定位问题</li> </ul> <p>现在的内存管理方案就是引入虚拟内存这一中间层。虚拟内存位于程序和物理内存之间,程序只能看见虚拟内存,不能直接访问物理内存。每个程序都有自己独立的虚拟地址空间,这样就做到了<strong>进程地址空间的隔离</strong>。</p> <p>引入了虚拟地址技术后,我们需要解决如何将虚拟地址映射到物理地址。这主要有分段和分页两种技术。</p>

2020/5/15
阅读更多

fork()与写时复制

<h3 id="没有写时复制时的问题"><a href="#没有写时复制时的问题" class="headerlink" title="没有写时复制时的问题"></a>没有写时复制时的问题</h3><p>最初在Unit系统中,在使用<code>fork()</code>系统调用创建子进程的时候,会复制父进程的整个地址空间并把复制的那一份分配给子进程。这种情况比较耗时。因为它需要:</p> <ul> <li>为子进程的页表分配空间</li> <li>为子进程的页分配页面</li> <li>初始子进程的页表</li> <li>把父进程的页复制到子进程相应的页中。</li> </ul> <p>创建一个地址空间的这种方法涉及许多内存访问,消耗许多CPU周期,并且完全破环了高速缓存中的内容。在大多数情况下,这种做法常常时毫无意义的,因为许多子进程通过装入一个新的程序开始它们的执行,这样就完全丢弃了所继承的地址空间。</p>

2020/5/15
阅读更多

Linux内核设计与实现读书笔记一

<h2 id="进程管理"><a href="#进程管理" class="headerlink" title="进程管理"></a>进程管理</h2><h3 id="进程"><a href="#进程" class="headerlink" title="进程"></a>进程</h3><h4 id="相关概念"><a href="#相关概念" class="headerlink" title="相关概念"></a>相关概念</h4><p>进程就是处于执行期的程序。进程是处于执行期的程序以及相关资源的总称。<br>线程是进程中的活动对象,每个线程都拥有一个独立的程序计数器、进程栈和一组进程寄存器。<br>内核调度的对象是线程而不是进程。</p> <h4 id="进程描述符及任务结构"><a href="#进程描述符及任务结构" class="headerlink" title="进程描述符及任务结构"></a>进程描述符及任务结构</h4><p>内核吧进程的列表存放在叫做任务队列的双向循环列表中。链表中每一项的类型都是<code>task_struct</code>、被称为进程描述符。该结构包含了内核管理一个进程所需的所有信息。</p>

2020/5/14
阅读更多

Dubbo小知识点总结

<h2><span id="dubbo的几种集群容错方案">Dubbo的几种集群容错方案</span></h2><table> <thead> <tr> <th>集群容错方案</th> <th>解释</th> </tr> </thead> <tbody> <tr> <td>Fai

2020/5/12
阅读更多

MyBatis的使用回顾

<h2 id="Mapper文件的编写"><a href="#Mapper文件的编写" class="headerlink" title="Mapper文件的编写"></a>Mapper文件的编写</h2><h3 id="select"><a href="#select" class="headerlink" title="select"></a>select</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span> = <span class="string">“</span> <span class="attr">selectPerson</span>” <span class="attr">parameterType</span> = <span class="string">“</span> <span class="attr">int</span>” <span class="attr">resultType</span> = <span class="string">“</span> <span class="attr">hashmap</span>” &gt;</span> </span><br><span class="line"> SELECT * FROM PERSON WHERE ID =#&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/ <span class="attr">select</span>&gt;</span></span><br></pre></td></tr></table></figure> <p>这里有两点需要注意的,一是区分<code>#</code>和<code>$</code>的区别.<code>#</code>的底层是基于预编译语句来实现了,这样可以避免SQL注入的风险。而<code>$</code>在底层是通过字符串的直接拼接来实现了,因此有SQL注入的风险。</p>

2020/5/12
阅读更多

Dubbo集群容错

<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>Dubbo集群容错方面的源码包括四个部分,分别式服务目录Directory、服务路由Router、集群Cluster和负载均衡LoadBalance。</p> <p>它们之间的关系是这样的:</p> <p><img src="https://s1.ax1x.com/2020/05/11/YJAi1H.png" alt="YJAi1H.png"></p>

2020/5/11
阅读更多

Dubbo服务调用过程

<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>Dubbo服务调用的基本过程如图:</p> <p><img src="https://s1.ax1x.com/2020/05/10/Y33nc8.png" alt="Y33nc8.png"></p> <p>首先服务消费者通过代理对象Proxy发起远程调用,接着通过网络客户端将编码后的请求发送给服务提供方的网络层上。Server收到请求之后,首先要做的就是对数据包进行解码。然后将解码后的请求发送至分发器,再由分发器将请求发送到指定的线程池上,最后由线程池调用具体的服务。这就是一个远程调用请求的发送过程。</p>

2020/5/10
阅读更多

InnoDB的锁

<h2 id="什么是锁?"><a href="#什么是锁?" class="headerlink" title="什么是锁?"></a>什么是锁?</h2><p>锁是数据库系统区别于文件系统的一个关键特性,锁机制用于管理对共享资源的并发访问。</p> <h2 id="lock和latch"><a href="#lock和latch" class="headerlink" title="lock和latch"></a>lock和latch</h2><p>latch一般称为闩锁,因为其要求锁定的时间必须非常短,则应用的性能会非常的差。在InnoDB存储引擎中,latch由可以分为matuex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检查机制。</p> <p>lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或rollback后进行释放。此外lock是有死锁检查机制的。</p>

2020/5/4
阅读更多

SpringBoot启动原理

<h2 id="SpringBoot启动"><a href="#SpringBoot启动" class="headerlink" title="SpringBoot启动"></a>SpringBoot启动</h2><p>SpringBoot因为内置了tomcat或jetty服务器,不需要直接部署War文件,所以SpringBoot的程序起点是一个普通的主函数。主函数如下:</p> <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SpringbootStudyApplication</span> </span>&#123;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line"> SpringApplication.run(SpringbootStudyApplication.class, args);</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure> <p>整个SpringBoot的启动过程其实都是通过<code>@SpringBootApplication</code>注解和<code>SpringApplication.run</code>方法来实现的。</p> <p>整个启动的过程可以概括为:</p> <ol> <li>读取所有依赖的<code>META-INF/spring.factories</code>文件,该文件指明了哪些依赖可以被自动加载。</li> <li>根据<code>importSelector</code>类选择加载哪些依赖,使用<code>conditionOn</code>系列注解排除掉不需要的配置文件</li> <li>将剩余的配置文件所代表的bean加载到IOC容器中。</li> </ol>

2020/5/3
阅读更多

Maven和Git命令的一些总结

<h2 id="Maven命令"><a href="#Maven命令" class="headerlink" title="Maven命令"></a>Maven命令</h2><ol> <li><p>创建Maven的普通Java项目</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mvn archetype:create</span><br><span class="line"> -DgroupId=packageName</span><br><span class="line"> - DartifactId=projectName</span><br></pre></td></tr></table></figure> </li> <li><p>创建Maven的Web项目:</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mvn archetype:create</span><br><span class="line"> -DgroupId=packageName</span><br><span class="line"> -DartifactId=webappName</span><br><span class="line"> -DarchetypeArtifactId=maven-archetype-webapp</span><br></pre></td></tr></table></figure> </li> <li><p>编译源代码</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvc compile</span><br></pre></td></tr></table></figure>

2020/5/2
阅读更多

高可用Redis:Redis Cluster

<p>Redis Cluster是Redis官方提供的Redis集群功能。</p> <h2 id="为什么现需要Redis-Cluster"><a href="#为什么现需要Redis-Cluster" class="headerlink" title="为什么现需要Redis Cluster"></a>为什么现需要Redis Cluster</h2><ol> <li>主从复制不能满足高可用的要求</li> <li>随着业务的发展,需要更高的QPS</li> <li>数据量的增长导致服务器内存不足以存储</li> <li>网络流量的增长,业务的流量已经超过了服务器的网卡的上限值,可以考虑使用分布式技术来进行分流。</li> <li>离线计算,需要中间环节缓冲等别的需求。</li> </ol> <h2 id="数据分布"><a href="#数据分布" class="headerlink" title="数据分布"></a>数据分布</h2><p>当单机的redis节点无法满足要求,按照分区规则把数据分到若干个子集中。<br>

2020/5/1
阅读更多