<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Gallon&#39;s Note</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://yoursite.com/"/>
  <updated>2020-01-20T13:11:04.696Z</updated>
  <id>http://yoursite.com/</id>
  
  <author>
    <name>SKJin</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>raft算法</title>
    <link href="http://yoursite.com/2020/01/20/raft%E7%AE%97%E6%B3%95/"/>
    <id>http://yoursite.com/2020/01/20/raft算法/</id>
    <published>2020-01-20T12:22:51.000Z</published>
    <updated>2020-01-20T13:11:04.696Z</updated>
    
    <content type="html"><![CDATA[<h2 id="CAP理论"><a href="#CAP理论" class="headerlink" title="CAP理论"></a>CAP理论</h2><p>对于一个分布式系统，不可能同时满足以下三点：</p><ul><li><p>一致性(Consistence)：在<strong>同一时刻所有节点的数据都是一样</strong>的。</p><ul><li>最终一致性。所有结点的数据并不是立刻一样的，而是在将来的某一个时刻会满足一致性。</li><li>强一致性。</li></ul></li><li><p>可用性(Availability)：每次请求都能<strong>获取到非错的响应</strong>——但是不保证获取的数据为最新数据。</p></li><li><p>分区容错性(Partition Tolerance)：分布式系统在遇到任何网络分区故障的时候，仍然能够对外提供满足一致性和可用性的服务，除非整个网络环境都发生了故障.比如<strong>，某个服务器宕机了，集群仍能够对外提供服务</strong>。</p></li></ul><p>一个分布式系统不可能同时满足三个特性，最多只可以满足两个，而<strong>分区容错性又是我们必须要满足的</strong>，因此，一致性和可用性我们只能满足两个。这里的一致性是强一致性，即在同一时刻，所有节点的数据都是一致的。假如我们选择了可用性，放弃了强一致性，可以使用<strong>最终一致性</strong>来解决。</p><p>在满足了分区容错性P后，想要满足一致性C，一个服务的多个节点之间就必须进行数据复制达到数据一致之后再返回给调用者响应，然而在多个节点数据复制的过程中，可能节点之间会出现网络等问题使得数据复制阻塞或失败导致响应超时，服务调用失败，这就失去了系统的可用性A。</p><p>​       如果不强制满足强一致性，那在服务被调用的时候不用管数据复制的问题，直接返回响应，这就满足了可用性，但是由于此服务的多个节点数据可能没有完成复制，节点数据可能不一致，这就失去了系统的一致性。</p><p>著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。CA之间的取舍<strong>要根据实际业务来决定</strong>，比如银行转账业务，我们必须要保证他的一致性。比如电商业务，一致性就没那么重要了，可以尽可能保证他的高可用性。</p><h2 id="强一致性"><a href="#强一致性" class="headerlink" title="强一致性"></a>强一致性</h2><h3 id="主从同步"><a href="#主从同步" class="headerlink" title="主从同步"></a>主从同步</h3><p>主从同步复制。<br>1.Master接受写请求。<br>2.Master复制日志到slave<br>3.Master等待，直到所有slve返回成功的消息。<br>缺点：<strong>一个slave失败，会导致Mater阻塞，从而导致整个集群阻塞，可用性低</strong>。</p><h3 id="多数派"><a href="#多数派" class="headerlink" title="多数派"></a>多数派</h3><p>有N/2个slave返回写入成功即成功。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;CAP理论&quot;&gt;&lt;a href=&quot;#CAP理论&quot; class=&quot;headerlink&quot; title=&quot;CAP理论&quot;&gt;&lt;/a&gt;CAP理论&lt;/h2&gt;&lt;p&gt;对于一个分布式系统，不可能同时满足以下三点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;一致性(Consistence)：在&lt;
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>RocketMQ入门</title>
    <link href="http://yoursite.com/2020/01/19/RocketMQ%E5%85%A5%E9%97%A8/"/>
    <id>http://yoursite.com/2020/01/19/RocketMQ入门/</id>
    <published>2020-01-19T07:06:41.000Z</published>
    <updated>2020-01-20T12:17:09.101Z</updated>
    
    <content type="html"><![CDATA[<h2 id="高可用性"><a href="#高可用性" class="headerlink" title="高可用性"></a>高可用性</h2><p>RocketMQ与Kafka集群有很大的不同。</p><p><img src="/images/RocketMQ%E5%85%A5%E9%97%A8/1563179127856-1563179127892.png" alt="title"></p><p>Kafka的一台机器可能是partition1的leader，又是partition2的follower.Kafka的一个机器既可能是leader有可能是follower。</p><p>RocketMQ也将一个tpic分为多个partition，在RocketMQ叫Queue，也是将Queue均匀分布在各个broker上来实现负载均衡。但是他的leader，follower身份是固定死的，一个leader和他的follower叫做一个broker群组。当一个master出现宕机，消费者可以从他的slave读取消息，生产者将消息写到别的master上面来实现可用性。但是slave上的消息并不一定是完全同步过来的，因此会有少量的消息丢失。但是消息最终不会丢的，一旦master恢复，未同步过去的消息会被消费掉。</p><h2 id="文件存储"><a href="#文件存储" class="headerlink" title="文件存储"></a>文件存储</h2>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;高可用性&quot;&gt;&lt;a href=&quot;#高可用性&quot; class=&quot;headerlink&quot; title=&quot;高可用性&quot;&gt;&lt;/a&gt;高可用性&lt;/h2&gt;&lt;p&gt;RocketMQ与Kafka集群有很大的不同。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/RocketMQ%E5%8
      
    
    </summary>
    
      <category term="消息队列" scheme="http://yoursite.com/categories/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/"/>
    
    
      <category term="消息队列" scheme="http://yoursite.com/tags/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/"/>
    
  </entry>
  
  <entry>
    <title>Kafka入门</title>
    <link href="http://yoursite.com/2020/01/19/Kafka%E5%85%A5%E9%97%A8/"/>
    <id>http://yoursite.com/2020/01/19/Kafka入门/</id>
    <published>2020-01-19T07:06:17.000Z</published>
    <updated>2020-01-20T10:59:13.094Z</updated>
    
    <content type="html"><![CDATA[<p>Kafka是基于发布订阅模式的，采用消费者拉消息的模式，消息可以被重复消费。</p><p><img src="/images/Kafka%E5%85%A5%E9%97%A8/1562901746685-1562901746690.png" alt="title"></p><h2 id="一些概念"><a href="#一些概念" class="headerlink" title="一些概念"></a>一些概念</h2><h3 id="批量发送"><a href="#批量发送" class="headerlink" title="批量发送"></a>批量发送</h3><p>生产者在生产完一条消息后不是直接发送的，<strong>而是分批次写入（类似于缓冲）</strong>，这样可以提高吞吐量。</p><h3 id="主题-topic-和分区-partition"><a href="#主题-topic-和分区-partition" class="headerlink" title="主题(topic)和分区(partition)"></a>主题(topic)和分区(partition)</h3><p>kafka通过主题进行分类。一个主题可以包含多个分区,<strong>消息以追加的方式写入分区</strong>,然后以先入先出的方式顺序读取.但是由于一个主题包含多个分区,因此,不能保证整个主题的消息顺序,只可以<strong>保证分区内的消息顺序</strong>.<strong>kafka是没有索引的</strong>。kafka是通过offset来标识消息,即该消息在分区中的偏移量.因此，<strong>kafka是几乎不支持随机读写的</strong>。<br>当consumer正常消费消息时,offset将会”线性”的向前驱动,即消息将依次顺序被消费.事实上consumer可以使用任意顺序消费消息,它只需要将offset重置为任意值。</p><p>为什么需要分区呢?<br>主要是为了<strong>负载均衡,将消息分散到多个server上</strong>.</p><ul><li>最根本原因是kafka基于文件存储.通过分区,可以,来避免文件尺寸达到单机磁盘的上限,每个partiton都会被当前server(kafka实例)保存;可以将一个topic切分多任意多个partitions,来消息保存/消费的效率.此外越多的partitions意味着可以容纳更多的consumer,有效提升并发消费的能力.<br>假设我们只有一个分区,那么我们所有的消息都堆积到这一个服务器上.但是,在我们将topic划分为多个分区上,我们可以将分区均匀的分散到多个服务器上,这样,每台服务器压力就会小很多.</li><li>还有一个就是消费者可以并发的读取数据.</li></ul><h2 id="生产者"><a href="#生产者" class="headerlink" title="生产者"></a>生产者</h2><p>生产者生产消息后，采用<strong>顺序写的方式将消息追加写入分区</strong>。</p><h3 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h3><ul><li>创建消息:<strong>创建一个ProducerRecord对象</strong>,主要包括topic,partition,key,value四项,其中patirion和key是可选的.</li><li><strong>序列化</strong>,将ProducerRecord对象序列化.</li><li><strong>分区选择</strong>.若指定分区，直接发送到该分区；若没指定分区，有key，按key哈希计算；若没有key，且没指定分区，采用轮询的方式选择分区。</li><li><strong>添加进批次里,等到批次满了统一发送</strong>.同一批次里的消息topic和partition都应该是相同的.</li><li><strong>服务器返回响应</strong>,消息是否写入成功.</li></ul><h3 id="发送消息方式"><a href="#发送消息方式" class="headerlink" title="发送消息方式"></a>发送消息方式</h3><ul><li>发送即忘记：发送完就不管了。</li><li>同步发送。</li><li>异步发送：指定回调函数来对发送异常进行处理。</li></ul><h3 id="acks"><a href="#acks" class="headerlink" title="acks"></a>acks</h3><p>制定了有多少分区副本收到消息，才算是写入成功。</p><ul><li>acks=0：发送完就不管了，吞吐量高。</li><li>acks=1：首领节点的副本收到消息即可。</li><li>acks=all:所有副本都受到消息。</li></ul><h2 id="消费者"><a href="#消费者" class="headerlink" title="消费者"></a>消费者</h2><h2 id="高可用性"><a href="#高可用性" class="headerlink" title="高可用性"></a>高可用性</h2><p>假如说服务器宕机了怎么办，通过集群来解决。Kafka使用zookeeper来管理集群。多台机器存储数据，当leader宕机了，重新选取一台新的就行了。</p><h3 id="多副本冗余"><a href="#多副本冗余" class="headerlink" title="多副本冗余"></a>多副本冗余</h3><p>因为kafka是以partition为单位的。其<strong>每一个分区都有多个副本，其中，一个leader，其他都是follower</strong>，只有leader进行读写。而且多个副本分布在多台机器上，这样，一台服务器宕机，可以通过选举的方式重新选举leader，依然保持是可用的。而且，应该<strong>每一个分区的leader分布在不同的机器</strong>上，达到负载均衡的目的。例如，机器1存放：leader1,follower2，follower3.机器2存放：follower1,leader2，follower3.机器1存放：follower1,follower2，leader3.这样的话，每一个分区的leader分布在不同的机器上</p><h4 id="写数据"><a href="#写数据" class="headerlink" title="写数据"></a>写数据</h4><p>写数据的时候，<strong>生产者就写 leader</strong>，然后 leader 将数据落地写本地磁盘，接着其他 follower 自己主动从 leader 来 pull 数据。一旦 follower 同步好数据了，就会发送 ack 给 leader。具有同步复制以及异步复制两种模式。</p><h4 id="读数据"><a href="#读数据" class="headerlink" title="读数据"></a>读数据</h4><p>只会从 leader 去读，但是只有当一个消息已经被所有 follower 都同步成功返回 ack 的时候，这个消息才会被消费者读到。</p><h3 id="leader-follower同步问题"><a href="#leader-follower同步问题" class="headerlink" title="leader follower同步问题"></a>leader follower同步问题</h3><p>写数据的时候，<strong>生产者就写 leader</strong>，然后 leader 将数据落地写本地磁盘，接着其他 follower 自己主动从 leader 来 pull 数据。一旦 follower 同步好数据了，就会发送 ack 给 leader。</p><h3 id="ISR机制"><a href="#ISR机制" class="headerlink" title="ISR机制"></a>ISR机制</h3><p>ISR保存的是与leader数据一致的副本列表，根据副本与leader的交互时间差（每隔XXs会向leader发送一个请求）与信息条数差(follower差leader几条信息)判断是否同步，当超过某个阈值就将其移除ISR。</p><p>只有ISR里面的成员才可能被选为leader。当follower又重新追赶上leader之后，将其重新放入ISR。</p><h2 id="幂等性"><a href="#幂等性" class="headerlink" title="幂等性"></a>幂等性</h2><p>消息不重复消费。</p><h3 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h3><p>由于<strong>提交偏移量</strong>可能会有延迟性，会造成Kafka消息重复的问题。</p><p>假如采用定时提交，消费者消费完了一部分消息还未提交，突然宕机了。再均衡之后，消费该分区新的消费者会读取原来的偏移量，这样，未提交偏移量的这部分消息会重复消费。</p><h3 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h3><p>对于每条消息，MQ内部生成一个<strong>全局唯一、与业务无关的消息ID</strong>：inner-msg-id。当MQ-server接收到消息时，先根据inner-msg-id判断消息是否重复发送，再决定是否将消息落地到DB中。这样，有了这个inner-msg-id作为去重的依据就能保证一条消息只能一次落地到DB。</p><h2 id="可靠性"><a href="#可靠性" class="headerlink" title="可靠性"></a>可靠性</h2><p>不丢失消息。</p><h3 id="生产者-1"><a href="#生产者-1" class="headerlink" title="生产者"></a>生产者</h3><p>ack=0时，生产者向broker发送消息，发送途中消息丢失。因为ack=0，发送完就不管了，就不会重试发送消息，消息丢失。</p><p>ack=all可以解决。</p><h3 id="broker"><a href="#broker" class="headerlink" title="broker"></a>broker</h3><p>ack==1，假如消息到达broker，而且写入了leader，但此时leader宕机了，而且并没有写入follower，那么选举的新的leader肯定是follower中的，消息会丢失。</p><p>ack=all可以解决。</p><h3 id="消费者-1"><a href="#消费者-1" class="headerlink" title="消费者"></a>消费者</h3><p>自动提交的问题。如果在消息处理完成前就提交了offset，那么就有可能造成数据的丢失。</p><p>关闭自动提交可以解决。</p><h2 id="顺序性"><a href="#顺序性" class="headerlink" title="顺序性"></a>顺序性</h2><h3 id="什么导致无序"><a href="#什么导致无序" class="headerlink" title="什么导致无序"></a>什么导致无序</h3><ul><li>生产者重试。假如发送1，2，2成功了，1由于网络原因丢失，重新发送1，顺序就变味了2，1.</li><li>分区的问题。假如1，2被发送到了两个不同分区，1所在分区消费的慢，2所在分区消费的快，顺序变为2，1.</li><li>并行消费的问题。即使1，2在一个分区，且未乱序，可能该分区有两个消费者A，B，A先读取1处理，B后读取2处理，B处理比较快。乱序。</li></ul><h3 id="保证局部有序"><a href="#保证局部有序" class="headerlink" title="保证局部有序"></a>保证局部有序</h3><p>分区内有序。</p><p>例如订单场景，创建，付款，发货需要严格有序。</p><p>解决生产者重试问题：每一次确认消息完全到达分区了在发送下一条消息。</p><p>解决分区问题：将同一个订单消息发送到同一个分区。可以根据订单号哈希。</p><p>解决并行消费问题。分区只有一个消费者。或者对分区加锁。</p><h3 id="保证全局有序"><a href="#保证全局有序" class="headerlink" title="保证全局有序"></a>保证全局有序</h3><p>不仅仅是分区内有序，而是所有分区都有序。</p><p>那就只能之创建一个分区了。</p><h2 id="文件存储"><a href="#文件存储" class="headerlink" title="文件存储"></a>文件存储</h2><p>同一个topic下有多个不同的 partition，每个 partiton 为一个目录，partition 的名称规则为：topic 名称 + 有序序号。所以，<strong>partition是物理概念，topic是逻辑概念</strong>。</p><p>partition又可以拆分为多个大小相等的segment。拆分为多个segment，一个是因为这样<strong>查找效率高</strong>；另一个segment为了<strong>删除过期的消息而设置的</strong>。kafka中<strong>消息的写入是直接追加到文件尾部</strong>，而消息被消费后也不会被删除，但是我们可以设置一个过期时间进行消息的删除。我们删除消息直接删除segment文件即可。</p><p>segment包括一个索引文件，一个数据文件。segment文件的命名：segment文件名为上一个segment文件最后一条消息的offset。</p><p>索引文件存储的message在数据文件中的偏移，快速定位message。</p><h3 id="文件存储高效原因"><a href="#文件存储高效原因" class="headerlink" title="文件存储高效原因"></a>文件存储高效原因</h3><h4 id="分段"><a href="#分段" class="headerlink" title="分段"></a>分段</h4><p>采用分段存储的话，因为<strong>数据文件以该段中最小的offset</strong>命名。这样在查找指定offset的Message的时候，用<strong>二分查找就可以定位到该Message在哪个段中</strong>。</p><h4 id="索引文件"><a href="#索引文件" class="headerlink" title="索引文件"></a>索引文件</h4><p>每一个数据文件都有一个索引文件，便于快速寻找消息在段中的位置。</p><h4 id="稀疏索引"><a href="#稀疏索引" class="headerlink" title="稀疏索引"></a>稀疏索引</h4><p>i<strong>ndex file并没有为数据文件中的每条message建立索引</strong>，而是采取<strong>稀疏索引存储</strong>方式，每隔一定字节的数据建立一条索引，它减少了索引文件大小，<strong>通过map可以直接内存操作</strong>，稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间，但查找起来需要消耗更多的时间。</p><h3 id="文件读写高效原因"><a href="#文件读写高效原因" class="headerlink" title="文件读写高效原因"></a>文件读写高效原因</h3><p>写入优化：顺序写入+Mmap。</p><p>读取优化：sendFile零拷贝+读写空中接力</p><h4 id="顺序写入"><a href="#顺序写入" class="headerlink" title="顺序写入"></a>顺序写入</h4><p>kafka是<strong>顺序追加写入</strong>的，<strong>避免了磁道寻址</strong>的时间，顺序写入比随机写入，尤其是机械硬盘效率要大得多。。</p><h4 id="MMap"><a href="#MMap" class="headerlink" title="MMap"></a>MMap</h4><p>采用MMap来写入数据到磁盘。</p><p><strong>传统的文件写入方式是将数据从用户空间转移到内核空间，再由内核空间拷贝到PageCache，最后由操作系统异步刷盘将pageCache中数据落盘</strong>。</p><p>而MMap省去了用户空间到内核空间的过程，<strong>直接将数据写入到pageCache</strong>，再由操作系统将pageCache中的数据落盘。</p><p>也有一个很明显的缺陷——不可靠，<strong>写到mmap中的数据并没有被真正的写到硬盘，操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘。</strong>如果在pageCache还未落盘的时候宕机了，数据会丢失。</p><p>Kafka提供了一个参数——producer.type来控制是不是主动flush，如果Kafka写入到mmap之后就立即flush然后再返回Producer叫<strong>同步</strong>(sync)；写入mmap之后立即返回Producer不调用flush叫<strong>异步</strong>(async)。</p><h4 id="sendFile零拷贝"><a href="#sendFile零拷贝" class="headerlink" title="sendFile零拷贝"></a>sendFile零拷贝</h4><p>消费者在读取消息的时候，使用sendFile。</p><p>传统I/O与socket传输：磁盘数据-&gt;内核缓冲区-&gt;用户空间-&gt;内核socket缓冲区-&gt;网卡缓存，四次拷贝。</p><p>而sendFile直接从内核缓冲区发送到网卡缓存，省掉了两次拷贝。</p><h4 id="读写空中接力"><a href="#读写空中接力" class="headerlink" title="读写空中接力"></a>读写空中接力</h4><ul><li>当写操作发生时，它只是将数据写入Page Cache中，并将该页置上dirty标志。</li><li>当读操作发生时，它会首先在Page Cache中查找内容，如果有就直接返回了，没有的话就会从磁盘读取文件再写回Page Cache。</li><li>可见，只要生产者与消费者的速度相差不大，消费者会直接读取之前生产者写入Page Cache的数据，大家在内存里完成接力，根本没有磁盘访问。而比起在内存中维护一份消息数据的传统做法，这既不会重复浪费一倍的内存，Page Cache又不需要GC(可以放心使用大把内存了)，而且<strong>即使Kafka重启了，Page Cache还依然在</strong>。</li></ul><p><a href="https://juejin.im/post/5cbf2d58f265da0380436fde" target="_blank" rel="noopener">高可用</a></p><p><a href="http://matt33.com/2016/03/08/kafka-store/" target="_blank" rel="noopener">kafka文件存储</a></p><p><a href="https://www.jianshu.com/p/650c9878dee7" target="_blank" rel="noopener">kafka文件读写</a></p><p><a href="https://www.cnblogs.com/monkeyteng/p/10221291.html" target="_blank" rel="noopener">kafka读写问题</a></p><p><a href="https://zhuanlan.zhihu.com/p/71149410" target="_blank" rel="noopener">pageCache问题</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Kafka是基于发布订阅模式的，采用消费者拉消息的模式，消息可以被重复消费。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/Kafka%E5%85%A5%E9%97%A8/1562901746685-1562901746690.png&quot; alt=&quot;title&quot;&gt;&lt;/p&gt;
      
    
    </summary>
    
      <category term="消息队列" scheme="http://yoursite.com/categories/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/"/>
    
    
      <category term="消息队列" scheme="http://yoursite.com/tags/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/"/>
    
  </entry>
  
  <entry>
    <title>消息队列简介</title>
    <link href="http://yoursite.com/2020/01/19/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%AE%80%E4%BB%8B/"/>
    <id>http://yoursite.com/2020/01/19/消息队列简介/</id>
    <published>2020-01-19T02:49:18.000Z</published>
    <updated>2020-01-20T11:25:06.279Z</updated>
    
    <content type="html"><![CDATA[<p>啊啊消息队列就是用来存储消息的容器，假如A应用需要将消息传送给B，那么他并不是直接发送给B，而是将消息发送到消息队列中，由B直接从消息队列中获取。</p><a id="more"></a><h2 id="消息队列作用"><a href="#消息队列作用" class="headerlink" title="消息队列作用"></a>消息队列作用</h2><h3 id="解耦"><a href="#解耦" class="headerlink" title="解耦"></a>解耦</h3><p>假如系统A需要将数据发送个B，那么直接定义一个发送至B的方法，但是不久之后，A的数据又需要发送到C呢，难道再更改A的代码，这样可扩展性太低了。但是，有了消息队列就不同了，<strong>A直接将消息发送到消息队列，不用去管谁需要使用消息</strong>。</p><h3 id="异步"><a href="#异步" class="headerlink" title="异步"></a>异步</h3><p>系统A将数据写到消息队列，就可以直接返回，可以不用管消费者具体怎么处理数据的。</p><h3 id="削峰"><a href="#削峰" class="headerlink" title="削峰"></a>削峰</h3><p>当短时间内并发量比较大时，可能暂时无法处理这么多请求，<strong>可以先将消息存储再消息队列中，等并发量下去了在处理堆积的请求</strong>。</p><h2 id="三种协议"><a href="#三种协议" class="headerlink" title="三种协议"></a>三种协议</h2><h3 id="JMS"><a href="#JMS" class="headerlink" title="JMS"></a>JMS</h3><p>ActiveMQ是基于JMS的。</p><p>JMS主要有两种消费模式，点对点和发布/订阅模式。这两种模式的区别<strong>主要在于消息是否可以重复消费</strong>。</p><h4 id="点对点"><a href="#点对点" class="headerlink" title="点对点"></a>点对点</h4><p><img src="/images/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%AE%80%E4%BB%8B/1562760110133-1562760110140.png" alt="title"><br>生产者将消息发送到Queue中，消费者从Queue中取出消息并消费。<strong>消息被消费完之后，Queue中消息会被删除。</strong><br><strong>Queue支持存在多个消费者，但是一条消息只可能被一个消费者消费，一旦消费完成消息会被删除。</strong><br>这种模式消费者需要不断去<strong>轮询监听</strong>消息队列看有没有新的消息产生。</p><h4 id="发布-订阅模型"><a href="#发布-订阅模型" class="headerlink" title="发布/订阅模型"></a>发布/订阅模型</h4><p><img src="/images/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%AE%80%E4%BB%8B/1562760358990-1562760359009.png" alt="title"></p><p>生产者将消息发送到topic，同时有多个消费者订阅该消息，那么<strong>所有的订阅者都会消费该消息</strong>。<br>发布订阅模式缺点是无法感知客户端的实际处理能力。</p><p>发布订阅模式下，当发布者消息量很大时，显然单个订阅者的处理能力是不足的。<strong>实际上现实场景中是多个订阅者节点组成一个订阅组负载均衡消费topic消息即分组订阅</strong>，这样订阅者很容易实现消费能力线性扩展。可以看成是一个topic下有多个Queue，每个Queue是点对点的方式，Queue之间是发布订阅方式。</p><p><img src="/images/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%AE%80%E4%BB%8B/1562901340287-1562901340308.png" alt="title"></p><h3 id="AMQP"><a href="#AMQP" class="headerlink" title="AMQP"></a>AMQP</h3><p>与JMS一样，他也有生产者和消费者，消息也是存储在Queue中的。<br>最大的不同是，<strong>AMQP是通过bindingkey和exchange来决定将消息给哪个消费者消费</strong>。<br>在创建Queue的时候<strong>给Queue一个binding key</strong>，生产者发送消息的时候，会给这条<strong>消息设定一个router key</strong>，exchange会将router key与binding key进行比较，将消息发送到符合的Queue中，再由相应的消费者消费消息。<br>交换机收到生产者投递的消息，基于路由规则及队列绑定关系匹配到投递对应的交换机或者队列进行分发，交换机不存储消息，只做转发。</p><p>RabbitMQ使用的是该协议。</p><h3 id="MQTT"><a href="#MQTT" class="headerlink" title="MQTT"></a>MQTT</h3><p>专门为小设备设计，简单不复杂，适用于物联网。</p><p>基于发布/订阅模式。</p><h2 id="推-拉两种模式"><a href="#推-拉两种模式" class="headerlink" title="推/拉两种模式"></a>推/拉两种模式</h2><p>在消费中，一般有<strong>推消息和拉消息</strong>两种模式。</p><p>推模式即服务端收到消息后，<strong>主动将消息推送给消费者</strong>，由消费者进行处理，这种模式具有<strong>更高的实时性</strong>，但是由于服务端不能准确评估消费端的消费性能，所以有可能<strong>造成消息推送过多使客户端来不及处理</strong>收到的消息； </p><p>拉模式则是服务端收到消息后将消息保存在服务端，被动的等待<strong>客户端来拉取消息</strong>，这种模式下客户端可以根据自己的处理能力来决定拉消息的频率，但是缺点就是消息处理可能有延迟，不过可以通过长轮询的方式来提高实时性。</p><h2 id="三种消息级别"><a href="#三种消息级别" class="headerlink" title="三种消息级别"></a>三种消息级别</h2><h3 id="至多一次"><a href="#至多一次" class="headerlink" title="至多一次"></a>至多一次</h3><p>这个很简单，消息发送完就不管了，不管它有没有消费成功。</p><h3 id="至少一次"><a href="#至少一次" class="headerlink" title="至少一次"></a>至少一次</h3><p>生产者发消息到 MQ，MQ 收到消息后返回确认信息（ACK）给生产者，生产者收到确认信息后生产过程完成，如果在一定时间内，生产者没有收到确认信息，生产者重新发送消息。<br>但是这样就容易导致<strong>重复发送</strong>的问题。</p><h3 id="恰好一次"><a href="#恰好一次" class="headerlink" title="恰好一次"></a>恰好一次</h3><p>发送端发消息给接收端，接收端收到消息后持久化保存消息 ID 并返回 REC 信息给发送端，通知生产端我已经收到这个消息了。 这时消息是一种中间态，接受端不会进行业务逻辑的处理。这个过程中，如果 REC 消息丢失，服务端重传了消息， 接受端接受到消息后会和本地保存到消息 ID 做对比，如果重复，就丢弃消息不做处理，避免消息被处理多次，而且消息 ID 会持久化到硬盘，防止因为断电内存中数据丢失倒是消息被重复处理。 发送端收到接收端返回的 rec 消息后，发送一个 rel 请求给消费端，告诉消费端我确认收到了你的确认消息，接收端收到 rel 请求后才会进行具体的业务逻辑处理，并返回 comp 信息给发送端，同时在本地删除保存的消息 ID。如果发送端没有收到 comp 信息，会重发 rel 请求而不会重发消息。</p><p>其实，在大部分情况下，大部分消息中间件一般只保证至少一次，去重的过程交给消费者自己处理了。  那么，什么场景下，需要保证正好一次呢？ 答案是物联网。 而标准的实现协议，是 MQTT。 因为物联网场景下，大部分终端是嵌入式系统，处理能力会比服务器低很多，所以服务端需要帮助终端实现去重，简化终端的业务逻辑。</p><h2 id="高可用性"><a href="#高可用性" class="headerlink" title="高可用性"></a>高可用性</h2><p>集群来解决。</p><h2 id="幂等性"><a href="#幂等性" class="headerlink" title="幂等性"></a>幂等性</h2><p>保证消息不会被重复消费。</p><h2 id="可靠性保障"><a href="#可靠性保障" class="headerlink" title="可靠性保障"></a>可靠性保障</h2><p>保证消息不会丢失。</p><h2 id="顺序消息"><a href="#顺序消息" class="headerlink" title="顺序消息"></a>顺序消息</h2><h2 id="事务消息"><a href="#事务消息" class="headerlink" title="事务消息"></a>事务消息</h2><h2 id="刷盘问题"><a href="#刷盘问题" class="headerlink" title="刷盘问题"></a>刷盘问题</h2><p><img src="/images/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%AE%80%E4%BB%8B/5475068-4399932f6471e662.webp" alt="img"></p><p>同步刷盘：写入到pageCache之后，需要手动将pageCache数据落盘才返回。不会丢消息，但是效率低。</p><p>异步刷盘：写入到pageCache就返回，pageCache落盘由操作系统定期执行。效率高，但是宕机有可能丢消息。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;啊啊消息队列就是用来存储消息的容器，假如A应用需要将消息传送给B，那么他并不是直接发送给B，而是将消息发送到消息队列中，由B直接从消息队列中获取。&lt;/p&gt;
    
    </summary>
    
      <category term="消息队列" scheme="http://yoursite.com/categories/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/"/>
    
    
      <category term="消息队列" scheme="http://yoursite.com/tags/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/"/>
    
  </entry>
  
  <entry>
    <title>反射机制</title>
    <link href="http://yoursite.com/2020/01/16/%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6/"/>
    <id>http://yoursite.com/2020/01/16/反射机制/</id>
    <published>2020-01-16T06:44:37.000Z</published>
    <updated>2020-01-16T07:42:30.509Z</updated>
    
    <content type="html"><![CDATA[<h2 id="何为反射"><a href="#何为反射" class="headerlink" title="何为反射"></a>何为反射</h2><p>反射是框架设计的灵魂。在<strong>运行时才通过类名动态的将class对象加载进内存</strong>，通过类的class对象就可以获取类的全部信息，包括方法，字段等。一般常用于框架设计中。</p><h3 id="创建一个对象的过程"><a href="#创建一个对象的过程" class="headerlink" title="创建一个对象的过程"></a>创建一个对象的过程</h3><ul><li>将字节码文件加载进内存，形成运行时内存结构，形成class对象。</li><li>分配堆内存空间。</li><li>调用构造器，创造一个空白对象。</li><li>子类调用父类构造器。</li><li>执行子类构造器。</li></ul><p><img src="/images/%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6/v2-eddc430b991c58039dfc79dd6f3139cc_hd.jpg" alt="img"></p><p>所以，实例化一个对象，是离不开class对象的。</p><h3 id="class对象"><a href="#class对象" class="headerlink" title="class对象"></a>class对象</h3><p>class对象主要包含Field，Method，Constructor。</p><p><img src="/images/%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6/v2-96e87c388c61b8de3a6c526a17128f63_hd.jpg" alt="img"></p><p>因此，class对象包含了这个类的所有信息，通过Field，Method就可以直接访问类的成员。</p><h3 id="反射使用"><a href="#反射使用" class="headerlink" title="反射使用"></a>反射使用</h3><h4 id="获取class对象"><a href="#获取class对象" class="headerlink" title="获取class对象"></a>获取class对象</h4><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></pre></td><td class="code"><pre><span class="line">Class c2 = Class.forName(<span class="string">"[D"</span>);</span><br><span class="line">Class c1 = Boolean.class;</span><br><span class="line">Class c4 = instance.getClass();</span><br></pre></td></tr></table></figure><h4 id="获取成员"><a href="#获取成员" class="headerlink" title="获取成员"></a>获取成员</h4><p>getField</p><p>通过反射甚至可以访问私有变量。</p><h4 id="获取并调用方法"><a href="#获取并调用方法" class="headerlink" title="获取并调用方法"></a>获取并调用方法</h4><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></pre></td><td class="code"><pre><span class="line">Class&lt;?&gt; klass = methodClass.class;</span><br><span class="line"><span class="comment">//创建methodClass的实例</span></span><br><span class="line">Object obj = klass.newInstance();</span><br><span class="line"><span class="comment">//获取methodClass类的add方法，传入int.class是为了确定唯一的方法，以防重载</span></span><br><span class="line">Method method = klass.getMethod(<span class="string">"add"</span>,<span class="keyword">int</span>.class,<span class="keyword">int</span>.class);</span><br><span class="line"><span class="comment">//调用method对应的方法 =&gt; add(1,4)</span></span><br><span class="line">Object result = method.invoke(obj,<span class="number">1</span>,<span class="number">4</span>);</span><br><span class="line">System.out.println(result);</span><br></pre></td></tr></table></figure><h2 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h2><p>JDBC数据库连接</p><p>Spring框架配置</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;何为反射&quot;&gt;&lt;a href=&quot;#何为反射&quot; class=&quot;headerlink&quot; title=&quot;何为反射&quot;&gt;&lt;/a&gt;何为反射&lt;/h2&gt;&lt;p&gt;反射是框架设计的灵魂。在&lt;strong&gt;运行时才通过类名动态的将class对象加载进内存&lt;/strong&gt;，通过类的clas
      
    
    </summary>
    
      <category term="java" scheme="http://yoursite.com/categories/java/"/>
    
    
      <category term="java" scheme="http://yoursite.com/tags/java/"/>
    
  </entry>
  
  <entry>
    <title>leetcode字符串</title>
    <link href="http://yoursite.com/2020/01/02/leetcode%E5%AD%97%E7%AC%A6%E4%B8%B2/"/>
    <id>http://yoursite.com/2020/01/02/leetcode字符串/</id>
    <published>2020-01-02T14:35:02.000Z</published>
    <updated>2020-01-15T07:29:33.269Z</updated>
    
    <content type="html"><![CDATA[<h3 id="32-最长有效括号"><a href="#32-最长有效括号" class="headerlink" title="32. 最长有效括号"></a><a href="https://leetcode-cn.com/problems/longest-valid-parentheses/" target="_blank" rel="noopener">32. 最长有效括号</a></h3><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 可以直接使用栈来做，栈中存放的是下标。</span></span><br><span class="line"><span class="comment">     * 当元素是'('，直接入栈下标，当元素是')'且栈顶是'('，将栈顶出栈，并且减去栈顶下标，然后就得到当前合法序列的长度</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">longestValidParentheses</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(s==<span class="keyword">null</span>||s.length()==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Stack&lt;Integer&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    stack.push(-<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;s.length();i++)&#123;</span><br><span class="line">        <span class="keyword">if</span>(s.charAt(i)==<span class="string">'('</span>)&#123;</span><br><span class="line">            stack.push(i);</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            stack.pop();</span><br><span class="line">            <span class="keyword">if</span>(stack.isEmpty())&#123;</span><br><span class="line">                stack.push(i);</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                res = Math.max(res,i-stack.peek());</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">longestValidParentheses</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span>[] dp = <span class="keyword">new</span> <span class="keyword">int</span>[s.length()];</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> max = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//假如直接是'('，那么dp[i]直接等于0,如果是')'，那么需要看i-dp[i-1]-1个位置是否是'('，假如是的话+2，还需要再看i-dp[i-1]-1前一个位置的dp</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>;i&lt;s.length();i++)&#123;</span><br><span class="line">        <span class="keyword">if</span>(s.charAt(i)==<span class="string">')'</span>)&#123;</span><br><span class="line">            <span class="keyword">int</span> pre = i-dp[i-<span class="number">1</span>]-<span class="number">1</span>;</span><br><span class="line">            <span class="keyword">if</span>(pre&gt;=<span class="number">0</span>&amp;&amp;s.charAt(pre)==<span class="string">'('</span>)&#123;</span><br><span class="line">                dp[i] = dp[i-<span class="number">1</span>]+<span class="number">2</span>+(pre-<span class="number">1</span>&gt;=<span class="number">0</span>?dp[pre-<span class="number">1</span>]:<span class="number">0</span>);</span><br><span class="line">                max= Math.max(max,dp[i]);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="20-有效的括号"><a href="#20-有效的括号" class="headerlink" title="20.有效的括号"></a>20.有效的括号</h3><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isValid</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">    Stack&lt;Character&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;s.length();i++)&#123;</span><br><span class="line">        <span class="keyword">if</span>(s.charAt(i)==<span class="string">']'</span>||s.charAt(i)==<span class="string">')'</span>||s.charAt(i)==<span class="string">'&#125;'</span>)&#123;</span><br><span class="line">            <span class="keyword">if</span>(!stack.isEmpty())&#123;</span><br><span class="line">                <span class="keyword">char</span> c1 = stack.pop();</span><br><span class="line">                <span class="keyword">if</span>(!isSym(c1,s.charAt(i)))&#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            stack.push(s.charAt(i));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> stack.isEmpty();</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isSym</span><span class="params">(<span class="keyword">char</span> c1,<span class="keyword">char</span> c2)</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (c1==<span class="string">'('</span>&amp;&amp;c2==<span class="string">')'</span>)||(c1==<span class="string">'['</span>&amp;&amp;c2==<span class="string">']'</span>)||(c1==<span class="string">'&#123;'</span>&amp;&amp;c2==<span class="string">'&#125;'</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;32-最长有效括号&quot;&gt;&lt;a href=&quot;#32-最长有效括号&quot; class=&quot;headerlink&quot; title=&quot;32. 最长有效括号&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://leetcode-cn.com/problems/longest-valid-pa
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>leetcode牛客进阶班</title>
    <link href="http://yoursite.com/2019/12/21/leetcode%E7%89%9B%E5%AE%A2%E8%BF%9B%E9%98%B6%E7%8F%AD/"/>
    <id>http://yoursite.com/2019/12/21/leetcode牛客进阶班/</id>
    <published>2019-12-21T11:56:47.000Z</published>
    <updated>2020-01-14T02:56:51.705Z</updated>
    
    <content type="html"><![CDATA[<h4 id="9-回文数"><a href="#9-回文数" class="headerlink" title="9. 回文数"></a><a href="https://leetcode-cn.com/problems/palindrome-number/" target="_blank" rel="noopener">9. 回文数</a></h4><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isPalindrome</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(x&lt;<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//计算x的最高位数,12321 计算出10000</span></span><br><span class="line">    <span class="keyword">int</span> help = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(x/help&gt;=<span class="number">10</span>)&#123;</span><br><span class="line">        help*=<span class="number">10</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span>(x!=<span class="number">0</span>) &#123;</span><br><span class="line">        <span class="comment">//x/help计算第一个位置 x%10计算最后一个位置</span></span><br><span class="line">        <span class="keyword">if</span> (x / help != x % <span class="number">10</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//x%help/10 12321-&gt;232，因为少了两位，所以help/100</span></span><br><span class="line">        x = x%help/<span class="number">10</span>;</span><br><span class="line">        help/=<span class="number">100</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="未排序正数数组中累加和为定值的最长子数组长度"><a href="#未排序正数数组中累加和为定值的最长子数组长度" class="headerlink" title="未排序正数数组中累加和为定值的最长子数组长度"></a>未排序正数数组中累加和为定值的最长子数组长度</h3><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><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 未排序正数数组中累加和为定值的最长子数组长度</span></span><br><span class="line"><span class="comment">     * 准备两个指针，left以及right，以sum表示left以及right之间的数值和。</span></span><br><span class="line"><span class="comment">     * 假如sum&lt;k，则right后移；</span></span><br><span class="line"><span class="comment">     * sum==k，记录下长度，并将left左移；</span></span><br><span class="line"><span class="comment">     * sum&gt;k，left直接左移</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getMaxLength</span><span class="params">(<span class="keyword">int</span>[] nums,<span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (nums == <span class="keyword">null</span> || nums.length == <span class="number">0</span> || k &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> left = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> right = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> maxLength = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> (right &lt; nums.length) &#123;</span><br><span class="line">        <span class="comment">//假如sum&lt;k，说明不够长，还需要加元素，right往右移</span></span><br><span class="line">        <span class="keyword">if</span> (sum &lt; k) &#123;</span><br><span class="line">            right++;</span><br><span class="line">            <span class="comment">//注意下标越界判断</span></span><br><span class="line">            <span class="keyword">if</span>(right==nums.length)&#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            sum += nums[right];</span><br><span class="line">            <span class="comment">//sum==k，记录长度，太满了，缩小长度，将left右移</span></span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (sum == k) &#123;</span><br><span class="line">            maxLength = Math.max(maxLength, right - left + <span class="number">1</span>);</span><br><span class="line">            sum -= nums[left];</span><br><span class="line">            left++;</span><br><span class="line">            <span class="comment">//sum&gt;k，太满了，left右移</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            sum -= nums[left];</span><br><span class="line">            left++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> maxLength;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="未排序整数数组中累加和为定值的最长子数组长度"><a href="#未排序整数数组中累加和为定值的最长子数组长度" class="headerlink" title="未排序整数数组中累加和为定值的最长子数组长度"></a>未排序整数数组中累加和为定值的最长子数组长度</h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 未排序整数数组中累加和为定值的最长子数组长度，可为正，负，0</span></span><br><span class="line"><span class="comment">     * sum用来记录从0到i的子数组之和，使用map存储所有出现的sum值以及位置</span></span><br><span class="line"><span class="comment">     * 在map中查找sum-k，假如存在，那么i与该位置之间就是满足的子数组，与最值比较</span></span><br><span class="line"><span class="comment">     * 假如sum-k不存在，那么以nums[i]结尾的情况下没有累加和为k的子数组</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">subarraySum</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(nums==<span class="keyword">null</span>||nums.length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> max = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//存储sum值以及他第一次出现的位置</span></span><br><span class="line">    Map&lt;Integer,Integer&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    map.put(<span class="number">0</span>,-<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> index=<span class="number">0</span>;index&lt;nums.length;index++)&#123;</span><br><span class="line">        sum+=nums[index];</span><br><span class="line">        <span class="keyword">if</span>(map.containsKey(sum-k))&#123;</span><br><span class="line">            max = Math.max(max,index-map.get(sum-k));</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(!map.containsKey(sum))&#123;</span><br><span class="line">            map.put(sum,index);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="525-连续数组"><a href="#525-连续数组" class="headerlink" title="525. 连续数组"></a><a href="https://leetcode-cn.com/problems/contiguous-array/" target="_blank" rel="noopener">525. 连续数组</a></h3><p>给定一个二进制数组, 找到含有相同数量的 0 和 1 的最长连续子数组（的长度）。</p><p>该题与上题类似，可以将0转化为-1，这样求解累加和是0的最长子数组长度。</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><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></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">findMaxLength</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">if</span>(nums==<span class="keyword">null</span>||nums.length==<span class="number">0</span>)&#123;</span><br><span class="line">           <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="comment">//存储某个sum值以及第一次出现的位置</span></span><br><span class="line">       Map&lt;Integer,Integer&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">       <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">       <span class="keyword">int</span> max = <span class="number">0</span>;</span><br><span class="line">       map.put(<span class="number">0</span>,-<span class="number">1</span>);</span><br><span class="line">       <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;nums.length;i++)&#123;</span><br><span class="line">           sum+=nums[i]==<span class="number">0</span>?-<span class="number">1</span>:nums[i];</span><br><span class="line">           <span class="keyword">if</span>(map.containsKey(sum-<span class="number">0</span>))&#123;</span><br><span class="line">               max = Math.max(max,i-map.get(sum-<span class="number">0</span>));</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">if</span>(!map.containsKey(sum))&#123;</span><br><span class="line">               map.put(sum,i);</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="560-和为K的子数组"><a href="#560-和为K的子数组" class="headerlink" title="560. 和为K的子数组"></a><a href="https://leetcode-cn.com/problems/subarray-sum-equals-k/" target="_blank" rel="noopener">560. 和为K的子数组</a></h3><p>给定一个整数数组和一个整数 <strong>k，</strong>你需要找到该数组中和为 <strong>k</strong> 的连续的子数组的个数。</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 整数数组，依旧使用sum-k的方式</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">subarraySum2</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(nums==<span class="keyword">null</span>||nums.length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//map中存储的是某个sum值出现的次数</span></span><br><span class="line">    Map&lt;Integer,Integer&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    <span class="comment">//初始0值出现了一次</span></span><br><span class="line">    map.put(<span class="number">0</span>,<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> index=<span class="number">0</span>;index&lt;nums.length;index++)&#123;</span><br><span class="line">        sum+=nums[index];</span><br><span class="line">        <span class="keyword">if</span>(map.containsKey(sum-k))&#123;</span><br><span class="line">            count+=map.get(sum-k);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//存储sum出现的次数，假如map中已经存在，直接++，未存在，直接存储1</span></span><br><span class="line">        map.put(sum,map.getOrDefault(sum,<span class="number">0</span>)+<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> count;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="未排序数组中累加和小于或等于给定值的最长子数组长度"><a href="#未排序数组中累加和小于或等于给定值的最长子数组长度" class="headerlink" title="未排序数组中累加和小于或等于给定值的最长子数组长度"></a>未排序数组中累加和小于或等于给定值的最长子数组长度</h3><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="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxLength</span><span class="params">(<span class="keyword">int</span>[] arr,<span class="keyword">int</span> k)</span></span>&#123;</span><br><span class="line">    <span class="comment">//计算以i结尾的最小子数组长度</span></span><br><span class="line">    <span class="keyword">int</span>[] minSums = <span class="keyword">new</span> <span class="keyword">int</span>[arr.length];</span><br><span class="line">    <span class="keyword">int</span>[] minEnds = <span class="keyword">new</span> <span class="keyword">int</span>[arr.length];</span><br><span class="line">    minSums[arr.length-<span class="number">1</span>] = minSums[arr.length-<span class="number">1</span>];</span><br><span class="line">    minEnds[arr.length-<span class="number">1</span>] = arr.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=arr.length-<span class="number">2</span>;i&gt;=<span class="number">0</span>;i--)&#123;</span><br><span class="line">        <span class="keyword">if</span>(minSums[i+<span class="number">1</span>]&lt;<span class="number">0</span>)&#123;</span><br><span class="line">            minSums[i] = minSums[i+<span class="number">1</span>]+arr[i];</span><br><span class="line">            minEnds[i] = minEnds[i+<span class="number">1</span>];</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            minSums[i] = arr[i];</span><br><span class="line">            minEnds[i] = i;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//扩展窗口,end是窗口最右位置的下一个位置，i是窗口的左侧</span></span><br><span class="line">    <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> end = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> max = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;arr.length;i++)&#123;</span><br><span class="line">        <span class="comment">//将窗口向右扩，直到&gt;k</span></span><br><span class="line">        <span class="keyword">while</span>(end&lt;arr.length&amp;&amp;sum+minSums[end]&lt;=k)&#123;</span><br><span class="line">            sum+=minSums[end];</span><br><span class="line">            end = minEnds[end]+<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//扩充到不能再扩了，形成了一个结果</span></span><br><span class="line">        max = Math.max(max,end-i);</span><br><span class="line">        <span class="comment">//移动左侧位置</span></span><br><span class="line">        <span class="keyword">if</span>(end&gt;i)&#123;</span><br><span class="line">            sum-=arr[i];</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            end = i+<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="约瑟夫环问题"><a href="#约瑟夫环问题" class="headerlink" title="约瑟夫环问题"></a>约瑟夫环问题</h3>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h4 id=&quot;9-回文数&quot;&gt;&lt;a href=&quot;#9-回文数&quot; class=&quot;headerlink&quot; title=&quot;9. 回文数&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://leetcode-cn.com/problems/palindrome-number/&quot; target=&quot;
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>leetcode递归与动态规划</title>
    <link href="http://yoursite.com/2019/12/21/leetcode%E9%80%92%E5%BD%92%E4%B8%8E%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
    <id>http://yoursite.com/2019/12/21/leetcode递归与动态规划/</id>
    <published>2019-12-21T03:17:19.000Z</published>
    <updated>2020-01-14T13:29:56.741Z</updated>
    
    <content type="html"><![CDATA[<h2 id="0-1背包"><a href="#0-1背包" class="headerlink" title="0-1背包"></a>0-1背包</h2><p>有一个<strong>容量为 N</strong> 的背包，要用<strong>这个背包装下物品的价值最大</strong>，这些物品有两个属性：体积 w 和价值 v。<strong>每件物品仅使用一次</strong>。</p><p>主要特点：每个物品只有一件，选择放或者不放。</p><p>f(i,v)表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是：f(i,v)=max{f(i-1,v),f(i-1,v-c[i])+w[i]}。</p><p>放第i件物品：f(i,v) = 第i件物品的价值+i-1件物品放入v-第i件物品的花费</p><p>不放第i件物品：就是前i-1件物品放入容量为v的背包中。</p><h4 id="416-分割等和子集"><a href="#416-分割等和子集" class="headerlink" title="416. 分割等和子集"></a><a href="https://leetcode-cn.com/problems/partition-equal-subset-sum/" target="_blank" rel="noopener">416. 分割等和子集</a></h4><p>给定一个<strong>只包含正整数</strong>的<strong>非空</strong>数组。是否可以将这个数组分割成两个子集，使得两个子集的元素和相等。</p><h2 id="完全背包"><a href="#完全背包" class="headerlink" title="完全背包"></a>完全背包</h2><p><strong>每件物品使用次数不限制</strong>。</p><h2 id="多重背包"><a href="#多重背包" class="headerlink" title="多重背包"></a>多重背包</h2><p><strong>每个物品可选的次数不同</strong>。</p><h2 id="汉诺塔"><a href="#汉诺塔" class="headerlink" title="汉诺塔"></a>汉诺塔</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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 汉诺塔问题</span></span><br><span class="line"><span class="comment">     * 递归方法来解决。</span></span><br><span class="line"><span class="comment">     * from  to   help</span></span><br><span class="line"><span class="comment">     * 一开始from有n个元素，需要将这n个元素移动到to中。可以分为三个步骤：</span></span><br><span class="line"><span class="comment">     *  1.将n-1个元素从from移动到help</span></span><br><span class="line"><span class="comment">     *  2.将第n个元素从from直接移到to</span></span><br><span class="line"><span class="comment">     *  3.将n-1个元素从help移动到to</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">hanuo</span><span class="params">(<span class="keyword">int</span> N,String from,String to,String help)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(N==<span class="number">1</span>)&#123;</span><br><span class="line">        System.out.println(<span class="string">"move 1 "</span>+<span class="string">" form "</span>+from+<span class="string">" to "</span>+to);</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        hanuo(N-<span class="number">1</span>,from,help,to);</span><br><span class="line">        System.out.println(<span class="string">"move "</span>+N+<span class="string">" from "</span>+from+<span class="string">" to "</span>+to);</span><br><span class="line">        hanuo(N-<span class="number">1</span>,help,to,from);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="198-打家劫舍"><a href="#198-打家劫舍" class="headerlink" title="198.打家劫舍"></a>198.打家劫舍</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></pre></td><td class="code"><pre><span class="line"><span class="comment">//dp[i]到第i家可以偷多少钱dp[i]=max(dp[i-1],dp[i-2]+nums[i-1])</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">rob</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(nums.length&lt;<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</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>[nums.length+<span class="number">1</span>];</span><br><span class="line">    dp[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">    dp[<span class="number">1</span>] = nums[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">2</span>;i&lt;=nums.length;i++)&#123;</span><br><span class="line">        dp[i] = Math.max(dp[i-<span class="number">2</span>]+nums[i-<span class="number">1</span>],dp[i-<span class="number">1</span>]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> dp[nums.length];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="打印字符串子序列"><a href="#打印字符串子序列" class="headerlink" title="打印字符串子序列"></a>打印字符串子序列</h2><p>例如abc，打印a , ab , abc ,ac, bc,以及空字符串</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><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">printAllSub</span><span class="params">(<span class="keyword">char</span>[] arr,<span class="keyword">int</span> i,String res)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(i==arr.length)&#123;</span><br><span class="line">        System.out.println(res);</span><br><span class="line">        <span class="keyword">return</span> ;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//存在两种情况，打印该元素以及不打印该元素</span></span><br><span class="line">    printAllSub(arr,i+<span class="number">1</span>,res);</span><br><span class="line">    printAllSub(arr,i+<span class="number">1</span>,res+String.valueOf(arr[i]));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="生牛"><a href="#生牛" class="headerlink" title="生牛"></a>生牛</h2><p><img src="../images/leetcode%E9%80%92%E5%BD%92%E4%B8%8E%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/1576899784912.png" alt="1576899784912"></p><h2 id="64-最小路径和"><a href="#64-最小路径和" class="headerlink" title="64. 最小路径和"></a><a href="https://leetcode-cn.com/problems/minimum-path-sum/" target="_blank" rel="noopener">64. 最小路径和</a></h2><p>暴力递归解法</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><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></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">minPathSum</span><span class="params">(<span class="keyword">int</span>[][] grid)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(grid.length==<span class="number">0</span>||grid[<span class="number">0</span>].length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> helperMinPath(grid,<span class="number">0</span>,<span class="number">0</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 递归来解决</span></span><br><span class="line"><span class="comment">     *  该方法表示从(row,col)走到右下角的距离</span></span><br><span class="line"><span class="comment">     *  1.到达最右下角节点，直接返回结果</span></span><br><span class="line"><span class="comment">     *  2.res  = min(向右走，向下走)</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">helperMinPath</span><span class="params">(<span class="keyword">int</span>[][] grid,<span class="keyword">int</span> row,<span class="keyword">int</span> col)</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> val = grid[row][col];</span><br><span class="line">    <span class="comment">//走到最右下角点</span></span><br><span class="line">    <span class="keyword">if</span>(row==(grid.length-<span class="number">1</span>)&amp;&amp;col == grid[<span class="number">0</span>].length-<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> grid[row][col];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//走到最后一行或者是最后一列</span></span><br><span class="line">    <span class="keyword">if</span>(row==grid.length-<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> val+helperMinPath(grid,row,col+<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(col == grid[<span class="number">0</span>].length-<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> val+helperMinPath(grid,row+<span class="number">1</span>,col);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//取向下走以及往右走的最小值</span></span><br><span class="line">    <span class="keyword">int</span> down = helperMinPath(grid,row+<span class="number">1</span>,col);</span><br><span class="line">    <span class="keyword">int</span> right = helperMinPath(grid,row,col+<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">return</span> Math.min(down,right)+val;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>实际上，暴力递归有许多计算是重复的，这样造成时间复杂度过高，暴力嘀咕可以转化为动态规划。</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><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></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">minPathSum</span><span class="params">(<span class="keyword">int</span>[][] grid)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(grid.length==<span class="number">0</span>||grid[<span class="number">0</span>].length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> DPMinPath(grid);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">minPathSum</span><span class="params">(<span class="keyword">int</span>[][] grid)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> DPMinpath(grid);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">DPMinpath</span><span class="params">(<span class="keyword">int</span>[][] matrix)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(matrix.length==<span class="number">0</span>||matrix[<span class="number">0</span>].length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> m = matrix.length;</span><br><span class="line">    <span class="keyword">int</span> n = matrix[<span class="number">0</span>].length;</span><br><span class="line">    <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[m][n];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;m;i++)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>;j&lt;n;j++)&#123;</span><br><span class="line">            <span class="keyword">if</span>(i==<span class="number">0</span>&amp;&amp;j==<span class="number">0</span>)&#123;</span><br><span class="line">                dp[i][j] =  matrix[i][j];</span><br><span class="line">            &#125;<span class="keyword">else</span> <span class="keyword">if</span>(i==<span class="number">0</span>)&#123;</span><br><span class="line">                dp[i][j] = dp[i][j-<span class="number">1</span>]+matrix[i][j];</span><br><span class="line">            &#125;<span class="keyword">else</span> <span class="keyword">if</span>(j==<span class="number">0</span>)&#123;</span><br><span class="line">                dp[i][j] = dp[i-<span class="number">1</span>][j]+matrix[i][j];</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                dp[i][j] = Math.min(dp[i-<span class="number">1</span>][j]+matrix[i][j],dp[i][j-<span class="number">1</span>]+matrix[i][j]);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> dp[m-<span class="number">1</span>][n-<span class="number">1</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>使用一维数组</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><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></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">minPathSum</span><span class="params">(<span class="keyword">int</span>[][] grid)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> DPMinpath(grid);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">DPMinpath</span><span class="params">(<span class="keyword">int</span>[][] matrix)</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(matrix.length==<span class="number">0</span>||matrix[<span class="number">0</span>].length==<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> m = matrix.length;</span><br><span class="line">        <span class="keyword">int</span> n = matrix[<span class="number">0</span>].length;</span><br><span class="line">        <span class="keyword">int</span>[] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n];</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;m;i++)&#123;</span><br><span class="line">            <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>;j&lt;n;j++)&#123;</span><br><span class="line">                <span class="keyword">if</span>(i==<span class="number">0</span>&amp;&amp;j==<span class="number">0</span>)&#123;</span><br><span class="line">                    dp[<span class="number">0</span>] =  matrix[i][j];</span><br><span class="line">                &#125;<span class="keyword">else</span> <span class="keyword">if</span>(i==<span class="number">0</span>)&#123;</span><br><span class="line">                    dp[j] = dp[j-<span class="number">1</span>]+matrix[i][j];</span><br><span class="line">                &#125;<span class="keyword">else</span> <span class="keyword">if</span>(j==<span class="number">0</span>)&#123;</span><br><span class="line">                    dp[j] = dp[j]+matrix[i][j];</span><br><span class="line">                &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                    dp[j] = Math.min(dp[j]+matrix[i][j],dp[j-<span class="number">1</span>]+matrix[i][j]);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dp[n-<span class="number">1</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="任意个数字相加等于aim"><a href="#任意个数字相加等于aim" class="headerlink" title="任意个数字相加等于aim?"></a>任意个数字相加等于aim?</h2><p><img src="../images/leetcode%E9%80%92%E5%BD%92%E4%B8%8E%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/1576925330206.png" alt="1576925330206"></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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**第一种是递归方法来解决。每个元素有选择以及不选择两种可能</span></span><br><span class="line"><span class="comment">     * 假如i==arr.length，说明已经走完了最后一个元素，判断sum是否等于aim</span></span><br><span class="line"><span class="comment">     * 对于每一个元素，我们有选择加他或者不加他两种可能</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> arr1：输入的数组</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> i：数组中第几个数据</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> sum</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> aim：目标和</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span>  <span class="keyword">boolean</span> <span class="title">process1</span><span class="params">(<span class="keyword">int</span>[] arr1,<span class="keyword">int</span> i,<span class="keyword">int</span> sum,<span class="keyword">int</span> aim)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(i==arr1.length)&#123;</span><br><span class="line">        <span class="keyword">return</span> sum==aim;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//分为选择该元素以及不选择该元素两种可能</span></span><br><span class="line">    <span class="keyword">return</span> process1(arr1,i+<span class="number">1</span>,sum,aim)||process1(arr1,i+<span class="number">1</span>,sum+arr1[i],aim);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * DP版本</span></span><br><span class="line"><span class="comment">     * 两个可变参数：sum以及i(元素个数)</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span>  <span class="keyword">boolean</span> <span class="title">process1</span><span class="params">(<span class="keyword">int</span>[] arr1,<span class="keyword">int</span> aim)</span></span>&#123;</span><br><span class="line">    <span class="comment">//计算sum范围</span></span><br><span class="line">    <span class="keyword">int</span> sum = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> ele:arr1)&#123;</span><br><span class="line">        sum+=ele;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">boolean</span>[][] dp = <span class="keyword">new</span> <span class="keyword">boolean</span>[arr1.length+<span class="number">1</span>][sum+<span class="number">1</span>];</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * if(i==arr1.length)&#123;</span></span><br><span class="line"><span class="comment">         *    return sum==aim;</span></span><br><span class="line"><span class="comment">         *  &#125;</span></span><br><span class="line"><span class="comment">         *  计算特殊情况</span></span><br><span class="line"><span class="comment">         * */</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;=sum;i++)&#123;</span><br><span class="line">        dp[arr1.length][i] = i==aim?<span class="keyword">true</span>:<span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>;i&lt;arr1.length;i++)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>;j&lt;=sum;j++)&#123;</span><br><span class="line">            dp[i][j] = dp[i+<span class="number">1</span>][j]||dp[i+<span class="number">1</span>][j+arr1[j]];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> dp[<span class="number">0</span>][<span class="number">0</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="53-最大子序和"><a href="#53-最大子序和" class="headerlink" title="53. 最大子序和"></a><a href="https://leetcode-cn.com/problems/maximum-subarray/" target="_blank" rel="noopener">53. 最大子序和</a></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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 集合组成是以i个元素结尾的字段，比如[2,1,-1,4]有四个，分别是以2，1，-1，4结尾的子段</span></span><br><span class="line"><span class="comment">     * f(i) = max(f(i-1),0)+nums[i]，f(i)表示以i作为结尾的子段的所有元素之和</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxSubArray</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(nums.length==<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> nums[<span class="number">0</span>];</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>[nums.length];</span><br><span class="line">    dp[<span class="number">0</span>] = nums[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">int</span> max = dp[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>;i&lt;nums.length;i++)&#123;</span><br><span class="line">        dp[i] = Math.max(dp[i-<span class="number">1</span>],<span class="number">0</span>)+nums[i];</span><br><span class="line">        max = Math.max(max,dp[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="120-三角形最小路径和"><a href="#120-三角形最小路径和" class="headerlink" title="120. 三角形最小路径和"></a><a href="https://leetcode-cn.com/problems/triangle/" target="_blank" rel="noopener">120. 三角形最小路径和</a></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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 特殊情况：col = 0 dp[i][0] = dp[i-1][0]+triangle.get(i).get(0);</span></span><br><span class="line"><span class="comment">     *           每个list中的最后一个元素</span></span><br><span class="line"><span class="comment">     * dp[i][j] = min(dp[i-1][j],dp[i-1][j-1])+当前值</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">minimumTotal</span><span class="params">(List&lt;List&lt;Integer&gt;&gt; triangle)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(triangle==<span class="keyword">null</span>||triangle.size()==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</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>[triangle.size()][triangle.size()];</span><br><span class="line">    dp[<span class="number">0</span>][<span class="number">0</span>] = triangle.get(<span class="number">0</span>).get(<span class="number">0</span>);</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>;i&lt;triangle.size();i++)&#123;</span><br><span class="line">        dp[i][<span class="number">0</span>] = dp[i-<span class="number">1</span>][<span class="number">0</span>]+triangle.get(i).get(<span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>;i&lt;triangle.size();i++)&#123;</span><br><span class="line">        List&lt;Integer&gt; data = triangle.get(i);</span><br><span class="line">        dp[i][data.size()-<span class="number">1</span>] = dp[i-<span class="number">1</span>][data.size()-<span class="number">2</span>]+data.get(data.size()-<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>;i&lt;triangle.size();i++)&#123;</span><br><span class="line">        List&lt;Integer&gt; data = triangle.get(i);</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">1</span>;j&lt;data.size()-<span class="number">1</span>;j++)&#123;</span><br><span class="line">            dp[i][j] = Math.min(dp[i-<span class="number">1</span>][j-<span class="number">1</span>],dp[i-<span class="number">1</span>][j])+data.get(j);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> min = Integer.MAX_VALUE;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;triangle.get(triangle.size()-<span class="number">1</span>).size();i++)&#123;</span><br><span class="line">        min = Math.min(min,dp[triangle.size()-<span class="number">1</span>][i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> min;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="换钱方法数"><a href="#换钱方法数" class="headerlink" title="换钱方法数"></a>换钱方法数</h2><p><img src="/images/leetcode%E9%80%92%E5%BD%92%E4%B8%8E%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/1578623250591.png" alt="1578623250591"></p><p>递归版本</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 假设[5,10,25,1]，targrt = 15</span></span><br><span class="line"><span class="comment">     * 使用0张5元的，剩下的15元在[10,25,1]中凑得。使用1张5元的，剩下的10元在[10,25,1]中凑得。使用两张5元的，剩下的5元在[10,25,1]中凑得。使用3张5元的，剩下0元，不用凑了。</span></span><br><span class="line"><span class="comment">     * 对[10,25,1]继续递归这个过程，直到遍历完这个数组。</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">coinChange</span><span class="params">(<span class="keyword">int</span>[] coins, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> helper(coins,<span class="number">0</span>,target);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">helper</span><span class="params">(<span class="keyword">int</span>[] coins,<span class="keyword">int</span> index,<span class="keyword">int</span> amount)</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//遍历完数组，假如还剩下0元，那么这是一种选择方法</span></span><br><span class="line">    <span class="keyword">if</span>(index==coins.length)&#123;</span><br><span class="line">        <span class="keyword">return</span> amount==<span class="number">0</span>?<span class="number">1</span>:<span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;coins[index]*i&lt;=amount;i++)&#123;</span><br><span class="line">        res+=helper(coins,index+<span class="number">1</span>,amount-coins[index]*i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>动态规划版本：</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使用动态规划来完成，两个变量，index，amount，我们需要求的值是index=0，amount=target</span></span><br><span class="line"><span class="comment">     * 特殊情况：index==coins.length,amount==0?1:0</span></span><br><span class="line"><span class="comment">     * 普通情况：dp[i][j] = dp[index+1][amount-coins[index]]+dp[index+1][amount-coins[index]*2]....</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">coinChange2</span><span class="params">(<span class="keyword">int</span>[] coins, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//定义动态规划数组，index以及amount两个变量</span></span><br><span class="line">    <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[coins.length+<span class="number">1</span>][target+<span class="number">1</span>];</span><br><span class="line">    dp[coins.length][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>;i&lt;=target;i++) &#123;</span><br><span class="line">        dp[coins.length][i] = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=coins.length-<span class="number">1</span>;i&gt;=<span class="number">0</span>;i--)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>;j&lt;=target;j++)&#123;</span><br><span class="line">            <span class="comment">//                for(int k=0;j-coins[i]*k&gt;=0;k++) &#123;</span></span><br><span class="line">            <span class="comment">//                    dp[i][j] += dp[i + 1][j - coins[i]*k];</span></span><br><span class="line">            <span class="comment">//                &#125;</span></span><br><span class="line">            dp[i][j] = dp[i+<span class="number">1</span>][j]+(j-coins[i]&gt;=<span class="number">0</span>?dp[i][j-coins[i]]:<span class="number">0</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> dp[<span class="number">0</span>][target];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="486-纸牌博弈问题"><a href="#486-纸牌博弈问题" class="headerlink" title="486.纸牌博弈问题"></a>486.纸牌博弈问题</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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 暴力递归</span></span><br><span class="line"><span class="comment">     * f(i,j):绝顶聪明的人在arr[i...j]上先拿纸牌，可以获得什么分数</span></span><br><span class="line"><span class="comment">     * s(i,j):绝顶聪明的人在arr[i...j]上后拿纸牌，可以获得什么分数</span></span><br><span class="line"><span class="comment">     * 返回玩家1先拿纸牌的分数以及玩家2后拿纸牌的分数</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">PredictTheWinner</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> first(nums,<span class="number">0</span>,nums.length-<span class="number">1</span>)&gt;second(nums,<span class="number">0</span>,nums.length-<span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 先拿纸牌获取的分数</span></span><br><span class="line"><span class="comment">     * start==end:return nums[start]</span></span><br><span class="line"><span class="comment">     * strat!=end:可以取nums[start]或者是nums[end]，</span></span><br><span class="line"><span class="comment">     *      取nums[start]，那么，在[start+1,end]中后取</span></span><br><span class="line"><span class="comment">     *      取nums[end]，那么，在[start,end-1]中后取</span></span><br><span class="line"><span class="comment">     *      因为他绝顶聪明，所以会选取两个最大值取</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">first</span><span class="params">(<span class="keyword">int</span>[] nums,<span class="keyword">int</span> start ,<span class="keyword">int</span> end)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(start==end)&#123;</span><br><span class="line">        <span class="keyword">return</span> nums[start];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> Math.max(nums[start]+second(nums,start+<span class="number">1</span>,end),nums[end]+second(nums,start,end-<span class="number">1</span>));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 后拿纸牌获取的分数</span></span><br><span class="line"><span class="comment">     * start==end:直接返回0</span></span><br><span class="line"><span class="comment">     * strat!=end:对手可以取nums[start]或者是nums[end]，</span></span><br><span class="line"><span class="comment">     *      对手取nums[start]，那么，玩家就可以在[start+1,end]中先取</span></span><br><span class="line"><span class="comment">     *      对手取nums[end]，那么，玩家就可以在[start,end-1]中先取</span></span><br><span class="line"><span class="comment">     *      因为对手也是绝顶聪明，所以会留取最差的情况给玩家，返回最小值</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">second</span><span class="params">(<span class="keyword">int</span>[] nums,<span class="keyword">int</span> start ,<span class="keyword">int</span> end)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(start==end)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> Math.min(first(nums,start+<span class="number">1</span>,end),first(nums,start,end-<span class="number">1</span>));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 递归改动态规划</span></span><br><span class="line"><span class="comment">     * 需要准备两个动态规划数组，f以及s</span></span><br><span class="line"><span class="comment">     * 两个变量：start，end</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">PredictTheWinner</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(nums.length&lt;=<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span>[][] f = <span class="keyword">new</span> <span class="keyword">int</span>[nums.length][nums.length];</span><br><span class="line">    <span class="keyword">int</span>[][] s = <span class="keyword">new</span> <span class="keyword">int</span>[nums.length][nums.length];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;nums.length;i++)&#123;</span><br><span class="line">        f[i][i] = nums[i];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=nums.length-<span class="number">2</span>;i&gt;=<span class="number">0</span>;i--)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j=i+<span class="number">1</span>;j&lt;nums.length;j++)&#123;</span><br><span class="line">            <span class="keyword">if</span>(i!=j)&#123;</span><br><span class="line">                f[i][j] = Math.max(nums[i]+s[i+<span class="number">1</span>][j],nums[j]+s[i][j-<span class="number">1</span>]);</span><br><span class="line">                s[i][j] = Math.min(f[i+<span class="number">1</span>][j],f[i][j-<span class="number">1</span>]);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> f[<span class="number">0</span>][nums.length-<span class="number">1</span>]&gt;=s[<span class="number">0</span>][nums.length-<span class="number">1</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="机器人达到指定位置"><a href="#机器人达到指定位置" class="headerlink" title="机器人达到指定位置"></a>机器人达到指定位置</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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 机器人到达指定位置方法数</span></span><br><span class="line"><span class="comment">     * N:N个位置</span></span><br><span class="line"><span class="comment">     * M:机器人开始的位置</span></span><br><span class="line"><span class="comment">     * K:需要走的步数</span></span><br><span class="line"><span class="comment">     * P:最终来到的位置</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">walkWay</span><span class="params">(<span class="keyword">int</span> N,<span class="keyword">int</span> M,<span class="keyword">int</span> K,<span class="keyword">int</span> P)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(N&lt;<span class="number">2</span>||M&lt;<span class="number">1</span>||K&lt;<span class="number">1</span>||P&lt;<span class="number">1</span>||M&gt;N||P&gt;N)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> walk(N,M,K,P);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> cur:当前所处的位置</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> rest：剩余的步数</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">walk</span><span class="params">(<span class="keyword">int</span> N,<span class="keyword">int</span> cur,<span class="keyword">int</span> rest,<span class="keyword">int</span> P)</span></span>&#123;</span><br><span class="line">    <span class="comment">//步数走完了，看是否停在了P</span></span><br><span class="line">    <span class="keyword">if</span>(rest==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> cur==P?<span class="number">1</span>:<span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//假如走到了1位置，那么只能向右走</span></span><br><span class="line">    <span class="keyword">if</span>(cur==<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> walk(N,<span class="number">2</span>,rest-<span class="number">1</span>,P);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//假如走到了N位置，那么只能向左走</span></span><br><span class="line">    <span class="keyword">if</span>(cur==N)&#123;</span><br><span class="line">        <span class="keyword">return</span> walk(N,N-<span class="number">1</span>,rest-<span class="number">1</span>,P);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//其他位置，可以向左走向右走</span></span><br><span class="line">    <span class="keyword">return</span> walk(N,cur+<span class="number">1</span>,rest-<span class="number">1</span>,P)+walk(N,cur-<span class="number">1</span>,rest-<span class="number">1</span>,P);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 递归转动态规划</span></span><br><span class="line"><span class="comment">     * 可变参数：cur，rest</span></span><br><span class="line"><span class="comment">     * 返回：dp[M][K]</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">walkWay2</span><span class="params">(<span class="keyword">int</span> N,<span class="keyword">int</span> M,<span class="keyword">int</span> K,<span class="keyword">int</span> P)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(N&lt;<span class="number">2</span>||M&lt;<span class="number">1</span>||K&lt;<span class="number">1</span>||P&lt;<span class="number">1</span>||M&gt;N||P&gt;N)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//K:rest N:cur</span></span><br><span class="line">    <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[K+<span class="number">1</span>][N+<span class="number">1</span>];</span><br><span class="line">    dp[<span class="number">0</span>][P] = <span class="number">1</span>;</span><br><span class="line">    <span class="comment">//因为rest==0时是初始的特殊情况，所以，所有值都应该根据rest==0时求得，所以应该rest值先进性遍历，即&lt;=k</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i =<span class="number">1</span>;i&lt;=K;i++)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">1</span>;j&lt;=N;j++)&#123;</span><br><span class="line">            <span class="keyword">if</span>(j==<span class="number">1</span>)&#123;</span><br><span class="line">                dp[i][j] = dp[i-<span class="number">1</span>][<span class="number">2</span>];</span><br><span class="line">            &#125;<span class="keyword">else</span> <span class="keyword">if</span>(j==N)&#123;</span><br><span class="line">                dp[i][j] = dp[i-<span class="number">1</span>][N-<span class="number">1</span>];</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                dp[i][j] = dp[i-<span class="number">1</span>][j-<span class="number">1</span>]+dp[i-<span class="number">1</span>][j+<span class="number">1</span>];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> dp[K][M];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;0-1背包&quot;&gt;&lt;a href=&quot;#0-1背包&quot; class=&quot;headerlink&quot; title=&quot;0-1背包&quot;&gt;&lt;/a&gt;0-1背包&lt;/h2&gt;&lt;p&gt;有一个&lt;strong&gt;容量为 N&lt;/strong&gt; 的背包，要用&lt;strong&gt;这个背包装下物品的价值最大&lt;/str
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>leetcode贪心策略</title>
    <link href="http://yoursite.com/2019/12/20/leetcode%E8%B4%AA%E5%BF%83%E7%AD%96%E7%95%A5/"/>
    <id>http://yoursite.com/2019/12/20/leetcode贪心策略/</id>
    <published>2019-12-20T13:21:40.000Z</published>
    <updated>2020-01-03T11:35:47.336Z</updated>
    
    <content type="html"><![CDATA[<h2 id="分金条"><a href="#分金条" class="headerlink" title="分金条"></a>分金条</h2><p><img src="../images/leetcode%E8%B4%AA%E5%BF%83%E7%AD%96%E7%95%A5/1576848273437.png" alt="1576848273437"></p><p><strong>这是一种求最小花费的问题</strong>，而且总共的代价是由子代价累加得到的，<strong>可以使用哈夫曼树来解决</strong>。</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><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></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">min_money</span><span class="params">(<span class="keyword">int</span>[] arr)</span></span>&#123;</span><br><span class="line">    <span class="comment">//定义一个小顶堆，每次取出两个最小的元素作为哈夫曼树的构建</span></span><br><span class="line">    PriorityQueue&lt;Integer&gt; data = <span class="keyword">new</span> PriorityQueue&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;arr.length;i++)&#123;</span><br><span class="line">        data.add(arr[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//构建哈夫曼树，每次取出两个最小元素作为合并的两个节点，并将合并的值重新放入堆中</span></span><br><span class="line">    <span class="keyword">int</span> cur = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span>(data.size()&gt;<span class="number">1</span>)&#123;</span><br><span class="line">        cur = data.poll()+data.poll();</span><br><span class="line">        data.add(cur);</span><br><span class="line">        res+= cur;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="502-IPO"><a href="#502-IPO" class="headerlink" title="502. IPO"></a><a href="https://leetcode-cn.com/problems/ipo/" target="_blank" rel="noopener">502. IPO</a></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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</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">Node</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> cost;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> profit;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Node</span><span class="params">(<span class="keyword">int</span> cost,<span class="keyword">int</span> profit)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.cost = cost;</span><br><span class="line">        <span class="keyword">this</span>.profit = profit;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MinHeapComparator</span> <span class="keyword">implements</span> <span class="title">Comparator</span>&lt;<span class="title">Node</span>&gt; </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(Node o1, Node o2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> o1.cost-o2.cost;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MaxHeapComparator</span> <span class="keyword">implements</span> <span class="title">Comparator</span>&lt;<span class="title">Node</span>&gt;</span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(Node o1, Node o2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> o2.profit-o1.profit;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">findMaximizedCapital</span><span class="params">(<span class="keyword">int</span> k, <span class="keyword">int</span> W, <span class="keyword">int</span>[] Profits, <span class="keyword">int</span>[] Capital)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//小顶堆，按照花费排序</span></span><br><span class="line">    PriorityQueue&lt;Node&gt; minCostHeap = <span class="keyword">new</span> PriorityQueue&lt;&gt;(<span class="keyword">new</span> MinHeapComparator());</span><br><span class="line">    <span class="comment">//大顶堆，按照收益排序</span></span><br><span class="line">    PriorityQueue&lt;Node&gt; maxProfitHeap = <span class="keyword">new</span> PriorityQueue&lt;&gt;(<span class="keyword">new</span> MaxHeapComparator());</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;Profits.length;i++)&#123;</span><br><span class="line">        Node node = <span class="keyword">new</span> Node(Capital[i],Profits[i]);</span><br><span class="line">        minCostHeap.add(node);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/***将minCostHeap中所有&lt;=W的元素全部移到MaxProfit中，这样，MaxProfit中存储的就是所有小于总资产的可挑选的项目，</span></span><br><span class="line"><span class="comment">         * 并且按照收益排序，因此，直接获取MaxProfit堆顶元素即可，直到k次项目选择完毕，或者是大顶堆没有元素(没有项目&lt;=手中的资产)*/</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i =<span class="number">0</span>;i&lt;k;i++)&#123;</span><br><span class="line">        <span class="keyword">while</span>(!minCostHeap.isEmpty()&amp;&amp;minCostHeap.peek().cost&lt;=W)&#123;</span><br><span class="line">            maxProfitHeap.add(minCostHeap.poll());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(maxProfitHeap.size()&lt;<span class="number">1</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> W;</span><br><span class="line">        &#125;</span><br><span class="line">        W+=maxProfitHeap.poll().profit;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> W;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="会议室项目宣讲"><a href="#会议室项目宣讲" class="headerlink" title="会议室项目宣讲"></a>会议室项目宣讲</h2><p>一些项目要占用一个会议室宣讲，<strong>会议室不能同时容纳两个项目</strong>的宣讲。 给你每一个项目开始的时间和结束的时间(给你一个数组，里面 是一个个具体的项目)，你来安排宣讲的日程，要求会议室进行 的<strong>宣讲的场次最多</strong>。返回这个最多的宣讲场次。  </p><p>贪心策略：</p><ul><li>开始时间最早的项目先安排。反例：开始时间最早，但持续时间占了一整天，其他项目无法安排。</li><li>持续时间最短的先安排。反例：这样安排会导致结束时间在此期间和开始时间在此期间的所有项目不能安排。</li><li>最优策略：<strong>最先结束的项目先安排</strong>。</li></ul><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></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">Program</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> start;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> end;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Program</span><span class="params">(<span class="keyword">int</span> start,<span class="keyword">int</span> end)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.start = start;</span><br><span class="line">        <span class="keyword">this</span>.end = end;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ProgramComparator</span> <span class="keyword">implements</span> <span class="title">Comparator</span>&lt;<span class="title">Program</span>&gt;</span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(Program o1, Program o2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> o1.end-o2.end;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 以结束时间最早作为贪心策略</span></span><br><span class="line"><span class="comment">     * 因此，每次需要取出大于等于上一次结束时间的且结束时间最小的项目</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">bestArrange</span><span class="params">(Program[] programs, <span class="keyword">int</span> start)</span> </span>&#123;</span><br><span class="line">    Arrays.sort(programs,<span class="keyword">new</span> ProgramComparator());</span><br><span class="line">    <span class="keyword">int</span> result = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;programs.length;i++)&#123;</span><br><span class="line">        <span class="keyword">if</span>(start&lt;=programs[i].start)&#123;</span><br><span class="line">            result++;</span><br><span class="line">            start = programs[i].end;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;分金条&quot;&gt;&lt;a href=&quot;#分金条&quot; class=&quot;headerlink&quot; title=&quot;分金条&quot;&gt;&lt;/a&gt;分金条&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;../images/leetcode%E8%B4%AA%E5%BF%83%E7%AD%96%E7%95%A5/1
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>leetcode哈希表</title>
    <link href="http://yoursite.com/2019/12/19/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/"/>
    <id>http://yoursite.com/2019/12/19/leetcode哈希表/</id>
    <published>2019-12-19T12:23:56.000Z</published>
    <updated>2020-01-11T07:42:10.550Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/1576758278802.png" alt="1576758278802"></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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 需要建立两个Map，mapA=&#123;value,插入顺序&#125;  MapB=&#123;插入顺序,value&#125;</span></span><br><span class="line"><span class="comment"> * */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RandomPool</span>&lt;<span class="title">K</span>&gt; </span>&#123;</span><br><span class="line">    HashMap&lt;K,Integer&gt; mapA = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    HashMap&lt;Integer,K&gt; mapB = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> index = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//插入元素，需要插入两个map</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">insert</span><span class="params">(K key)</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(!mapA.containsKey(key)) &#123;</span><br><span class="line">            mapA.put(key, index);</span><br><span class="line">            mapB.put(index, key);</span><br><span class="line">            index++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//删除元素的时候，假如mapB key在0-25之间，这样，删除某一个元素的话，key就不是均匀分布的，因此，需要从最后一个位置补元素</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">delete</span><span class="params">(K key)</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(mapA.containsKey(key)) &#123;</span><br><span class="line">            <span class="keyword">int</span> del_index = mapA.get(key);</span><br><span class="line">            <span class="keyword">int</span> lastIndex = --index;</span><br><span class="line">            <span class="comment">//将最后一个元素移到删除位置</span></span><br><span class="line">            K lastEle = mapB.get(lastIndex);</span><br><span class="line">            mapA.put(lastEle,del_index);</span><br><span class="line">            mapB.put(del_index,lastEle);</span><br><span class="line">            mapB.remove(lastIndex);</span><br><span class="line">            mapA.remove(key);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//随机等概率获取元素，mapB key在0-index之间，所以Math.random()*index即可返回随机的元素下标</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> K <span class="title">getRandom</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(index==<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> mapB.get((<span class="keyword">int</span>)(Math.random()*index));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="海量数据判重问题"><a href="#海量数据判重问题" class="headerlink" title="海量数据判重问题"></a>海量数据判重问题</h2><p>假如使用哈希表的话，需要存储上亿条级别的数据，十分浪费空间，尽管查询时间复杂度是O(1).</p><p>一般来说，对于这种情况，可以使用布隆过滤器来实现。</p><p>比较巧妙的<strong>概率型数据结构</strong>（probabilistic data structure），特点是高效地插入和查询，可以用来告诉你 <strong>“某样东西一定不存在或者可能存在”</strong>。</p><p>布隆过滤器是一个 bit 向量或者说 bit 数组，长这样：</p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-530c9d4478398718c15632b9aa025c36_hd.jpg" alt="img"></p><p>如果我们要映射一个值到布隆过滤器中，我们需要使用<strong>多个不同的哈希函数</strong>生成<strong>多个哈希值，并对每个生成的哈希值指向的 bit 位置 1</strong>，例如针对值 “baidu” 和三个不同的哈希函数分别生成了哈希值 1、4、7，则上图转变为：</p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-a0ee721daf43f29dd42b7d441b79d227_hd.jpg" alt="img"></p><p>如何判断某一个对象是之前的某一个输入对象呢？</p><p>依旧是将该值进行K个哈希函数的计算，求出映射之后的位置是0还是1，假如<strong>有0的话，那么该值一定不是之前的某一个输入对象</strong>。假如<strong>全是1的话</strong>，也不一定能保证一定就是之前的某一个输入对象，<strong>只是有一定的概率是</strong>。</p><p>过小的布隆过滤器很快所有的 bit 位均为 1，那么查询任何值都会返回“可能存在”，如何确定过滤器大小？</p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-1ed5b79aa7ac2e9cd66c83690fdbfcf0_hd.jpg" alt="img"></p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-1ed5b79aa7ac2e9cd66c83690fdbfcf0_hd-1576763256214.jpg" alt="img"></p><p>其中，n为元素个数，p为容错率。</p><h2 id="一致性哈希"><a href="#一致性哈希" class="headerlink" title="一致性哈希"></a>一致性哈希</h2><p>在处理多台服务器负载均衡的时候，传统的hash方式。</p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-bc6db15378a13b66a1ddaea68979762b_hd.jpg" alt="img"></p><p><strong>虽然可以达到负载均衡的目的</strong>，但是，假如我们需要增加服务器，或者需要移除服务器，就<strong>需要重新hash计算之前缓存的所有数据</strong>，十分不便。</p><p>一致性哈希算法可以解决这个问题，达到高效数据迁移的目的。</p><p>一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环，它的取模法不是对服务器数量进行取模，而是对整个哈希值空间。</p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-fd44ab71c834f3fe458a6f76f3997f98_hd.jpg" alt="img"></p><p>将各个服务器使用Hash进行一个哈希，这样每台机器就能确定其在哈希环上的位置。</p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-509993a49d447b378273e455a095de3c_hd.jpg" alt="img"></p><p>接下来使用如下算法定位数据访问到相应服务器：将数据key使用相同的函数Hash计算出哈希值，并确定此数据在环上的位置，从此位置沿环顺时针“行走”，第一台遇到的服务器就是其应该定位到的服务器。</p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-4fab60735dfae0bf511709e9d337789b_hd.jpg" alt="img"></p><h3 id="一致性Hash算法的容错性和可扩展性"><a href="#一致性Hash算法的容错性和可扩展性" class="headerlink" title="一致性Hash算法的容错性和可扩展性"></a>一致性Hash算法的容错性和可扩展性</h3><p>假如某一个节点宕机，例如C，则只需要将BC之间的数据重新哈希到D上，不需要重哈希全部数据。</p><p>增加节点也是，假如BC间添加一个节点，只需要将B与该节点之间的数据重哈希。</p><p>一致性Hash算法对于节点的增减都只需<strong>重定位环空间中的一小部分数据</strong>，具有较好的容错性和可扩展性。</p><h3 id="数据倾斜问题"><a href="#数据倾斜问题" class="headerlink" title="数据倾斜问题"></a>数据倾斜问题</h3><p>假如机器比较少，可能造成机器在整个环上分布不均匀。例如：</p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-d499324a9aa067915bbb3f5f3416b032_hd.jpg" alt="img"></p><p>解决该问题可以使用虚拟节点机制。</p><p>例如上面的情况，可以为每台服务器计算三个虚拟节点，于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值，于是形成六个虚拟节点：</p><p><img src="/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/v2-0368841e5020dd07f1e67f449b49a1ba_hd.jpg" alt="img"></p><p>同时数据定位算法不变，<strong>只是多了一步虚拟节点到实际节点的映射</strong>，例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。这样就解决了<strong>服务节点少时数据倾斜的问题</strong>。</p><h4 id="200-岛屿数量"><a href="#200-岛屿数量" class="headerlink" title="200. 岛屿数量"></a><a href="https://leetcode-cn.com/problems/number-of-islands/" target="_blank" rel="noopener">200. 岛屿数量</a></h4><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></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">numIslands</span><span class="params">(<span class="keyword">char</span>[][] grid)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(grid.length==<span class="number">0</span>||grid[<span class="number">0</span>].length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> row = grid.length;</span><br><span class="line">    <span class="keyword">int</span> col = grid[<span class="number">0</span>].length;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;row;i++)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>;j&lt;col;j++)&#123;</span><br><span class="line">            <span class="keyword">if</span>(grid[i][j]==<span class="string">'1'</span>)&#123;</span><br><span class="line">                res++;</span><br><span class="line">                infect(grid,i,j,row,col);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">infect</span><span class="params">(<span class="keyword">char</span>[][]grid,<span class="keyword">int</span> i,<span class="keyword">int</span> j,<span class="keyword">int</span> M,<span class="keyword">int</span> N)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(i&lt;<span class="number">0</span>||j&lt;<span class="number">0</span>||i&gt;=M||i&gt;=N||grid[i][j]!=<span class="string">'1'</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> ;</span><br><span class="line">    &#125;</span><br><span class="line">    grid[i][j]=<span class="string">'2'</span>;</span><br><span class="line">    infect(grid,i-<span class="number">1</span>,j,M,N);</span><br><span class="line">    infect(grid,i+<span class="number">1</span>,j,M,N);</span><br><span class="line">    infect(grid,i,j-<span class="number">1</span>,M,N);</span><br><span class="line">    infect(grid,i,j+<span class="number">1</span>,M,N);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;&lt;img src=&quot;/images/leetcode%E5%93%88%E5%B8%8C%E8%A1%A8/1576758278802.png&quot; alt=&quot;1576758278802&quot;&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>leetcode矩阵问题</title>
    <link href="http://yoursite.com/2019/12/17/leetcode%E7%9F%A9%E9%98%B5%E9%97%AE%E9%A2%98/"/>
    <id>http://yoursite.com/2019/12/17/leetcode矩阵问题/</id>
    <published>2019-12-17T05:34:33.000Z</published>
    <updated>2020-01-08T09:19:22.186Z</updated>
    
    <content type="html"><![CDATA[<h4 id="54-螺旋矩阵"><a href="#54-螺旋矩阵" class="headerlink" title="54. 螺旋矩阵"></a><a href="https://leetcode-cn.com/problems/spiral-matrix/" target="_blank" rel="noopener">54. 螺旋矩阵</a></h4><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> List&lt;Integer&gt; result;</span><br><span class="line"><span class="comment">//一圈一圈进行打印，当左上角元素在右下角元素的上方或者右方时结束</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">spiralOrder</span><span class="params">(<span class="keyword">int</span>[][] matrix)</span> </span>&#123;</span><br><span class="line">    result = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    <span class="keyword">if</span>(matrix.length==<span class="number">0</span>||matrix[<span class="number">0</span>].length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> left_row = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> left_col = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> right_row = matrix.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> right_col = matrix[<span class="number">0</span>].length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(left_row&lt;=right_row&amp;&amp;left_col&lt;=right_col)&#123;</span><br><span class="line">        helper(matrix,left_row++,left_col++,right_row--,right_col--);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**打印一圈元素局灶性，这实际上是一个矩形，需要传递该矩形的左上角以及左下角坐标</span></span><br><span class="line"><span class="comment">     * 当两个坐标同行，直接打印</span></span><br><span class="line"><span class="comment">     * 当两个坐标同列，直接打印</span></span><br><span class="line"><span class="comment">     * 两个坐标不同行也不同列：</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">helper</span><span class="params">(<span class="keyword">int</span>[][] matrix,<span class="keyword">int</span> left_row,<span class="keyword">int</span> left_col,<span class="keyword">int</span> right_row,<span class="keyword">int</span> right_col)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(left_row==right_row)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i= left_col;i&lt;=right_col;i++)&#123;</span><br><span class="line">            result.add(matrix[left_row][i]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;<span class="keyword">else</span> <span class="keyword">if</span>(left_col==right_col)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i= left_row;i&lt;=right_row;i++)&#123;</span><br><span class="line">            result.add(matrix[i][left_col]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">int</span> curCol = left_col;</span><br><span class="line">        <span class="keyword">while</span>(curCol!=right_col)&#123;</span><br><span class="line">            result.add(matrix[left_row][curCol]);</span><br><span class="line">            curCol++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> curRow = left_row;</span><br><span class="line">        <span class="keyword">while</span>(curRow!=right_row)&#123;</span><br><span class="line">            result.add(matrix[curRow][right_col]);</span><br><span class="line">            curRow++;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span>(curCol!=left_col)&#123;</span><br><span class="line">            result.add(matrix[right_row][curCol]);</span><br><span class="line">            curCol--;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span>(curRow!=left_row)&#123;</span><br><span class="line">            result.add(matrix[curRow][left_col]);</span><br><span class="line">            curRow--;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="498-对角线遍历"><a href="#498-对角线遍历" class="headerlink" title="498. 对角线遍历"></a><a href="https://leetcode-cn.com/problems/diagonal-traverse/" target="_blank" rel="noopener">498. 对角线遍历</a></h4><p><img src="/images/leetcode%E7%9F%A9%E9%98%B5%E9%97%AE%E9%A2%98/1576572207688.png" alt="1576572207688"></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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 当a点走完最后一个点，可以结束循环</span></span><br><span class="line"><span class="comment">     * 执行完一次对角线打印，坐标变换方式：</span></span><br><span class="line"><span class="comment">     * b：先下，走到底了，再右</span></span><br><span class="line"><span class="comment">     * a：先右，走到最右，再下</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> arr_index= <span class="number">0</span>;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">int</span>[] findDiagonalOrder(<span class="keyword">int</span>[][] matrix) &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(matrix.length==<span class="number">0</span>||matrix[<span class="number">0</span>].length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span>[] result = <span class="keyword">new</span> <span class="keyword">int</span>[matrix.length*matrix[<span class="number">0</span>].length];</span><br><span class="line">    arr_index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">boolean</span> form = <span class="keyword">false</span>;</span><br><span class="line">    <span class="keyword">int</span> row_lenth = matrix.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> col_length = matrix[<span class="number">0</span>].length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> a_row =<span class="number">0</span>,b_row = <span class="number">0</span>,a_col=<span class="number">0</span>,b_col=<span class="number">0</span>;</span><br><span class="line">    <span class="comment">//a到达最后一个节点</span></span><br><span class="line">    <span class="keyword">while</span>(a_row&lt;=row_lenth)&#123;</span><br><span class="line">        helper(matrix,a_row,a_col,b_row,b_col,form,result);</span><br><span class="line">        <span class="keyword">if</span>(a_col&lt;col_length)&#123;</span><br><span class="line">            a_col++;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            a_row++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(b_row&lt;row_lenth)&#123;</span><br><span class="line">            b_row++;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            b_col++;</span><br><span class="line">        &#125;</span><br><span class="line">        form=!form;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 打印一个对角，a为右上角元素，b为左下角元素</span></span><br><span class="line"><span class="comment">     * 因为有左到右以及右到左两种方式交替，所以需要一个form参数</span></span><br><span class="line"><span class="comment">     * 右到左：a_row&gt;=b_row 赋值 移动到做下第一个点:a_row--  a_col--</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">helper</span><span class="params">(<span class="keyword">int</span>[][] matrix,<span class="keyword">int</span> a_row,<span class="keyword">int</span> a_col,<span class="keyword">int</span> b_row,<span class="keyword">int</span> b_col,<span class="keyword">boolean</span> form,<span class="keyword">int</span>[] result)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(form)&#123;</span><br><span class="line">        <span class="keyword">while</span>(a_row&lt;=b_row&amp;&amp;a_col&gt;=b_col)&#123;</span><br><span class="line">            result[arr_index++] = matrix[a_row++][a_col--];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">while</span>(a_row&lt;=b_row&amp;&amp;a_col&gt;=b_col)&#123;</span><br><span class="line">            result[arr_index++] = matrix[b_row--][b_col++];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h4 id=&quot;54-螺旋矩阵&quot;&gt;&lt;a href=&quot;#54-螺旋矩阵&quot; class=&quot;headerlink&quot; title=&quot;54. 螺旋矩阵&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://leetcode-cn.com/problems/spiral-matrix/&quot; target
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>leetcode栈和队列</title>
    <link href="http://yoursite.com/2019/12/16/leetcode%E6%A0%88%E5%92%8C%E9%98%9F%E5%88%97/"/>
    <id>http://yoursite.com/2019/12/16/leetcode栈和队列/</id>
    <published>2019-12-16T11:47:23.000Z</published>
    <updated>2020-01-03T12:32:19.458Z</updated>
    
    <content type="html"><![CDATA[<h3 id="数组实现栈"><a href="#数组实现栈" class="headerlink" title="数组实现栈"></a>数组实现栈</h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//使用index来代表栈顶位置，index=0，栈为空，index = size，栈满</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ArrStack</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span>[] arr;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> index;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">ArrStack</span><span class="params">(<span class="keyword">int</span> size)</span></span>&#123;</span><br><span class="line">        arr = <span class="keyword">new</span> <span class="keyword">int</span>[size];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">push</span><span class="params">(<span class="keyword">int</span> x)</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(index==arr.length)&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> ArrayIndexOutOfBoundsException(<span class="string">"full"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        arr[index++] = x;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span>  <span class="title">pop</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(index==<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> ArrayIndexOutOfBoundsException(<span class="string">"empty"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> arr[--index];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span>  <span class="title">peek</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(index==<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> ArrayIndexOutOfBoundsException(<span class="string">"empty"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> arr[index-<span class="number">1</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isEmpty</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> index==<span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="622-循环队列"><a href="#622-循环队列" class="headerlink" title="622.循环队列"></a>622.循环队列</h3><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</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">MyCircularQueue</span> </span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 记录队头的front，记录队尾的wear，size表示队列大小</span></span><br><span class="line"><span class="comment">     * front指向第一个元素 rear指向最后一个元素后一个位置</span></span><br><span class="line"><span class="comment">     * 入队：arr[rear]=value，rear后移，size++，注意，因为要完成一个循环队列rear+1需要取模运算</span></span><br><span class="line"><span class="comment">     * 出队：font后移取模运算，size--</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> front = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> rear = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> size = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span>[] arr;</span><br><span class="line">    <span class="comment">/** Initialize your data structure here. Set the size of the queue to be k. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MyCircularQueue</span><span class="params">(<span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line">        arr = <span class="keyword">new</span> <span class="keyword">int</span>[size];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** Insert an element into the circular queue. Return true if the operation is successful. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">enQueue</span><span class="params">(<span class="keyword">int</span> value)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(size==arr.length)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        arr[rear] = value;</span><br><span class="line">        rear = (rear +<span class="number">1</span>)%arr.length;</span><br><span class="line">        size++;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** Delete an element from the circular queue. Return true if the operation is successful. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">deQueue</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(size==<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        front = (front++)%arr.length;</span><br><span class="line">        size--;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** Get the front item from the queue. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">Front</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(size==<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(<span class="string">"empty"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> arr[front];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** Get the last item from the queue. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">Rear</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(size==<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(<span class="string">"empty"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> arr[(rear-<span class="number">1</span>)%arr.length];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** Checks whether the circular queue is empty or not. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isEmpty</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> size==<span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** Checks whether the circular queue is full or not. */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isFull</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> size==arr.length;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="155-最小栈"><a href="#155-最小栈" class="headerlink" title="155.最小栈"></a>155.最小栈</h3><p>设计一个支持 push，pop，top 操作，并能在常数时间内检索到最小元素的栈。</p><p>push(x) – 将元素 x 推入栈中。<br>pop() – 删除栈顶的元素。<br>top() – 获取栈顶元素。<br>getMin() – 检索栈中的最小元素。</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">Stack&lt;Integer&gt; data = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">Stack&lt;Integer&gt; min = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">MinStack</span><span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**入栈的时候除了data栈之外，还包括min栈，存储的每一个元素其相应的最小值</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">push</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">    data.push(x);</span><br><span class="line">    <span class="keyword">if</span>(min.isEmpty())&#123;</span><br><span class="line">        min.push(x);</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">int</span> minVal = min.peek();</span><br><span class="line">        <span class="keyword">if</span>(x&lt;minVal)&#123;</span><br><span class="line">            min.push(x);</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            min.push(minVal);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pop</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(!data.isEmpty()) &#123;</span><br><span class="line">        data.pop();</span><br><span class="line">        min.pop();</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> ArrayIndexOutOfBoundsException(<span class="string">"empty"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">top</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">if</span>(!data.isEmpty()) &#123;</span><br><span class="line">        res = data.peek();</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> ArrayIndexOutOfBoundsException(<span class="string">"empty"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getMin</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">if</span>(!min.isEmpty()) &#123;</span><br><span class="line">        res = min.peek();</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> ArrayIndexOutOfBoundsException(<span class="string">"empty"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="255-用队列实现栈"><a href="#255-用队列实现栈" class="headerlink" title="255.用队列实现栈"></a>255.用队列实现栈</h3><p>队列是先进先出的，我们准备两个队列data，helper，data存放入队的数据，pop的时候将前n-1个元素从data出队到helper中，这样data中就只剩下一个最先进队的元素，即可以达到先进后出的目的。</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> Queue&lt;Integer&gt; data = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line"><span class="keyword">private</span> Queue&lt;Integer&gt; helper = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> top;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">MyStack</span><span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** 放入到data队列中 */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">push</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">    data.add(x);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** pop元素的时候，将前n-1个元素放入helper中，只留下最后一个元素，这样，就可以达到栈的目的</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">pop</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(data.size()&gt;<span class="number">1</span>)&#123;</span><br><span class="line">        helper.add(data.remove());</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> res = data.remove();</span><br><span class="line">    swap();</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">swap</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Queue&lt;Integer&gt; tmp = <span class="keyword">this</span>.data;</span><br><span class="line">    <span class="keyword">this</span>.data = <span class="keyword">this</span>.helper;</span><br><span class="line">    <span class="keyword">this</span>.helper = tmp;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/** Get the top element. */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">top</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(data.size()&gt;<span class="number">1</span>)&#123;</span><br><span class="line">        helper.add(data.poll());</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> res = data.poll();</span><br><span class="line">    helper.add(res);</span><br><span class="line">    swap();</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Returns whether the stack is empty. */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">empty</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> data.size()==<span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="232-用栈实现队列"><a href="#232-用栈实现队列" class="headerlink" title="232.用栈实现队列"></a>232.用栈实现队列</h3><p>因为栈是先进后出，因此元素先进去一个栈push，在从该栈push出栈到另一个栈pop，这样，我们从pop中取出元素就可以达到先进先出的目的。</p><p>需要注意的是，元素从push到pop，需要满足两个条件：需要一次性将push栈元素出栈完；当pop中有元素时，不可以入栈。</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><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><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">Stack&lt;Integer&gt; sta_pop = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line"><span class="comment">/** Initialize your data structure here. */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">MyQueue</span><span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Push element x to the back of queue. */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">push</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">    pushtoPop();</span><br><span class="line">    sta_push.push(x);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Removes the element from in front of queue and returns that element. */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">pop</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    pushtoPop();</span><br><span class="line">    <span class="keyword">return</span> sta_pop.pop();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Get the front element. */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">peek</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    pushtoPop();</span><br><span class="line">    <span class="keyword">return</span> sta_pop.peek();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//将元素从push推到pop</span></span><br><span class="line"><span class="comment">//1.一次性推完push中元素 2.pop中为空</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">pushtoPop</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(sta_pop.isEmpty()) &#123;</span><br><span class="line">        <span class="keyword">while</span> (!sta_push.isEmpty()) &#123;</span><br><span class="line">            sta_pop.push(sta_push.pop());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Returns whether the queue is empty. */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">empty</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> sta_pop.isEmpty()&amp;&amp;sta_push.isEmpty();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;数组实现栈&quot;&gt;&lt;a href=&quot;#数组实现栈&quot; class=&quot;headerlink&quot; title=&quot;数组实现栈&quot;&gt;&lt;/a&gt;数组实现栈&lt;/h3&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>leetcode搜索</title>
    <link href="http://yoursite.com/2019/12/11/leetcode%E6%90%9C%E7%B4%A2/"/>
    <id>http://yoursite.com/2019/12/11/leetcode搜索/</id>
    <published>2019-12-11T07:56:15.000Z</published>
    <updated>2019-12-15T06:56:07.741Z</updated>
    
    <content type="html"><![CDATA[<p>BFS：需要记录两层的节点，空间复杂度是指数级别的。O(2^h)，queue</p><p>DFS：空间复杂度为树的深度。O(h)，stack</p><p>BFS空间复杂度比较高，但是可以搜索最小性质。</p><table><thead><tr><th></th><th>空间复杂度</th><th>数据结构</th><th></th></tr></thead><tbody><tr><td>DFS</td><td>O(h)，h为树的高度</td><td>stack</td><td></td></tr><tr><td>BFS</td><td>O(2^h)，指数级别的</td><td>queue</td><td>可以求出最短路的问题(边的权重是1)</td></tr></tbody></table><p><img src="/images/leetcode%E6%90%9C%E7%B4%A2/1576072859183.png" alt="1576072859183"></p><h3 id="111-二叉树最小深度"><a href="#111-二叉树最小深度" class="headerlink" title="111.二叉树最小深度"></a>111.二叉树最小深度</h3><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></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">minDepth</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> helper(root);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 左右节点均不为空使，返回min(left,right)+1</span></span><br><span class="line"><span class="comment">     * 左右节点只有一个为空（left==null）时，需要返回right+1，而不是返回min(lef,right)+1</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">helper</span><span class="params">(TreeNode root)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> left = helper(root.left);</span><br><span class="line">    <span class="keyword">int</span> right = helper(root.right);</span><br><span class="line">    <span class="keyword">if</span>(root.left==<span class="keyword">null</span>||root.right==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> left+right+<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> Math.min(left,right)+<span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="279-完全平方数"><a href="#279-完全平方数" class="headerlink" title="279.完全平方数"></a>279.完全平方数</h3><p>给定正整数 <em>n</em>，找到若干个完全平方数（比如 <code>1, 4, 9, 16, ...</code>）使得它们的和等于 <em>n</em>。你需要让组成和的完全平方数的个数最少。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;BFS：需要记录两层的节点，空间复杂度是指数级别的。O(2^h)，queue&lt;/p&gt;
&lt;p&gt;DFS：空间复杂度为树的深度。O(h)，stack&lt;/p&gt;
&lt;p&gt;BFS空间复杂度比较高，但是可以搜索最小性质。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>leetcode树</title>
    <link href="http://yoursite.com/2019/12/07/leetcode%E6%A0%91/"/>
    <id>http://yoursite.com/2019/12/07/leetcode树/</id>
    <published>2019-12-07T11:08:09.000Z</published>
    <updated>2020-01-05T03:03:45.626Z</updated>
    
    <content type="html"><![CDATA[<p>a搜索二叉树：左子树小于根节点，右子树大于根节点。</p><p>平衡树：左右子树高度差不大于1</p><p>一般解决二叉树的问题采用<strong>递归以及递归转非递归</strong>的方法。</p><h3 id="98-验证二叉搜索树"><a href="#98-验证二叉搜索树" class="headerlink" title="98.验证二叉搜索树?"></a>98.验证二叉搜索树?</h3><ul><li>节点的左子树只包含<strong>小于</strong>当前节点的数。</li><li>节点的右子树只包含<strong>大于</strong>当前节点的数。</li><li>所有左子树和右子树自身必须也是二叉搜索树。</li></ul><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">左子树的所有点应该在(minVal,root),右子树在(root,maxVal)</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isValidBST</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> helper(root,Long.MIN_VALUE,Long.MAX_VALUE);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">helper</span><span class="params">(TreeNode root,<span class="keyword">long</span> minVal,<span class="keyword">long</span> maxVal)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(root.val&lt;=minVal||root.val&gt;=maxVal)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> helper(root.left,minVal,root.val)&amp;&amp;helper(root.right,root.val,maxVal);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>还有一种做法：中序遍历结果是递增的，即为二叉搜索树</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isValidBST</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">boolean</span> isRoot = <span class="keyword">true</span>;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">int</span> last = Integer.MIN_VALUE;</span><br><span class="line">    <span class="keyword">while</span>(!stack.isEmpty()||root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">while</span>(root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            stack.push(root);</span><br><span class="line">            root = root.left;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(!stack.isEmpty())&#123;</span><br><span class="line">            TreeNode node = stack.pop();</span><br><span class="line">            <span class="keyword">if</span>(isRoot)&#123;</span><br><span class="line">                last = node.val;</span><br><span class="line">                isRoot = <span class="keyword">false</span>;</span><br><span class="line">            &#125;<span class="keyword">else</span> <span class="keyword">if</span>(node.val&gt;last)&#123;</span><br><span class="line">                last = node.val;</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//dayin</span></span><br><span class="line">            root = node.right;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="144-前序非递归遍历"><a href="#144-前序非递归遍历" class="headerlink" title="144.前序非递归遍历"></a>144.前序非递归遍历</h3><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">preorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    List&lt;Integer&gt; result = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">while</span>(!stack.isEmpty()||root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">while</span>(root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            stack.push(root);</span><br><span class="line">            result.add(root.val);</span><br><span class="line">            root = root.left;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(!stack.isEmpty()) &#123;</span><br><span class="line">            TreeNode node = stack.pop();</span><br><span class="line">            root = node.right;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="94-中序非递归遍历"><a href="#94-中序非递归遍历" class="headerlink" title="94.中序非递归遍历"></a>94.中序非递归遍历</h3><p>1.将整棵树的左子树压入栈中</p><p>2.每次取出栈顶元素，如果他有右子树，则将右子树压入栈中。</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 将root的最左的元素全部压入栈，当root==null，表示压到底了，最左侧已经没有元素了，此时，可以将栈顶元素取出</span></span><br><span class="line"><span class="comment">     * 并开始对右子树做同样操作</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">inorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    List&lt;Integer&gt; result = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">while</span>(!stack.isEmpty()||root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">while</span> (root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            stack.push(root);</span><br><span class="line">            root = root.left;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(!stack.isEmpty())&#123;</span><br><span class="line">            TreeNode node = stack.pop();</span><br><span class="line">            result.add(node.val);</span><br><span class="line">            root = node.right;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="144-后序非递归"><a href="#144-后序非递归" class="headerlink" title="144.后序非递归"></a>144.后序非递归</h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 前序根右左，反转为左右根即可</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> List&lt;Integer&gt; <span class="title">postorderTraversal</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    List&lt;Integer&gt; result = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">while</span>(!stack.isEmpty()||root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">while</span>(root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            result.add(<span class="number">0</span>,root.val);</span><br><span class="line">            stack.push(root);</span><br><span class="line">            root = root.right;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(!stack.isEmpty())&#123;</span><br><span class="line">            TreeNode node = stack.pop();</span><br><span class="line">            root = node.left;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="101-对称二叉树"><a href="#101-对称二叉树" class="headerlink" title="101.对称二叉树?"></a>101.对称二叉树?</h3><p>例如，二叉树 <code>[1,2,2,3,4,4,3]</code> 是对称的。</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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">    1</span><br><span class="line">   / \</span><br><span class="line">  2   2</span><br><span class="line"> / \ / \</span><br><span class="line">3  4 4  3</span><br></pre></td></tr></table></figure><p>递归做法</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 两个根节点值相等</span></span><br><span class="line"><span class="comment">     * 左边的左子树和右边的右子树相等</span></span><br><span class="line"><span class="comment">     * 左边的右子树和右边的左子树相等</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isSymmetric</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//一般二叉树的题目首先判断是否null</span></span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> helper(root,root);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">helper</span><span class="params">(TreeNode p,TreeNode q)</span></span>&#123;</span><br><span class="line">    <span class="comment">// 两个节点同时为空，返回true 只有一个节点为空，返回false</span></span><br><span class="line">    <span class="keyword">if</span>(p==<span class="keyword">null</span>||q==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> p==<span class="keyword">null</span>&amp;&amp;q==<span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> p.val==q.val&amp;&amp;helper(p.left,q.right)&amp;&amp;helper(p.right,q.left);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>非递归方法</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><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><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     *对称树的话，对于根节点的左右子树分别进行左根右以及右左根应该是相同的</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isSymmetric</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> inOrder(root.left,root.right);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">inOrder</span><span class="params">(TreeNode left ,TreeNode right)</span></span>&#123;</span><br><span class="line">    Stack&lt;TreeNode&gt; s_left = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    Stack&lt;TreeNode&gt; s_right = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">while</span> (left!=<span class="keyword">null</span>||right!=<span class="keyword">null</span>||!s_left.isEmpty()||!s_right.isEmpty())&#123;</span><br><span class="line">        <span class="keyword">while</span>(left!=<span class="keyword">null</span>&amp;&amp;right!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            s_left.push(left);</span><br><span class="line">            s_right.push(right);</span><br><span class="line">            left = left.left;</span><br><span class="line">            right = right.right;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//假如left与right不等，表明左子树个数不一样，必定不同</span></span><br><span class="line">        <span class="keyword">if</span>(left!=right)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span>(s_left!=<span class="keyword">null</span>&amp;&amp;s_right!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            TreeNode leftnode = s_left.pop();</span><br><span class="line">            TreeNode rightnode = s_right.pop();</span><br><span class="line">            <span class="keyword">if</span>(leftnode.val!=rightnode.val)&#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            left = leftnode.right;</span><br><span class="line">            right = rightnode.left;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="105-从前序和中序遍历序列构造二叉树"><a href="#105-从前序和中序遍历序列构造二叉树" class="headerlink" title="105.从前序和中序遍历序列构造二叉树"></a>105.从前序和中序遍历序列构造二叉树</h3><p>递归的方法</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">buildTree</span><span class="params">(<span class="keyword">int</span>[] preorder, <span class="keyword">int</span>[] midorder)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//设置一个map存储索引位置，查询方便</span></span><br><span class="line">    HashMap&lt;Integer,Integer&gt; midorder_index = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;midorder.length;i++)&#123;</span><br><span class="line">        midorder_index.put(midorder[i],i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> helper(preorder,midorder,<span class="number">0</span>,preorder.length-<span class="number">1</span>,<span class="number">0</span>,preorder.length-<span class="number">1</span>,midorder_index);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * preorder[p_start]是根节点，这样就可以找到preorder[p_start]在中序遍历中的位置，这样，就可以获得左子树以及右子树的范围，接着递归来做</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">helper</span><span class="params">(<span class="keyword">int</span>[] preorder , <span class="keyword">int</span>[] midorder, <span class="keyword">int</span> p_start, <span class="keyword">int</span> p_end, <span class="keyword">int</span> m_start, <span class="keyword">int</span> m_end, Map&lt;Integer,Integer&gt; midorder_index)</span></span>&#123;</span><br><span class="line">    <span class="comment">//此时没有元素了，直接返回null</span></span><br><span class="line">    <span class="keyword">if</span>(p_start&gt;p_end)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//获取根节点</span></span><br><span class="line">    <span class="keyword">int</span> root_val = preorder[p_start];</span><br><span class="line">    TreeNode root = <span class="keyword">new</span> TreeNode(root_val);</span><br><span class="line">    <span class="keyword">int</span> index = midorder_index.get(root_val);</span><br><span class="line">    <span class="comment">//左子树的长度</span></span><br><span class="line">    <span class="keyword">int</span> length = index - m_start;</span><br><span class="line">    root.left = helper(preorder,midorder,p_start+<span class="number">1</span>,p_start+length,m_start,index-<span class="number">1</span>,midorder_index);</span><br><span class="line">    root.right = helper(preorder,midorder,p_start+length+<span class="number">1</span>,p_end,index+<span class="number">1</span>,m_end,midorder_index);</span><br><span class="line">    <span class="keyword">return</span> root;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="106-从中序与后序遍历序列构造二叉树"><a href="#106-从中序与后序遍历序列构造二叉树" class="headerlink" title="106. 从中序与后序遍历序列构造二叉树"></a><a href="https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/" target="_blank" rel="noopener">106. 从中序与后序遍历序列构造二叉树</a></h4><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">buildTree</span><span class="params">(<span class="keyword">int</span>[] inorder, <span class="keyword">int</span>[] postorder)</span> </span>&#123;</span><br><span class="line">    Map&lt;Integer,Integer&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;inorder.length;i++)&#123;</span><br><span class="line">        map.put(inorder[i],i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> helper3(inorder,postorder,<span class="number">0</span>,inorder.length-<span class="number">1</span>,<span class="number">0</span>,inorder.length-<span class="number">1</span>,map);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">helper3</span><span class="params">(<span class="keyword">int</span>[] inorder, <span class="keyword">int</span>[] postorder,<span class="keyword">int</span> i_start,<span class="keyword">int</span> i_end,<span class="keyword">int</span> p_start,<span class="keyword">int</span> p_end,Map&lt;Integer,Integer&gt; map)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(i_start&gt;i_end)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(i_start==i_end)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> TreeNode(postorder[p_start]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> root_val = postorder[p_end];</span><br><span class="line">    <span class="keyword">int</span> index = map.get(root_val);</span><br><span class="line">    <span class="keyword">int</span> length = index - i_start;</span><br><span class="line">    TreeNode root = <span class="keyword">new</span> TreeNode(root_val);</span><br><span class="line">    root.left = helper3(inorder,postorder,i_start,index-<span class="number">1</span>,p_start,p_start+length-<span class="number">1</span>,map);</span><br><span class="line">    root.right = helper3(inorder,postorder,index+<span class="number">1</span>,i_end,p_start+length,p_end-<span class="number">1</span>,map);</span><br><span class="line">    <span class="keyword">return</span> root;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="889-根据前序和后序遍历构造二叉树"><a href="#889-根据前序和后序遍历构造二叉树" class="headerlink" title="889. 根据前序和后序遍历构造二叉树"></a>889. 根据前序和后序遍历构造二叉树</h3><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">constructFromPrePost</span><span class="params">(<span class="keyword">int</span>[] pre, <span class="keyword">int</span>[] post)</span> </span>&#123;</span><br><span class="line">    Map&lt;Integer,Integer&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;pre.length;i++)&#123;</span><br><span class="line">        map.put(post[i],i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> helper2(pre,post,<span class="number">0</span>,pre.length-<span class="number">1</span>,<span class="number">0</span>,pre.length-<span class="number">1</span>,map);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">helper2</span><span class="params">(<span class="keyword">int</span>[] pre, <span class="keyword">int</span>[] post, <span class="keyword">int</span> pre_start, <span class="keyword">int</span> pre_end, <span class="keyword">int</span> post_start, <span class="keyword">int</span> post_end, Map&lt;Integer,Integer&gt; map)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(pre_start&gt;pre_end)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(pre_start==pre_end)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> TreeNode(pre[pre_start]);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> root_val = pre[pre_start];</span><br><span class="line">    <span class="keyword">int</span> left_val = pre[pre_start+<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">int</span> index = map.get(left_val);</span><br><span class="line">    TreeNode root = <span class="keyword">new</span> TreeNode(root_val);</span><br><span class="line">    <span class="keyword">int</span> length = index-post_start;</span><br><span class="line">    root.left = helper2(pre,post,pre_start+<span class="number">1</span>,pre_start+<span class="number">1</span>+length,post_start,index,map);</span><br><span class="line">    root.right  = helper2(pre,post,pre_start+<span class="number">1</span>+length+<span class="number">1</span>,pre_end,index+<span class="number">1</span>,post_end-<span class="number">1</span>,map);</span><br><span class="line">    <span class="keyword">return</span> root;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="102-二叉树层次遍历"><a href="#102-二叉树层次遍历" class="headerlink" title="102.二叉树层次遍历?"></a>102.二叉树层次遍历?</h3><p>通过队列来解决</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; levelOrder(TreeNode root) &#123;</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; result = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">    Queue&lt;TreeNode&gt; queue = <span class="keyword">new</span> LinkedList&lt;TreeNode&gt;();</span><br><span class="line">    queue.add(root);</span><br><span class="line">    <span class="keyword">while</span>(queue.size()&gt;<span class="number">0</span>)&#123;</span><br><span class="line">        List&lt;Integer&gt; vals = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        <span class="keyword">int</span> size = queue.size();</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;size;i++)&#123;</span><br><span class="line">            TreeNode node = queue.remove();</span><br><span class="line">            vals.add(node.val);</span><br><span class="line">            <span class="keyword">if</span>(node.left!=<span class="keyword">null</span>) &#123;</span><br><span class="line">                queue.add(node.left);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span>(node.right!=<span class="keyword">null</span>) &#123;</span><br><span class="line">                queue.add(node.right);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        result.add(vals);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="236-二叉树的最近公共祖先"><a href="#236-二叉树的最近公共祖先" class="headerlink" title="236.二叉树的最近公共祖先?"></a>236.二叉树的最近公共祖先?</h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 后序遍历二叉树。</span></span><br><span class="line"><span class="comment">     * 左子树返回不为空，右子树返回不为空，则该node必定是公共祖先</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">lowestCommonAncestor</span><span class="params">(TreeNode root, TreeNode p, TreeNode q)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//当前节点==p或者==q，那么该点必定是祖先</span></span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>||root==p||root==q)&#123;</span><br><span class="line">        <span class="keyword">return</span> root;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//递归左右子树</span></span><br><span class="line">    TreeNode left = lowestCommonAncestor(root.left,p,q);</span><br><span class="line">    TreeNode right = lowestCommonAncestor(root.right,p,q);</span><br><span class="line">    <span class="comment">//假如左右子树返回均不为空，那么当前节点就是公共祖先</span></span><br><span class="line">    <span class="keyword">if</span>(left!=<span class="keyword">null</span>&amp;&amp;right!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> root;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//只有一个子树返回的不是空</span></span><br><span class="line">    <span class="keyword">return</span> left!=<span class="keyword">null</span>?left:right;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="543-二叉树的直径"><a href="#543-二叉树的直径" class="headerlink" title="543.二叉树的直径"></a>543.二叉树的直径</h3><p>给定一棵二叉树，你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过根结点。</p><p>示例 :<br>给定二叉树</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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">    1</span><br><span class="line">   / \</span><br><span class="line">  2   3</span><br><span class="line"> / \     </span><br><span class="line">4   5</span><br></pre></td></tr></table></figure><p>返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 某一个节点的直径=左子树深度+右子树深度</span></span><br><span class="line"><span class="comment">     * 树的深度 = max(左子树深度,右子树深度)+1</span></span><br><span class="line"><span class="comment">     * 因为要求任意两个节点的直径，所以还需要一个ans记录当前直径的最大值</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="keyword">int</span> ans = <span class="number">0</span>;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">diameterOfBinaryTree</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    helper(root);</span><br><span class="line">    <span class="keyword">return</span> ans;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//helper返回的是树的深度，而直径最大值采用ans来记录</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">helper</span><span class="params">(TreeNode root)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//左右子树的深度</span></span><br><span class="line">    <span class="keyword">int</span> left = helper(root.left);</span><br><span class="line">    <span class="keyword">int</span> right = helper(root.right);</span><br><span class="line">    <span class="comment">//计算该点的直径，并与最大直径比较</span></span><br><span class="line">    <span class="keyword">int</span> zhijing = left+right;</span><br><span class="line">    ans = zhijing&gt;ans?zhijing:ans;</span><br><span class="line">    <span class="comment">//返回树的深度</span></span><br><span class="line">    <span class="keyword">return</span> (left&gt;right?left:right)+<span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="124-二叉树中最大路径和"><a href="#124-二叉树中最大路径和" class="headerlink" title="124.二叉树中最大路径和"></a>124.二叉树中最大路径和</h3><p>给定一个非空二叉树，返回其最大路径和。</p><p>本题中，路径被定义为一条从树中任意节点出发，达到任意节点的序列。该路径至少包含一个节点，且不一定经过根节点。</p><p>示例 2:</p><p>输入: [-10,9,20,null,null,15,7]</p><p>   -10<br>   / <br>  9  20<br>    /  <br>   15   7</p><p>输出: 42</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> res=Integer.MIN_VALUE;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxPathSum</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> helper(root);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">helper</span><span class="params">(TreeNode root)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> left = helper(root.left);</span><br><span class="line">    <span class="keyword">int</span> right = helper(root.right);</span><br><span class="line">    <span class="keyword">int</span> root_res = left+right+root.val;</span><br><span class="line">    res = Math.max(root_res,res);</span><br><span class="line">    <span class="keyword">return</span> Math.max(<span class="number">0</span>,Math.max(left,right)+root.val);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="173-二叉搜索树迭代器"><a href="#173-二叉搜索树迭代器" class="headerlink" title="173.二叉搜索树迭代器"></a>173.二叉搜索树迭代器</h3><p>可以用中序遍历来解决，但是要求空间复杂度为O(h)，h为树的深度。</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><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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BSTIterator</span> </span>&#123;</span><br><span class="line">    Stack&lt;TreeNode&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">BSTIterator</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">while</span>(root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            stack.push(root);</span><br><span class="line">            root = root.left;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** <span class="doctag">@return</span> the next smallest number */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">next</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        TreeNode node = stack.pop();</span><br><span class="line">        <span class="keyword">int</span> res = node.val;</span><br><span class="line">        node = node.right;</span><br><span class="line">        <span class="keyword">while</span>(node!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            stack.push(node);</span><br><span class="line">            node = node.left;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** <span class="doctag">@return</span> whether we have a next smallest number */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">hasNext</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> !stack.isEmpty();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="285-后继节点问题"><a href="#285-后继节点问题" class="headerlink" title="285.后继节点问题"></a>285.后继节点问题</h3><p><img src="/images/leetcode%E6%A0%91/1576680169342.png" alt="1576680169342"></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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 中序遍历：左根右</span></span><br><span class="line"><span class="comment">     * 所以，假如该节点有右子树，那么后继节点是右子树的最左一个节点</span></span><br><span class="line"><span class="comment">     * 假如该节点没有右子树，那么他一定是某一个节点p的左子树的最右节点，因此该节点后继节点就是p</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">getSuccessorNode</span><span class="params">(TreeNode node)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(node==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(node.right!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> getRightMostLeft(node.right);</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        TreeNode parent = node.parent;</span><br><span class="line">        <span class="keyword">while</span>(parent!=<span class="keyword">null</span>&amp;&amp;parent.left!=node)&#123;</span><br><span class="line">            node = node.parent;</span><br><span class="line">            parent = node.parent;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> parent;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">getRightMostLeft</span><span class="params">(TreeNode node)</span></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(node.left!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        node = node.left;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> node;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="297-二叉树的序列化与反序列化"><a href="#297-二叉树的序列化与反序列化" class="headerlink" title="297. 二叉树的序列化与反序列化"></a><a href="https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/" target="_blank" rel="noopener">297. 二叉树的序列化与反序列化</a></h3><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">serialize</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"#!"</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    String res = root.val+<span class="string">"!"</span>;</span><br><span class="line">    res += serialize(root.left);</span><br><span class="line">    res+= serialize(root.right);</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Decodes your encoded data to tree.</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">deserialize</span><span class="params">(String data)</span> </span>&#123;</span><br><span class="line">    String[] values = data.split(<span class="string">"!"</span>);</span><br><span class="line">    Queue&lt;String&gt; queue = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span>(String s:values)&#123;</span><br><span class="line">        queue.add(s);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> recoverFromPre(queue);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">recoverFromPre</span><span class="params">(Queue&lt;String&gt; queue)</span></span>&#123;</span><br><span class="line">    String value = queue.poll();</span><br><span class="line">    <span class="keyword">if</span>(value.equals(<span class="string">"#"</span>))&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        TreeNode root = <span class="keyword">new</span> TreeNode(Integer.parseInt(value));</span><br><span class="line">        root.left = recoverFromPre(queue);</span><br><span class="line">        root.right = recoverFromPre(queue);</span><br><span class="line">        <span class="keyword">return</span> root;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>层次遍历</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">serialize</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"#!"</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    StringBuilder res=  <span class="keyword">new</span> StringBuilder(root.val+<span class="string">"!"</span>);</span><br><span class="line">    Queue&lt;TreeNode&gt; queue = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">    queue.add(root);</span><br><span class="line">    <span class="keyword">while</span>(queue.size()&gt;<span class="number">0</span>)&#123;</span><br><span class="line">        TreeNode node = queue.poll();</span><br><span class="line">        <span class="keyword">if</span>(node.left!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            queue.add(node.left);</span><br><span class="line">            res.append(node.left.val+<span class="string">"!"</span>);</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            res.append(<span class="string">"#!"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(node.right!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            queue.add(node.right);</span><br><span class="line">            res.append(node.right.val+<span class="string">"!"</span>);</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            res.append(<span class="string">"#!"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res.toString();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Decodes your encoded data to tree.</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">deserialize</span><span class="params">(String data)</span> </span>&#123;</span><br><span class="line">    String[] values = data.split(<span class="string">"!"</span>);</span><br><span class="line">    <span class="keyword">int</span> index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">if</span>(values[<span class="number">0</span>].equals(<span class="string">"#"</span>))&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Queue&lt;TreeNode&gt; queue = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">    TreeNode root = <span class="keyword">new</span> TreeNode(Integer.parseInt(values[index++]));</span><br><span class="line">    queue.add(root);</span><br><span class="line">    <span class="keyword">while</span>(queue.size()&gt;<span class="number">0</span>)&#123;</span><br><span class="line">        TreeNode node =  queue.poll();</span><br><span class="line">        String s_left = values[index++];</span><br><span class="line">        String s_right = values[index++];</span><br><span class="line">        <span class="keyword">if</span>(s_left.equals(<span class="string">"#"</span>))&#123;</span><br><span class="line">            node.left = <span class="keyword">null</span>;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            node.left = <span class="keyword">new</span> TreeNode(Integer.parseInt(s_left));</span><br><span class="line">            queue.add(node.left);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(s_right.equals(<span class="string">"#"</span>))&#123;</span><br><span class="line">            node.right = <span class="keyword">null</span>;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            node.right = <span class="keyword">new</span> TreeNode(Integer.parseInt(s_right));</span><br><span class="line">            queue.add(node.right);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> root;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="110-平衡二叉树"><a href="#110-平衡二叉树" class="headerlink" title="110. 平衡二叉树"></a><a href="https://leetcode-cn.com/problems/balanced-binary-tree/" target="_blank" rel="noopener">110. 平衡二叉树</a></h3><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isBalanced</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    isBalance = <span class="keyword">true</span>;</span><br><span class="line">    healperBalance(root);</span><br><span class="line">    <span class="keyword">return</span> isBalance;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">boolean</span> isBalance = <span class="keyword">true</span>;</span><br><span class="line"><span class="comment">//返回树的高度</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span>  <span class="title">healperBalance</span><span class="params">(TreeNode root)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> left = healperBalance(root.left);</span><br><span class="line">    <span class="keyword">int</span> right = healperBalance(root.right);</span><br><span class="line">    <span class="keyword">if</span>(Math.abs(left-right)&gt;<span class="number">1</span>)&#123;</span><br><span class="line">        isBalance = <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> Math.max(left,right)+<span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="958-完全二叉树"><a href="#958-完全二叉树" class="headerlink" title="958. 完全二叉树"></a><a href="https://leetcode-cn.com/problems/check-completeness-of-a-binary-tree/" target="_blank" rel="noopener">958. 完全二叉树</a></h3><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 层序遍历，设置一个停止标志，遇到空节点，停止标志为真，如果停止标志为真，再遍历遇到非空节点，则非完全二叉树。</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isCompleteTree</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//当遇到第一个空节点时，将firstFull设置为true，假如是完全二叉树，后面所有节点都应该是空节点，不会再遇到非空节点</span></span><br><span class="line">    <span class="keyword">boolean</span> firstNull = <span class="keyword">false</span>;</span><br><span class="line">    Queue&lt;TreeNode&gt; queue = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">    queue.add(root);</span><br><span class="line">    <span class="keyword">while</span>(queue.size()&gt;<span class="number">0</span>) &#123;</span><br><span class="line">        TreeNode node = queue.poll();</span><br><span class="line">        <span class="keyword">if</span> (node.left != <span class="keyword">null</span>) &#123;</span><br><span class="line">            queue.add(node.left);</span><br><span class="line">            <span class="comment">//假如firstNull==true，该非空节点前面有一个空节点，必定不是完全二叉树</span></span><br><span class="line">            <span class="keyword">if</span> (firstNull) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">//第一个非空节点，记录标志</span></span><br><span class="line">            <span class="keyword">if</span> (!firstNull) &#123;</span><br><span class="line">                firstNull = <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (node.right != <span class="keyword">null</span>) &#123;</span><br><span class="line">            queue.add(node.right);</span><br><span class="line">            <span class="keyword">if</span> (firstNull) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (!firstNull) &#123;</span><br><span class="line">                firstNull = <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="222-完全二叉树的节点个数"><a href="#222-完全二叉树的节点个数" class="headerlink" title="222. 完全二叉树的节点个数?"></a><a href="https://leetcode-cn.com/problems/count-complete-tree-nodes/" target="_blank" rel="noopener">222. 完全二叉树的节点个数?</a></h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 寻找root右子树的最左节点，假如该节点位于最后一层，那么root的左子树必定是满二叉树，可以计算出节点个数，对于右子树，继续递归</span></span><br><span class="line"><span class="comment">     * 假如该节点位于倒数第二层，那么右子树是满二叉树，同理可计算</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> height = <span class="number">0</span>;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">countNodes</span><span class="params">(TreeNode root)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    height = getHeight(root,<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">return</span> helpCount(root,<span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getHeight</span><span class="params">(TreeNode root,<span class="keyword">int</span> level)</span></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(root!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        level++;</span><br><span class="line">        root = root.left;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> level-<span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">helpCount</span><span class="params">(TreeNode root,<span class="keyword">int</span> level)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(level==height)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//获取右子树最左节点的层数</span></span><br><span class="line">    <span class="keyword">int</span> leftMostheight = getHeight(root.right,level+<span class="number">1</span>);</span><br><span class="line">    <span class="comment">//最左节点位于最后一层，左子树是满二叉树</span></span><br><span class="line">    <span class="keyword">if</span>(leftMostheight==height)&#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="number">1</span>&lt;&lt;(height-level))+helpCount(root.right,level+<span class="number">1</span>);</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="number">1</span>&lt;&lt;(height-level-<span class="number">1</span>))+helpCount(root.left,level+<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>不判断root==null</li><li>||以及&amp;&amp;的问题</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;a搜索二叉树：左子树小于根节点，右子树大于根节点。&lt;/p&gt;
&lt;p&gt;平衡树：左右子树高度差不大于1&lt;/p&gt;
&lt;p&gt;一般解决二叉树的问题采用&lt;strong&gt;递归以及递归转非递归&lt;/strong&gt;的方法。&lt;/p&gt;
&lt;h3 id=&quot;98-验证二叉搜索树&quot;&gt;&lt;a href=&quot;#98-
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>leetcode数据结构</title>
    <link href="http://yoursite.com/2019/12/06/leetcode%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    <id>http://yoursite.com/2019/12/06/leetcode数据结构/</id>
    <published>2019-12-06T07:51:40.000Z</published>
    <updated>2020-01-11T10:52:46.714Z</updated>
    
    <content type="html"><![CDATA[<h2 id="单调栈"><a href="#单调栈" class="headerlink" title="单调栈"></a>单调栈</h2><p>单调栈主要解决以下几个问题：</p><ul><li>比当前元素更大的下一个元素</li><li>比当前元素更大的前一个元素</li><li>比当前元素更小的下一个元素</li><li>比当前元素更小的前一个元素</li></ul><p>寻找比当前元素<strong>更大的下一个元素或者下一个元素</strong>，那么应该使用<strong>栈底到栈顶由大到小</strong>的单调栈。当某个元素大于栈顶元素，将栈顶元素弹出，而该元素就是栈顶元素的最右侧的第一个大于它的元素。最左侧的最大元素，那么，某个元素在栈中的下一个元素就是大于它的第一个元素。</p><p>寻找比当前元素更小的下一个元素或者前一个元素，则使用栈底到栈顶由小到大的单调栈。</p><h3 id="496-下一个更大元素"><a href="#496-下一个更大元素" class="headerlink" title="496.下一个更大元素"></a>496.下一个更大元素</h3><p>给定两个没有重复元素的数组 nums1 和 nums2 ，其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。</p><p>nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在，对应位置输出-1。</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 因为nums1是nums2的子集，所以只需要求出nums2中的每一个元素的下一个更大元素即可，存储在map中，使用单调递增来解决</span></span><br><span class="line"><span class="comment">     * 遍历nums2，当栈顶元素比他小的时候，该元素是没有用的，将其踢出栈，并入栈</span></span><br><span class="line"><span class="comment">     * 当栈顶元素大于该元素的时候，保留栈顶元素，入栈</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">int</span>[] nextGreaterElement(<span class="keyword">int</span>[] nums1, <span class="keyword">int</span>[] nums2) &#123;</span><br><span class="line">    HashMap&lt;Integer,Integer&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    Stack&lt;Integer&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=nums2.length-<span class="number">1</span>;i&gt;=<span class="number">0</span>;i--)&#123;</span><br><span class="line">        <span class="keyword">while</span>(!stack.isEmpty()&amp;&amp;stack.peek()&lt;=nums2[i])&#123;</span><br><span class="line">            stack.pop();</span><br><span class="line">        &#125;</span><br><span class="line">        map.put(nums2[i],stack.isEmpty()?-<span class="number">1</span>:stack.peek());</span><br><span class="line">        stack.push(nums2[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span>[] result = <span class="keyword">new</span> <span class="keyword">int</span>[nums1.length];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;nums1.length;i++)&#123;</span><br><span class="line">        result[i] = map.get(nums1[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 因为要求更大元素，建立一个从栈底到栈顶由大到小的栈.</span></span><br><span class="line"><span class="comment">     * 当某个元素大于栈顶元素，将栈顶元素弹出，而该元素就是栈顶元素的最右侧的第一个大于它的元素。</span></span><br><span class="line"><span class="comment">     * 而要是求最左侧的最大元素，那么，某个元素在栈中的下一个元素就是大于它的第一个元素。</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">int</span>[] nextGreaterElement(<span class="keyword">int</span>[] nums1, <span class="keyword">int</span>[] nums2) &#123;</span><br><span class="line">    Map&lt;Integer,Integer&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    Stack&lt;Integer&gt; statck = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;nums2.length;i++)&#123;</span><br><span class="line">        <span class="keyword">while</span>(!statck.isEmpty()&amp;&amp;nums2[statck.peek()]&lt;nums2[i])&#123;</span><br><span class="line">            <span class="keyword">int</span> index = statck.pop();</span><br><span class="line">            map.put(nums2[index],nums2[i]);</span><br><span class="line">        &#125;</span><br><span class="line">        statck.push(i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span>(!statck.isEmpty())&#123;</span><br><span class="line">        map.put(nums2[statck.pop()],-<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span>[] res = <span class="keyword">new</span> <span class="keyword">int</span>[nums1.length];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;nums1.length;i++)&#123;</span><br><span class="line">        res[i] = map.get(nums1[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="503-下一个更大元素2"><a href="#503-下一个更大元素2" class="headerlink" title="503.下一个更大元素2"></a>503.下一个更大元素2</h3><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**给定一个循环数组（最后一个元素的下一个元素是数组的第一个元素），</span></span><br><span class="line"><span class="comment">     * 输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序，</span></span><br><span class="line"><span class="comment">     * 这个数字之后的第一个比它更大的数，这意味着你应该循环地搜索它的下一个更大的数。</span></span><br><span class="line"><span class="comment">     * 如果不存在，则输出 -1。</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 关于环型数组的问题，构建一个环型数组可以通过取余运算来解决</span></span><br><span class="line"><span class="comment">     * 例如，[1,3,4,2]，我们将其当作[1,3,4,2,1,3,4,2]来看待，遍历这个2n长度的数组</span></span><br><span class="line"><span class="comment">     * 其他的，与之前的求下一个最大元素类似，使用单调栈来解决</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">int</span>[] nextGreaterElements(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">    Stack&lt;Integer&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">int</span>[] result = <span class="keyword">new</span> <span class="keyword">int</span>[nums.length];</span><br><span class="line">    <span class="keyword">int</span> length = nums.length;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">2</span>*nums.length-<span class="number">1</span>;i&gt;=<span class="number">0</span>;i--)&#123;</span><br><span class="line">        <span class="keyword">while</span>(!stack.isEmpty()&amp;&amp;stack.peek()&lt;=nums[i%length])&#123;</span><br><span class="line">            stack.pop();</span><br><span class="line">        &#125;</span><br><span class="line">        result[i%length] = stack.isEmpty()?-<span class="number">1</span>:stack.peek();</span><br><span class="line">        stack.push(nums[i%length]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span>[] nextGreaterElements(<span class="keyword">int</span>[] nums) &#123;</span><br><span class="line">        <span class="keyword">int</span> n = nums.length;</span><br><span class="line">        <span class="keyword">int</span>[] res = <span class="keyword">new</span> <span class="keyword">int</span>[n];</span><br><span class="line">        Stack&lt;Integer&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>;i&lt;nums.length*<span class="number">2</span>;i++)&#123;</span><br><span class="line">            <span class="keyword">while</span>(!stack.isEmpty()&amp;&amp;nums[i%n]&gt;nums[stack.peek()%n])&#123;</span><br><span class="line">                <span class="keyword">int</span> index = stack.pop()%n;</span><br><span class="line">                res[index%n] = nums[i%n];</span><br><span class="line">            &#125;</span><br><span class="line">            stack.push(i);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span>(!stack.isEmpty())&#123;</span><br><span class="line">            <span class="keyword">int</span> index = stack.pop();</span><br><span class="line">            <span class="keyword">if</span>(index&lt;nums.length)&#123;</span><br><span class="line">                res[index] = -<span class="number">1</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><h3 id="556-下一个更大元素"><a href="#556-下一个更大元素" class="headerlink" title="556.下一个更大元素"></a>556.下一个更大元素</h3><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 给定一个32位正整数 n，你需要找到最小的32位整数，其与 n 中存在的位数完全相同，</span></span><br><span class="line"><span class="comment">     * 并且其值大于n。如果不存在这样的32位整数，则返回-1。</span></span><br><span class="line"><span class="comment">     *1.寻找第一个不是单调减的元素i，假如没有，返回-1</span></span><br><span class="line"><span class="comment">     * 2.寻找大于i的最小元素</span></span><br><span class="line"><span class="comment">     * 3.交换两个元素</span></span><br><span class="line"><span class="comment">     * 4.将i之后的元素反置</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">nextGreaterElement</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">char</span>[] a = (<span class="string">""</span>+n).toCharArray();</span><br><span class="line">    <span class="keyword">if</span>(a.length&lt;<span class="number">2</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//从尾部寻找第一个不是递减的元素</span></span><br><span class="line">    <span class="keyword">int</span> index = a.length-<span class="number">2</span>;</span><br><span class="line">    <span class="keyword">while</span>(index&gt;=<span class="number">0</span>&amp;&amp;a[index+<span class="number">1</span>]&lt;=a[index])&#123;</span><br><span class="line">        index--;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(index&lt;<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> j = a.length-<span class="number">1</span>;</span><br><span class="line">    <span class="comment">//寻找大于a[index]的</span></span><br><span class="line">    <span class="keyword">while</span>(j&gt;index&amp;&amp;a[index]&gt;=a[j])&#123;</span><br><span class="line">        j--;</span><br><span class="line">    &#125;</span><br><span class="line">    swap(a,index,j);</span><br><span class="line">    reverse(a,index+<span class="number">1</span>,a.length-<span class="number">1</span>);</span><br><span class="line">    <span class="comment">//注意处理异常，可能会溢出int范围</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> Integer.parseInt(<span class="keyword">new</span> String(a));</span><br><span class="line">    &#125;<span class="keyword">catch</span>(Exception e)&#123;</span><br><span class="line">        <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">swap</span><span class="params">(<span class="keyword">char</span>[] a,<span class="keyword">int</span> i,<span class="keyword">int</span> j)</span></span>&#123;</span><br><span class="line">    <span class="keyword">char</span> tmp = a[i];</span><br><span class="line">    a[i] = a[j];</span><br><span class="line">    a[j] = tmp;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">reverse</span><span class="params">(<span class="keyword">char</span>[] a,<span class="keyword">int</span> i,<span class="keyword">int</span> j)</span></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(i&lt;j)&#123;</span><br><span class="line">        swap(a,i,j);</span><br><span class="line">        i++;</span><br><span class="line">        j--;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="739-每日温度"><a href="#739-每日温度" class="headerlink" title="739.每日温度"></a>739.每日温度</h3><p>下一个更大元素问题，单调递增栈</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 每日温度</span></span><br><span class="line"><span class="comment">     * 根据每日 气温 列表，请重新生成一个列表，对应位置的输入是你需要再等待多久温度才会升高超过该日的天数。</span></span><br><span class="line"><span class="comment">     * 如果之后都不会升高，请在该位置用 0 来代替。</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     *单调递增栈来解决</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">int</span>[] dailyTemperatures(<span class="keyword">int</span>[] T) &#123;</span><br><span class="line">    Stack&lt;Integer&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">int</span>[] res = <span class="keyword">new</span> <span class="keyword">int</span>[T.length];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;T.length;i++)&#123;</span><br><span class="line">        <span class="keyword">while</span>(!stack.isEmpty()&amp;&amp;T[i]&gt;T[stack.peek()])&#123;</span><br><span class="line">            <span class="keyword">int</span> index = stack.pop();</span><br><span class="line">            res[index] = i-index;</span><br><span class="line">        &#125;</span><br><span class="line">        stack.push(i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span>(!stack.isEmpty())&#123;</span><br><span class="line">        <span class="keyword">int</span> index = stack.pop();</span><br><span class="line">        res[index] = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="901-股票价格跨度"><a href="#901-股票价格跨度" class="headerlink" title="901.股票价格跨度"></a>901.股票价格跨度</h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 今天股票价格的跨度被定义为股票价格小于或等于今天价格的最大连续日数（从今天开始往回数，包括今天）。</span></span><br><span class="line"><span class="comment"> * 其实就是求最近的大于他的元素</span></span><br><span class="line"><span class="comment"> * */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">StockSpanner</span> </span>&#123;</span><br><span class="line">    Stack&lt;Integer&gt; prices = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    Stack&lt;Integer&gt; weights = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">StockSpanner</span><span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">next</span><span class="params">(<span class="keyword">int</span> price)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> weight = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span>(!prices.isEmpty()&amp;&amp;prices.peek()&lt;=price)&#123;</span><br><span class="line">            prices.pop();</span><br><span class="line">            weight+=weights.pop();</span><br><span class="line">        &#125;</span><br><span class="line">        prices.push(price);</span><br><span class="line">        weights.push(weight);</span><br><span class="line">        <span class="keyword">return</span> weight;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="https://leetcode-cn.com/problems/online-stock-span/solution/gu-piao-jie-ge-kua-du-by-leetcode/" target="_blank" rel="noopener">题解</a></p><h3 id="84-柱状图中最大的矩形"><a href="#84-柱状图中最大的矩形" class="headerlink" title="84. 柱状图中最大的矩形"></a><a href="https://leetcode-cn.com/problems/largest-rectangle-in-histogram/" target="_blank" rel="noopener">84. 柱状图中最大的矩形</a></h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//本质就是找到某个元素左侧第一个小于它的元素，以及右侧小于它的第一个元素</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">largestRectangleArea</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(nums.length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Stack&lt;Integer&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">int</span> max = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i =<span class="number">0</span>;i&lt;nums.length;i++)&#123;</span><br><span class="line">        <span class="keyword">while</span>(!stack.isEmpty()&amp;&amp;nums[i]&lt;nums[stack.peek()])&#123;</span><br><span class="line">            <span class="keyword">int</span> ele = stack.pop();</span><br><span class="line">            <span class="keyword">int</span> after_index = i;</span><br><span class="line">            <span class="keyword">int</span> before_index = stack.isEmpty()?-<span class="number">1</span>:stack.peek();</span><br><span class="line">            max = Math.max(max,(after_index-before_index-<span class="number">1</span>)*nums[ele]);</span><br><span class="line">        &#125;</span><br><span class="line">        stack.push(i);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span>(!stack.isEmpty())&#123;</span><br><span class="line">        <span class="keyword">int</span> after_index = nums.length;</span><br><span class="line">        <span class="keyword">int</span> ele = stack.pop();</span><br><span class="line">        <span class="keyword">int</span> before_index =  stack.isEmpty()?-<span class="number">1</span>:stack.peek();</span><br><span class="line">        max = Math.max(max,(after_index-before_index-<span class="number">1</span>)*nums[ele]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="85-最大矩形"><a href="#85-最大矩形" class="headerlink" title="85. 最大矩形"></a><a href="https://leetcode-cn.com/problems/maximal-rectangle/" target="_blank" rel="noopener">85. 最大矩形</a></h3><p>本题与上一题类似</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 单调栈的应用</span></span><br><span class="line"><span class="comment">     * 对于某一个数组[3,2,4,2],求他形成的最大的最大矩形面积</span></span><br><span class="line"><span class="comment">     * 例如，对3，求其两侧的第一个小于它的元素，这两者之间的距离即是可以形成的矩形</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maximalRectangle</span><span class="params">(<span class="keyword">char</span>[][] matrix)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> max = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">if</span>(matrix.length==<span class="number">0</span>||matrix[<span class="number">0</span>].length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> max;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span>[] helper = <span class="keyword">new</span> <span class="keyword">int</span>[matrix[<span class="number">0</span>].length];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;matrix.length;i++)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j =<span class="number">0</span>;j&lt;matrix[<span class="number">0</span>].length;j++)&#123;</span><br><span class="line">            <span class="keyword">if</span>(String.valueOf(matrix[i][j]).equals(<span class="string">"0"</span>))&#123;</span><br><span class="line">                helper[j] = <span class="number">0</span>;</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                helper[j]++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        max = Math.max(max,generateMatrixArea(helper));</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//本质就是找到某个元素左侧第一个小于它的元素，以及右侧小于它的第一个元素</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">generateMatrixArea</span><span class="params">(<span class="keyword">int</span>[] nums)</span></span>&#123;</span><br><span class="line">    Stack&lt;Integer&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">int</span> max = Integer.MIN_VALUE;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i =<span class="number">0</span>;i&lt;nums.length;i++)&#123;</span><br><span class="line">        <span class="keyword">while</span>(!stack.isEmpty()&amp;&amp;nums[i]&lt;nums[stack.peek()])&#123;</span><br><span class="line">            <span class="keyword">int</span> ele = stack.pop();</span><br><span class="line">            <span class="keyword">int</span> after_index = i;</span><br><span class="line">            <span class="keyword">int</span> before_index = stack.isEmpty()?-<span class="number">1</span>:stack.peek();</span><br><span class="line">            max = Math.max(max,(after_index-before_index-<span class="number">1</span>)*nums[ele]);</span><br><span class="line">        &#125;</span><br><span class="line">        stack.push(i);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span>(!stack.isEmpty())&#123;</span><br><span class="line">        <span class="keyword">int</span> after_index = nums.length;</span><br><span class="line">        <span class="keyword">int</span> ele = stack.pop();</span><br><span class="line">        <span class="keyword">int</span> before_index =  stack.isEmpty()?-<span class="number">1</span>:stack.peek();</span><br><span class="line">        max = Math.max(max,(after_index-before_index-<span class="number">1</span>)*nums[ele]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="42-接雨水"><a href="#42-接雨水" class="headerlink" title="42. 接雨水"></a><a href="https://leetcode-cn.com/problems/trapping-rain-water/" target="_blank" rel="noopener">42. 接雨水</a></h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//使用单调递减栈，假如某个元素大于栈顶元素，因为元素栈底到栈顶是由大到小的，所以必定可以形成雨水区域</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">trap</span><span class="params">(<span class="keyword">int</span>[] height)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(height.length&lt;<span class="number">3</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Stack&lt;Integer&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;height.length;i++)&#123;</span><br><span class="line">        <span class="keyword">while</span>(!stack.isEmpty()&amp;&amp;height[stack.peek()]&lt;height[i])&#123;</span><br><span class="line">            <span class="keyword">int</span> top = stack.pop();</span><br><span class="line">            <span class="keyword">if</span>(stack.isEmpty())&#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//计算雨水区域大小,注意是i-stack.peek()-1，不是i-top</span></span><br><span class="line">            res+=(i-stack.peek()-<span class="number">1</span>)*(Math.min(height[i],height[stack.peek()])-height[top]);</span><br><span class="line">        &#125;</span><br><span class="line">        stack.push(i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="https://leetcode-cn.com/problems/trapping-rain-water/solution/bao-li-jie-fa-yi-kong-jian-huan-shi-jian-zhi-zhen-/" target="_blank" rel="noopener">题解</a></p><h2 id="单调队列"><a href="#单调队列" class="headerlink" title="单调队列"></a>单调队列</h2><h3 id="滑动窗口最大值"><a href="#滑动窗口最大值" class="headerlink" title="滑动窗口最大值"></a>滑动窗口最大值</h3><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></pre></td><td class="code"><pre><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 双端队列</span></span><br><span class="line"><span class="comment">     * 队头永远存储最大值，双端队列是单调递减的。</span></span><br><span class="line"><span class="comment">     * 入队的时候，假如&lt;队尾元素,直接入队,假如&gt;=队尾元素，那么将队尾元素挤掉，直到&lt;队尾元素</span></span><br><span class="line"><span class="comment">     * 还需要注意的是，需要对队头元素是否过期进行判断：i-w==queue.peekFirst()</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">int</span>[] maxSlidingWindow(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> k) &#123;</span><br><span class="line">    <span class="keyword">if</span>(nums.length&lt;k||nums.length&lt;<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">0</span>]; </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//队列中存储的是下标</span></span><br><span class="line">    LinkedList&lt;Integer&gt; queue = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">    <span class="keyword">int</span>[] res = <span class="keyword">new</span> <span class="keyword">int</span>[nums.length-k+<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">int</span> index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;nums.length;i++)&#123;</span><br><span class="line">        <span class="comment">//假如&gt;=队尾元素，那么将队尾元素挤掉，直到&lt;队尾元素</span></span><br><span class="line">        <span class="keyword">while</span>(!queue.isEmpty()&amp;&amp;nums[i]&gt;=nums[queue.peekLast()])&#123;</span><br><span class="line">            queue.pollLast();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//元素入队</span></span><br><span class="line">        queue.addLast(i);</span><br><span class="line">        <span class="comment">//过期判定</span></span><br><span class="line">        <span class="keyword">if</span>(i-k==queue.peekFirst())&#123;</span><br><span class="line">            queue.pollFirst();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//窗口中至少有k个元素，求取最值</span></span><br><span class="line">        <span class="keyword">if</span>(i&gt;=k-<span class="number">1</span>)&#123;</span><br><span class="line">            res[index++] = nums[queue.peekFirst()];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="滑动窗口变形"><a href="#滑动窗口变形" class="headerlink" title="滑动窗口变形"></a>滑动窗口变形</h3><p><img src="/.com//20170817113349801.gif" alt="这里写图片描述"></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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 准备两个单调队列，一个单调递减，存储的是最大值，一个单调递增，存储的是最小值</span></span><br><span class="line"><span class="comment">     * 假如[L,R]区间内满足max-min&lt;=target，那么[L,L..R]中也必定满足；假如[L,R]区间内不满足max-min&lt;=target，那么[L,R.R+1...arr.length]中也必定不满足；</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">SubArray</span><span class="params">(<span class="keyword">int</span>[] nums,<span class="keyword">int</span> target)</span></span>&#123;</span><br><span class="line">    <span class="comment">//单调减队列，队头存储的是最大值</span></span><br><span class="line">    LinkedList&lt;Integer&gt; qmax = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">    <span class="comment">//单调增队列，队头存储的是最小值</span></span><br><span class="line">    LinkedList&lt;Integer&gt; qmin = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">    <span class="keyword">int</span> left = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> right = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span>(left&lt;nums.length)&#123;</span><br><span class="line">        <span class="comment">//构建单调队列，假如nums[qmax.peekFirst()]-nums[qmin.peekFirst()]&gt;target，表明以left开始，只有[left,left.....right)这些个子数组是符合条件的</span></span><br><span class="line">        <span class="keyword">while</span>(right&lt;nums.length)&#123;</span><br><span class="line">            <span class="keyword">while</span>(qmax.size()&gt;<span class="number">0</span>&amp;&amp;nums[qmax.peekLast()]&lt;=nums[right])&#123;</span><br><span class="line">                qmax.pollLast();</span><br><span class="line">            &#125;</span><br><span class="line">            qmax.push(right);</span><br><span class="line">            <span class="keyword">while</span>(qmin.size()&gt;<span class="number">0</span>&amp;&amp;nums[qmin.peekLast()]&gt;=nums[right])&#123;</span><br><span class="line">                qmin.pollLast();</span><br><span class="line">            &#125;</span><br><span class="line">            qmin.push(right);</span><br><span class="line">            <span class="keyword">if</span>(nums[qmax.peekFirst()]-nums[qmin.peekFirst()]&gt;target)&#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            right++;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//过期条件，因为需要将left右移，所以，下标为left的队列元素应该删除</span></span><br><span class="line">        <span class="keyword">if</span>(qmax.peekFirst()==left)&#123;</span><br><span class="line">            qmax.pollFirst();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(qmin.peekFirst()==left)&#123;</span><br><span class="line">            qmin.pollFirst();</span><br><span class="line">        &#125;</span><br><span class="line">        res+=right-left;</span><br><span class="line">        left++;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="滑动窗口处理子串的问题"><a href="#滑动窗口处理子串的问题" class="headerlink" title="滑动窗口处理子串的问题"></a>滑动窗口处理子串的问题</h3><p>关于处理最小字串，最长字串等问题，可以使用滑动窗口来解决。</p><p>1、我们在字符串 S 中使用双指针中的左右指针技巧，初始化 left = right = 0，把索引闭区间 [left, right] 称为一个「窗口」。</p><p>2、<strong>我们先不断地增加 right 指针扩大窗口</strong> [left, right]，<strong>直到窗口中的字符串符合要求</strong>（包含了 T 中的所有字符）。</p><p>3、此时，我们停止增加 right，转而<strong>不断增加 left 指针缩小窗口 [left, right]，直到窗口中的字符串不再符合要求</strong>（不包含 T 中的所有字符了）。同时，<strong>每次增加 left，我们都要更新一轮结果</strong>。</p><p>4、重复第 2 和第 3 步，直到 right 到达字符串 S 的尽头。</p><p>这个思路其实也不难，第 2 步相当于在寻找一个「可行解」，然后第 3 步在优化这个「可行解」，最终找到最优解。左右指针轮流前进，窗口大小增增减减，窗口不断向右滑动。</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><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></pre></td><td class="code"><pre><span class="line">string s, t;</span><br><span class="line"><span class="comment">// 在 s 中寻找 t 的「最小覆盖子串」</span></span><br><span class="line"><span class="keyword">int</span> left = <span class="number">0</span>, right = <span class="number">0</span>;</span><br><span class="line">string res = s;</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span>(right &lt; s.size()) &#123;</span><br><span class="line">    window.add(s[right++]);</span><br><span class="line">    <span class="comment">// 如果符合要求，移动 left 缩小窗口</span></span><br><span class="line">    <span class="keyword">while</span> (window 符合要求) &#123;</span><br><span class="line">        <span class="comment">// 如果这个窗口的子串更短，则更新 res</span></span><br><span class="line">        res = minLen(res, window);</span><br><span class="line">        window.remove(s[left++]);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> res;</span><br></pre></td></tr></table></figure><h4 id="76-最小覆盖子串"><a href="#76-最小覆盖子串" class="headerlink" title="76. 最小覆盖子串"></a><a href="https://leetcode-cn.com/problems/minimum-window-substring/" target="_blank" rel="noopener">76. 最小覆盖子串</a></h4><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     *需要准备两个指针，left以及right，将right不断右移，直到[left...right]包含了t，那么这是一个满足条件的子数组</span></span><br><span class="line"><span class="comment">     * 但是，还有可能更短，将left右移动，直到[left...right]依旧包含t，当[left...right]不包含t的时候left移动停止</span></span><br><span class="line"><span class="comment">     * 再将right右移，重复以上过程</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">minWindow</span><span class="params">(String s, String t)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(s==<span class="keyword">null</span>||t==<span class="keyword">null</span>||s.length()&lt;t.length())&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">""</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//存储欠的字符的个数,例如t="abc"，那么初始应该前a:1,b:1,c:1</span></span><br><span class="line">    <span class="keyword">int</span>[] map = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">256</span>];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;t.length();i++)&#123;</span><br><span class="line">        map[t.charAt(i)]++;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//还差多少个字符串才能包含t，初始为t的长度，当match==0时，表明已经包含了t</span></span><br><span class="line">    <span class="keyword">int</span> match = t.length();</span><br><span class="line">    <span class="keyword">int</span> left = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> right = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> min = Integer.MAX_VALUE;</span><br><span class="line">    String res=<span class="string">""</span>;</span><br><span class="line">    <span class="keyword">while</span>(right&lt;s.length())&#123;</span><br><span class="line">        map[s.charAt(right)]--;</span><br><span class="line">        <span class="comment">//假如某个字符的map&gt;=0，match--</span></span><br><span class="line">        <span class="keyword">if</span>(map[s.charAt(right)]&gt;=<span class="number">0</span>)&#123;</span><br><span class="line">            match--;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//假如match==0，表明找到了一个子数组;但有可能该子数组并不是最短的，因此，应该将left左移，假如移动过程中有一个字符欠元素了，left停止移动</span></span><br><span class="line">        <span class="keyword">if</span>(match==<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">while</span>(map[s.charAt(left)]&lt;<span class="number">0</span>)&#123;</span><br><span class="line">                map[s.charAt(left++)]++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span>(min&gt;right-left+<span class="number">1</span>)&#123;</span><br><span class="line">                min = right-left+<span class="number">1</span>;</span><br><span class="line">                <span class="comment">//beginIndex - 开始处的索引（包括）endindex 结尾处索引（不包括）</span></span><br><span class="line">                res = s.substring(left,right+<span class="number">1</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            match++;</span><br><span class="line">            map[s.charAt(left++)]++;</span><br><span class="line">        &#125;</span><br><span class="line">        right++;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="3-无重复字符的最长子串？"><a href="#3-无重复字符的最长子串？" class="headerlink" title="3. 无重复字符的最长子串？"></a><a href="https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/" target="_blank" rel="noopener">3. 无重复字符的最长子串</a>？</h4><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></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">lengthOfLongestSubstring</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> left = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> right = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> max = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//记录字符出现的次数</span></span><br><span class="line">    <span class="keyword">int</span>[] map = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">256</span>];</span><br><span class="line">    <span class="keyword">while</span>(right&lt;s.length())&#123;</span><br><span class="line">        <span class="keyword">char</span> c1 = s.charAt(right);</span><br><span class="line">        map[s.charAt(right++)]++;</span><br><span class="line">        <span class="keyword">while</span>(map[c1]&gt;<span class="number">1</span>)&#123;</span><br><span class="line">            map[s.charAt(left++)]--;</span><br><span class="line">        &#125;</span><br><span class="line">        max = Math.max(max,right-left);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> max;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="跳表"><a href="#跳表" class="headerlink" title="跳表"></a>跳表</h2><p><strong>多级索引+链表</strong>。空间复杂度O(n)，查找以及插入时间复杂度O(logn)。</p><p>对于链表的查找，常见的形式是O(n)的复杂度，需要遍历链表。</p><p><img src="/.com//659f5bec14ccd8d8c052.png" alt="img"></p><p>因此，可以抽取索引来解决。这样的话，时间复杂度就可以缩短一半。</p><p><img src="/.com//a9648d8a8d71023a630eee04a57e2116" alt="img"></p><p><strong>skiplist正是受这种多层链表的想法的启发而设计出来的</strong>。</p><p>他会为每一个节点随机生成一个层数。</p><p><img src="/.com//714264ea6eba7af0fe67.png" alt="img"></p><ul><li>跳表实际上是通过多级索引来达到一个链表的二分查找的目的。</li><li>每个元素level是随机生成的。</li><li>最底层包含所有元素。</li><li>跳表查询、插入、删除的时间复杂度为O(log n)</li><li>每个元素内部是一个list，例如，7就是一个由4个元素组成的list。</li></ul><h3 id="查找数据"><a href="#查找数据" class="headerlink" title="查找数据"></a>查找数据</h3><p>查找时间复杂度是O(logn)。</p><p>从最高层开始，一层层遍历直到原始链表。</p><p><img src="/.com//714264ea6eba7af0fe67.png" alt="img"></p><p>最高层索引：从head开始，head下一个元素未7，所以后移。7下一个未null，所以位于7，null之间，下沉。</p><p>二层索引：从7开始，7下一个元素是37，23位于7，37之间。下沉。</p><p>一级索引：从7开始，7下一个元素19，23不位于，向右移动，19下一个元素37，23位于。下沉。</p><p>原始链表：从19开始，19下一个元素是22，23不位于，向右移动，22下一个元素26，找到23位置。</p><h3 id="插入数据"><a href="#插入数据" class="headerlink" title="插入数据"></a>插入数据</h3><p>当插入数据的时候，根据该点生成的层数level，从level层开始，逐层开始插入。<strong>跟查找整个过程相似</strong>，<strong>只不过添加了一个插入元素的过程</strong>。</p><p>插入数据6，level=3。</p><p><img src="/.com//16d7dfd07c5ac52c" alt="插入数据且维护跳表图示1.jpeg"></p><p>三级索引，1&lt;6&lt;13，所以往下移动。</p><p><img src="/.com//16d7dfd0a3fa67be" alt="插入数据且维护跳表图示2.jpeg"></p><p>二级索引，6位于1，7之间，所以，直接在1，7之间插入7。</p><p><img src="/.com//16d7dfd0c8eb5a8b" alt="插入数据且维护跳表图示3.jpeg"></p><p>一级索引，6不在1，4之间，所以向后移动，6位于4，7之间，所以插入。</p><p><img src="/.com//16d7dfd0f5c11bd4" alt="插入数据且维护跳表图示4.jpeg"></p><p>原始链表，6不位于4，5之间，向后移动，6位于5，7之间，直接插入。</p><h3 id="删除数据"><a href="#删除数据" class="headerlink" title="删除数据"></a>删除数据</h3><p>与查找，插入数据类似。时间复杂度也是O(logn)。</p><p><img src="/.com//16d7dfd11ce69fd9" alt="删除数据.jpeg"></p><p><a href="https://juejin.im/post/5d90e4a15188252d3a6a60b8" target="_blank" rel="noopener">跳表</a></p><h2 id="LRU和LFU"><a href="#LRU和LFU" class="headerlink" title="LRU和LFU"></a>LRU和LFU</h2><p>LRU：当容量满的时候，删除最久未使用的元素。</p><p>LFU：当容量满的时候，删除使用次数最少的，假如使用次数最少有多个元素，那么删除最久未使用的元素。</p><h3 id="LRU"><a href="#LRU" class="headerlink" title="LRU"></a>LRU</h3><p>146.设计和实现一个  <a href="https://baike.baidu.com/item/LRU" target="_blank" rel="noopener">LRU (最近最少使用) 缓存机制</a>。它应该支持以下操作： 获取数据 <code>get</code> 和 写入数据 <code>put</code> 。</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 需要准备一个map，一个双向链表，双向链表来解决访问记录的问题 .hashMap来存储数据。</span></span><br><span class="line"><span class="comment"> * 双向链表来存储数据访问的先后顺序，头节点代表的就是最久未访问的数据</span></span><br><span class="line"><span class="comment"> * 双向链表中存储的节点包含key以及value</span></span><br><span class="line"><span class="comment"> * 添加元素时，需要将node插入到双向链表以及map中，而且，假如插入的key以及包含了，那么代表该点被访问了，需要将其移动到双向链表尾部；当添加元素大于容量，需要将双向链表头部元素以及map中相应元素删除</span></span><br><span class="line"><span class="comment"> * 当访问某一个元素时，需要将该元素移动到链表尾部</span></span><br><span class="line"><span class="comment"> * */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LRUCache</span> </span>&#123;</span><br><span class="line">    <span class="comment">//双链表中的数据节点，存储的是key</span></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Node</span></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">int</span> key;</span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">int</span> value;</span><br><span class="line">        <span class="keyword">public</span> Node pre;</span><br><span class="line">        <span class="keyword">public</span> Node next;</span><br><span class="line">        Node(<span class="keyword">int</span> key,<span class="keyword">int</span> value)&#123;</span><br><span class="line">            <span class="keyword">this</span>.key = key;</span><br><span class="line">            <span class="keyword">this</span>.value = value;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//定义双链表</span></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DoubleList</span></span>&#123;</span><br><span class="line">        <span class="keyword">private</span> Node head;</span><br><span class="line">        <span class="keyword">private</span> Node tail;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">DoubleList</span><span class="params">()</span></span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.head=<span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">this</span>.tail=<span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addNode</span><span class="params">(Node node)</span></span>&#123;</span><br><span class="line">            <span class="keyword">if</span>(node==<span class="keyword">null</span>)&#123;</span><br><span class="line">                <span class="keyword">return</span> ;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span>(<span class="keyword">this</span>.head==<span class="keyword">null</span>)&#123;</span><br><span class="line">                head = node;</span><br><span class="line">                tail = node;</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                tail.next = node;</span><br><span class="line">                node.pre = tail;</span><br><span class="line">                tail = node;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//将某个节点移动到尾部，即将访问过的节点移动到尾部</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">moveToTail</span><span class="params">(Node node)</span></span>&#123;</span><br><span class="line">            <span class="keyword">if</span>(tail==node)&#123;</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span>(head==node) &#123;</span><br><span class="line">                head.next.pre = <span class="keyword">null</span>;</span><br><span class="line">                head = head.next;</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                node.pre.next = node.next;</span><br><span class="line">                node.next.pre = node.pre;</span><br><span class="line">            &#125;</span><br><span class="line">            tail.next = node;</span><br><span class="line">            node.pre = tail;</span><br><span class="line">            tail = node;</span><br><span class="line">            node.next = <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//删除头节点</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Node <span class="title">removeHead</span><span class="params">()</span></span>&#123;</span><br><span class="line">            <span class="keyword">if</span>(head==<span class="keyword">null</span>)&#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            Node tmp = head;</span><br><span class="line">            <span class="keyword">if</span>(head==tail)&#123;</span><br><span class="line">                head=<span class="keyword">null</span>;</span><br><span class="line">                tail=<span class="keyword">null</span>;</span><br><span class="line">            &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">                head.next.pre = <span class="keyword">null</span>;</span><br><span class="line">                head = head.next;</span><br><span class="line">                tmp.next = <span class="keyword">null</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> tmp;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    Map&lt;Integer,Node&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    DoubleList list = <span class="keyword">new</span> DoubleList();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> capicity;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">LRUCache</span><span class="params">(<span class="keyword">int</span> capacity)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.capicity = capacity;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">get</span><span class="params">(<span class="keyword">int</span> key)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//map中含有该元素，直接获取value，并将节点移动至尾部</span></span><br><span class="line">        <span class="keyword">if</span>(map.containsKey(key))&#123;</span><br><span class="line">            list.moveToTail(map.get(key));</span><br><span class="line">            <span class="keyword">return</span> map.get(key).value;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">put</span><span class="params">(<span class="keyword">int</span> key, <span class="keyword">int</span> value)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//map中包含该元素，那么更新value，并将list中节点移动到队尾</span></span><br><span class="line">        <span class="keyword">if</span>(map.containsKey(key))&#123;</span><br><span class="line">            map.get(key).value = value;</span><br><span class="line">            list.moveToTail(map.get(key));</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="comment">//map中没有该元素，新建节点直接插入map，并且插入到list尾部,假如超过了容量，需要list头部元素删除，并且删除map中相应元素</span></span><br><span class="line">            Node node = <span class="keyword">new</span> Node(key,value);</span><br><span class="line">            map.put(key,node);</span><br><span class="line">            list.addNode(node);</span><br><span class="line">            <span class="keyword">if</span>(map.size()==size+<span class="number">1</span>)&#123;</span><br><span class="line">                removeHead();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//删除list头部元素以及map中相应元素</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">removeHead</span><span class="params">()</span></span>&#123;</span><br><span class="line">        Node node = list.deleteHeadNode();</span><br><span class="line">        map.remove(node.key);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="LFU"><a href="#LFU" class="headerlink" title="LFU"></a>LFU</h3><p>当容量满的时候，<strong>删除的是访问次数最少的，假如有多个访问次数最少的节点，删除最久未访问的</strong>。</p><p>多个桶组成，每个桶代表的是访问次数的数值，桶内存储的是相同访问次数的所有节点，采用头插法，所以尾节点是该桶内最久未访问的节点。</p><p>各个桶之间也是使用双向链表来进行存储。</p><p>因此，需要定义一个Node：key，value，times(访问次数),pre,next.</p><p>两个map，一个存储key与Node，一个存储Node属于哪一个桶。</p><p>插入数据：假如map中包含该元素，那么更新value，访问次数++，并将该元素移动到访问次数+1桶。假如没有该元素，直接将该元素插入到访问次数为1的桶。假如超过了size，那么删除第一个桶的尾节点。</p><p>get数据：访问次数++，移动到访问次数+1的桶。</p><h2 id="并查集"><a href="#并查集" class="headerlink" title="并查集"></a>并查集</h2><p> 检查两个元素是否属于一个集合。</p><p>合并两个元素各自所在的所有集合。</p><p>并查集需要一次性将所有的数据传给他.</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</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">UnionFind</span>&lt;<span class="title">K</span>&gt; </span>&#123;</span><br><span class="line">    <span class="comment">//需要两个map，一个来存储元素的代表节点，一个来存储代表节点:集合大小</span></span><br><span class="line">    Map&lt;K,K&gt; fatherMap ;</span><br><span class="line">    Map&lt;K,Integer&gt; sizeMap;</span><br><span class="line">    <span class="comment">//初始化并查集，并查集需要一次性将所有的数据传给他，初始化每一个元素代表一个集合，代表节点是他本身，size = 1</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">UnionFind</span><span class="params">(List&lt;K&gt; nodes)</span></span>&#123;</span><br><span class="line">        fatherMap = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        sizeMap = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        <span class="keyword">for</span>(K node:nodes)&#123;</span><br><span class="line">            fatherMap.put(node,node);</span><br><span class="line">            sizeMap.put(node,<span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//寻找代表节点，通过不断的迭代寻找自己的上层节点，知道找到最顶层,需要注意的是，有一个路径压缩的问题，在node寻找代表节点的过程中</span></span><br><span class="line">    <span class="comment">//他经过的所有父节点都需要将自己的父节点更新为代表节点</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> K <span class="title">findHead</span><span class="params">(K node)</span></span>&#123;</span><br><span class="line">        <span class="comment">//stack中存储寻找代表节点过程中经历的所有父节点</span></span><br><span class="line">        Stack&lt;K&gt; stack = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">        <span class="comment">//寻找父节点</span></span><br><span class="line">        <span class="keyword">while</span>(node!=fatherMap.get(node))&#123;</span><br><span class="line">            stack.push(node);</span><br><span class="line">            node = fatherMap.get(node);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//路径压缩</span></span><br><span class="line">        <span class="keyword">while</span>(!stack.isEmpty())&#123;</span><br><span class="line">            fatherMap.put(stack.pop(),node);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> node;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 合并两个集合</span></span><br><span class="line"><span class="comment">     * 两个节点各自寻找到自己的代表节点，</span></span><br><span class="line"><span class="comment">     *      两个代表节点一致，不用合并</span></span><br><span class="line"><span class="comment">     *      将小集合的元素合并到大集合元素中</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">union</span><span class="params">(K a,K b)</span></span>&#123;</span><br><span class="line">        K aHead = findHead(a);</span><br><span class="line">        K bHead = findHead(b);</span><br><span class="line">        <span class="keyword">if</span>(aHead!=bHead) &#123;</span><br><span class="line">            <span class="keyword">int</span> aRank = sizeMap.get(aHead);</span><br><span class="line">            <span class="keyword">int</span> bRank = sizeMap.get(bHead);</span><br><span class="line">            <span class="comment">//a集合大，直接将bHead设置为aHead的子节点,将a集合size+bRank，并将b集合的size抹除</span></span><br><span class="line">            <span class="keyword">if</span>(aRank&gt;bRank)&#123;</span><br><span class="line">                fatherMap.put(bHead,aHead);</span><br><span class="line">                sizeMap.put(aHead,aRank+bRank);</span><br><span class="line">                sizeMap.remove(bHead);</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                fatherMap.put(aHead,bHead);</span><br><span class="line">                sizeMap.put(bHead,aRank+bRank);</span><br><span class="line">                sizeMap.remove(aHead);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="前缀树"><a href="#前缀树" class="headerlink" title="前缀树"></a>前缀树</h2><p>经常用于统计和排序大量的字符串（但不仅限于字符串）。它的优点是：<strong>最大限度地减少无谓的字符串比较</strong>，查询效率比哈希表高。</p><p>前缀匹配</p><p>trie树前缀匹配常用于搜索提示。如当输入一个网址，可以自动搜索出可能的选择。当没有完全匹配的搜索结果，可以返回前缀最相似的可能</p><p>字符串检索</p><p>给定一组字符串，查找某个字符串是否出现过。</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</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">Trie</span> </span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TrieNode</span></span>&#123;</span><br><span class="line">            <span class="comment">//该节点被经过了几次，可以用来求以其为前缀的字符串有多少</span></span><br><span class="line">            <span class="keyword">int</span> path;</span><br><span class="line">            <span class="comment">//该点为终止节点次数,可以用于求解某个字符串的个数</span></span><br><span class="line">            <span class="keyword">int</span> end;</span><br><span class="line">            <span class="comment">//字符串a-z一共有26个分支</span></span><br><span class="line">            TrieNode[] nexts ;</span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="title">TrieNode</span><span class="params">()</span></span>&#123;</span><br><span class="line">                <span class="keyword">this</span>.path = <span class="number">0</span>;</span><br><span class="line">                <span class="keyword">this</span>.end = <span class="number">0</span>;</span><br><span class="line">                nexts = <span class="keyword">new</span> TrieNode[<span class="number">26</span>];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//根节点，根节点是不存数值的</span></span><br><span class="line">        <span class="keyword">private</span> TrieNode root;</span><br><span class="line">        <span class="comment">/** Initialize your data structure here. */</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">Trie</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            root = <span class="keyword">new</span> TrieNode();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 插入元素。</span></span><br><span class="line"><span class="comment">         * "XXXX"转化成字符数组，遍历整个数组，假如nexts[i]不存在，说明第一次遇到该字符，新建一个TrieNode，另next[i]=TrieNode,并path++，</span></span><br><span class="line"><span class="comment">         * 当遍历完成整个数组，在最后一个TrieNode的end++,代表"XXXX"出现了几次</span></span><br><span class="line"><span class="comment">         * */</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">insert</span><span class="params">(String word)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">if</span>(word==<span class="keyword">null</span>)&#123;</span><br><span class="line">                <span class="keyword">return</span> ;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">char</span>[] values = word.toCharArray();</span><br><span class="line">            TrieNode node = <span class="keyword">this</span>.root;</span><br><span class="line">            node.path++;</span><br><span class="line">            <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;values.length;i++)&#123;</span><br><span class="line">                <span class="keyword">int</span> index = values[i]-<span class="string">'a'</span>;</span><br><span class="line">                <span class="keyword">if</span>(node.nexts[index]==<span class="keyword">null</span>)&#123;</span><br><span class="line">                    node.nexts[index] = <span class="keyword">new</span> TrieNode();</span><br><span class="line">                &#125;</span><br><span class="line">                node = node.nexts[index];</span><br><span class="line">                node.path++;</span><br><span class="line">            &#125;</span><br><span class="line">            node.end++;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">/** 查找元素,与插入元素类似，需要注意的是最后一个节点的end值必须&gt;1*/</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">search</span><span class="params">(String word)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">if</span>(word==<span class="keyword">null</span>)&#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            TrieNode node = root;</span><br><span class="line">            <span class="keyword">char</span>[] vals = word.toCharArray();</span><br><span class="line">            <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;vals.length;i++)&#123;</span><br><span class="line">                <span class="keyword">int</span> index = vals[i]-<span class="string">'a'</span>;</span><br><span class="line">                <span class="keyword">if</span>(node.nexts[index]==<span class="keyword">null</span>)&#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                node = node.nexts[index];</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> node.end!=<span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">/** 查询是否存在以某字符串为前缀 */</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">startsWith</span><span class="params">(String prefix)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">if</span>(prefix==<span class="keyword">null</span>)&#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            TrieNode node = root;</span><br><span class="line">            <span class="keyword">char</span>[] vals = prefix.toCharArray();</span><br><span class="line">            <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;vals.length;i++)&#123;</span><br><span class="line">                <span class="keyword">int</span> index = vals[i]-<span class="string">'a'</span>;</span><br><span class="line">                <span class="keyword">if</span>(node.nexts[index]==<span class="keyword">null</span>)&#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                node = node.nexts[index];</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">         <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 删除元素</span></span><br><span class="line"><span class="comment">         * 首先寻找是否在前缀树中，假如在，在前缀树中依次寻找节点，将path--，并将最后一个字符end--</span></span><br><span class="line"><span class="comment">         * 需要注意的是，假如某个节点path--==0，那么后续的节点可以直接不用判断，直接全部删除</span></span><br><span class="line"><span class="comment">         * */</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">delete</span><span class="params">(String word)</span></span>&#123;</span><br><span class="line">            <span class="keyword">if</span>(search(word))&#123;</span><br><span class="line">                TrieNode node = root;</span><br><span class="line">                <span class="keyword">char</span>[] vals = word.toCharArray();</span><br><span class="line">                <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;vals.length;i++)&#123;</span><br><span class="line">                    <span class="keyword">int</span> index = vals[i]-<span class="string">'a'</span>;</span><br><span class="line">                    <span class="keyword">if</span>(node.nexts[index].path--==<span class="number">1</span>)&#123;</span><br><span class="line">                        node.nexts[index]=<span class="keyword">null</span>;</span><br><span class="line">                        <span class="keyword">return</span> ;</span><br><span class="line">                    &#125;</span><br><span class="line">                    node = node.nexts[index];</span><br><span class="line">                &#125;</span><br><span class="line">                node.end--;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;单调栈&quot;&gt;&lt;a href=&quot;#单调栈&quot; class=&quot;headerlink&quot; title=&quot;单调栈&quot;&gt;&lt;/a&gt;单调栈&lt;/h2&gt;&lt;p&gt;单调栈主要解决以下几个问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;比当前元素更大的下一个元素&lt;/li&gt;
&lt;li&gt;比当前元素更大的前一个元素&lt;/
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>leetcode基础算法</title>
    <link href="http://yoursite.com/2019/12/05/leetcode%E5%9F%BA%E7%A1%80%E7%AE%97%E6%B3%95/"/>
    <id>http://yoursite.com/2019/12/05/leetcode基础算法/</id>
    <published>2019-12-05T09:15:28.000Z</published>
    <updated>2019-12-29T07:14:42.685Z</updated>
    
    <content type="html"><![CDATA[<h2 id="排序算法"><a href="#排序算法" class="headerlink" title="排序算法"></a>排序算法</h2><table><thead><tr><th>算法</th><th>稳定性</th><th>时间复杂度</th><th>空间复杂度</th><th>备注</th></tr></thead><tbody><tr><td>选择排序</td><td>×</td><td>N^2</td><td>1</td><td></td></tr><tr><td>冒泡排序</td><td>√</td><td>N^2</td><td>1</td><td></td></tr><tr><td>插入排序</td><td>√</td><td>N ~ N^2</td><td>1</td><td>时间复杂度和初始顺序有关</td></tr><tr><td>希尔排序</td><td>×</td><td>N 的若干倍乘于递增序列的长度</td><td>1</td><td>改进版插入排序</td></tr><tr><td>快速排序</td><td>×</td><td>NlogN</td><td>logN</td><td></td></tr><tr><td>三向切分快速排序</td><td>×</td><td>N ~ NlogN</td><td>logN</td><td>适用于有大量重复主键</td></tr><tr><td>归并排序</td><td>√</td><td>NlogN</td><td>N</td><td></td></tr><tr><td>堆排序</td><td>×</td><td>NlogN</td><td>1</td><td>无法利用局部性原理</td></tr></tbody></table><h3 id="快速排序"><a href="#快速排序" class="headerlink" title="快速排序"></a>快速排序</h3><p>快排的最坏时间复杂度，选的初始值是最大值或者是最小值，这样就是N-1+N-2+….1=O(n^2).</p><p><strong>最优的情况下空间复杂度为：O(logn)  ；每一次都平分数组的情况</strong>,就是二叉树的层数</p><p><strong>最差的情况下空间复杂度为：O( n )      ；退化为冒泡排序的情况</strong></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><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></pre></td><td class="code"><pre><span class="line">  <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 1.确定分界点(nums[l],nums[r],nums[(l+r)/2])</span></span><br><span class="line"><span class="comment">     * 2.调整区间，左区间&lt;=x,右区间&gt;=x</span></span><br><span class="line"><span class="comment">     *       使用两个指针来实现，一个指向头，一个指向尾部，假如分界点取nums[i]，那么尾部指针先动，走向中间</span></span><br><span class="line"><span class="comment">     *       当某个数&lt;x，该指针停止，头部指针开始往中间走，当某个数&gt;x,停止，将尾部指针指向的&lt;x的数与头部指向的数交换</span></span><br><span class="line"><span class="comment">     *       就可以达到目的，直到两个指针相遇</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 3.递归左右两个子区间</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">quick_sort</span><span class="params">(<span class="keyword">int</span> nums[],<span class="keyword">int</span> l,<span class="keyword">int</span> r)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(l&gt;=r)</span><br><span class="line">        <span class="keyword">return</span> ;</span><br><span class="line">    <span class="keyword">int</span> left = l-<span class="number">1</span>,right = r+<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> base = nums[(l+r)&gt;&gt;<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">while</span>(left&lt;right)&#123;</span><br><span class="line">        <span class="keyword">do</span>&#123;</span><br><span class="line">            left++;</span><br><span class="line">        &#125;<span class="keyword">while</span>(nums[left]&lt;base);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">do</span>&#123;</span><br><span class="line">            right++;</span><br><span class="line">        &#125;<span class="keyword">while</span>(nums[right]&gt;base);</span><br><span class="line">        <span class="keyword">if</span>(left&lt;right)&#123;</span><br><span class="line">            <span class="keyword">int</span> temp = nums[left];</span><br><span class="line">            nums[left] = nums[right];</span><br><span class="line">            nums[right] = temp;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//进行递归，分别判断左右两个子区间</span></span><br><span class="line">    quick_sort(nums,l,right);</span><br><span class="line">    quick_sort(nums,right+<span class="number">1</span>,r);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>改进版的快速排序，分为&lt;num等于num以及大于num三个子区间，这样的话当数据中有大量相同的数据，就可以大大节省时间。</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">quick_sort2</span><span class="params">(<span class="keyword">int</span>[] nums,<span class="keyword">int</span> left,<span class="keyword">int</span> right)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(left&gt;=right)&#123;</span><br><span class="line">        <span class="keyword">return</span> ;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> mid = (left+right)/<span class="number">2</span>;</span><br><span class="line">    <span class="comment">//拆分为三个子区间</span></span><br><span class="line">    <span class="keyword">int</span> less =left-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> more = right +<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> cur = left;</span><br><span class="line">    <span class="keyword">int</span> target = nums[mid];</span><br><span class="line">    <span class="keyword">while</span>(cur!=more)&#123;</span><br><span class="line">        <span class="keyword">if</span>(nums[cur]&lt;target)&#123;</span><br><span class="line">            less++;</span><br><span class="line">            swap(nums,cur,less);</span><br><span class="line">            cur++;</span><br><span class="line">        &#125;<span class="keyword">else</span> <span class="keyword">if</span>(nums[cur]&gt;target)&#123;</span><br><span class="line">            more--;</span><br><span class="line">            swap(nums,cur,more);</span><br><span class="line"></span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            cur++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(less&gt;left) &#123;</span><br><span class="line">        quick_sort2(nums, left, less);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(more&lt;right) &#123;</span><br><span class="line">        quick_sort2(nums, more, right);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="75-荷兰国旗问题"><a href="#75-荷兰国旗问题" class="headerlink" title="75.荷兰国旗问题"></a>75.荷兰国旗问题</h4><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="comment">/**</span></span><br><span class="line"><span class="comment">     * 其实就是&lt; num放左边，==num放中间,&gt;num放右边的问题</span></span><br><span class="line"><span class="comment">     * 准备三个指针，less表示小于num的临界指针，cur当前元素的指针，大于num表示大于num的临界指针</span></span><br><span class="line"><span class="comment">     * 当nums[cur]&lt;target，将当前值与less临界指针阿下一个元素交换，less指针后移，cur后移</span></span><br><span class="line"><span class="comment">     * 当nums[cur]==target，cur后移，无其它操作</span></span><br><span class="line"><span class="comment">     * 当nums[cur]&gt;target，将该元素与more指针的前一个元素交换,more前移</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">sortColors</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(nums.length&lt;<span class="number">2</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> target = <span class="number">1</span>;</span><br><span class="line">    <span class="comment">//定义指针，&lt;num为-1，&gt;num为nums.length，cur==0</span></span><br><span class="line">    <span class="keyword">int</span> less =-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> cur = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> more = nums.length;</span><br><span class="line">    <span class="keyword">while</span>(cur!=more)&#123;</span><br><span class="line">        <span class="keyword">if</span>(nums[cur]&lt;target)&#123;</span><br><span class="line">            swap(nums,cur,less+<span class="number">1</span>);</span><br><span class="line">            less++;</span><br><span class="line">            cur++;</span><br><span class="line">        &#125;<span class="keyword">else</span> <span class="keyword">if</span>(nums[cur]==target)&#123;</span><br><span class="line">            cur++;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            swap(nums,cur,more-<span class="number">1</span>);</span><br><span class="line">            more--;</span><br><span class="line">            <span class="comment">//注意，不需要cur++，因为交换的cur实际上可能&lt;target</span></span><br><span class="line">            <span class="comment">// cur++;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">swap</span><span class="params">(<span class="keyword">int</span>[] arr,<span class="keyword">int</span> a,<span class="keyword">int</span> b)</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> tmp = arr[a];</span><br><span class="line">    arr[a] = arr[b];</span><br><span class="line">    arr[b] = tmp;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="归并排序"><a href="#归并排序" class="headerlink" title="归并排序"></a>归并排序</h3><p>合二为一。将两个排序好的数组进行合并，使用双指针。</p><p>空间复杂度：O(N)，即tmp数组</p><p>时间复杂度：O(nlogN)，可有公式求出</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><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><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 1.确定分界点，取mid</span></span><br><span class="line"><span class="comment">     * 2.递归排序左右两个子区间</span></span><br><span class="line"><span class="comment">     * 3.归并两个排完序的子区间，使用双指针来解决</span></span><br><span class="line"><span class="comment">     * */</span></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">merge_sort</span><span class="params">(<span class="keyword">int</span>[] nums,<span class="keyword">int</span> l,<span class="keyword">int</span> r)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(l&gt;=r)</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    <span class="keyword">int</span> mid = (l+r)&gt;&gt;<span class="number">1</span>;</span><br><span class="line">    <span class="comment">//递归排序</span></span><br><span class="line">    merge_sort(nums,l,mid);</span><br><span class="line">    merge_sort(nums,mid+<span class="number">1</span>,r);</span><br><span class="line">    <span class="comment">//临时存储合并的排序结果</span></span><br><span class="line">    <span class="keyword">int</span>[] tmp = <span class="keyword">new</span> <span class="keyword">int</span>[r-l+<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">int</span> index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> first = l;</span><br><span class="line">    <span class="keyword">int</span> second = mid+<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(first&lt;=mid&amp;&amp;second&lt;=r)&#123;</span><br><span class="line">        <span class="keyword">if</span>(nums[first]&lt;=nums[second])&#123;</span><br><span class="line">            tmp[index++] = nums[first++];</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            tmp[index++] = nums[second++];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span>(first&lt;=mid)&#123;</span><br><span class="line">        tmp[index++] = nums[first++];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span>(second&lt;=r)&#123;</span><br><span class="line">        tmp[index++] = nums[second++];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//将临时数组内容存储到nums中</span></span><br><span class="line">    <span class="keyword">int</span> j = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i = l;i&lt;=r;i++)&#123;</span><br><span class="line">        nums[i] = tmp[j++];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="小和问题"><a href="#小和问题" class="headerlink" title="小和问题"></a>小和问题</h4><p>主要借助归并排序来解决。类似于可以划分为左右子区间的问题都可以使用递归方式来解决。</p><p><img src="/images/leetcode%E5%9F%BA%E7%A1%80%E7%AE%97%E6%B3%95/1576392749776.png" alt="1576392749776"></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><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><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">merge</span><span class="params">(<span class="keyword">int</span>[] arr,<span class="keyword">int</span> left ,<span class="keyword">int</span> right)</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> mid = left+((right-left)&gt;&gt;<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">if</span>(left&gt;=right)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> left_result = merge(arr,left,mid);</span><br><span class="line">    <span class="keyword">int</span> right_result = merge(arr,mid+<span class="number">1</span>,right);</span><br><span class="line">    <span class="comment">//合并</span></span><br><span class="line">    <span class="keyword">int</span>[] tmp = <span class="keyword">new</span> <span class="keyword">int</span>[right-left+<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">int</span> index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> first = left;</span><br><span class="line">    <span class="keyword">int</span> secod = mid+<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//对排完序的左右子区间进行合并操作</span></span><br><span class="line">    <span class="comment">//需要注意的是，假如左子区间的某个数i&lt;右子区间的某一个数j，这个数必定就是右子区间j以及j之后的数的小数，因为两个子区间都是有序的</span></span><br><span class="line">    <span class="keyword">while</span>(first&lt;=mid&amp;&amp;secod&lt;=right)&#123;</span><br><span class="line">        <span class="keyword">if</span>(arr[first]&lt;arr[secod])&#123;</span><br><span class="line">            res += (right-secod+<span class="number">1</span>)*arr[first];</span><br><span class="line">            tmp[index++] = arr[first++];</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            tmp[index++] = arr[secod++];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span>(first&lt;=mid)&#123;</span><br><span class="line">        tmp[index++] = arr[first++];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span>(secod&lt;=right)&#123;</span><br><span class="line">        tmp[index++] = arr[secod++];</span><br><span class="line">    &#125;</span><br><span class="line">    index = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=left;i&lt;=right;i++)&#123;</span><br><span class="line">        arr[i] = tmp[index++];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//结果为两区间之和+合并区间</span></span><br><span class="line">    <span class="keyword">return</span> left_result+right_result+res;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="冒泡排序"><a href="#冒泡排序" class="headerlink" title="冒泡排序"></a>冒泡排序</h3><p>时间复杂度为O(n^2)。n-1+n-2+….2=n^2/2</p><p>从左到右不断交换相邻逆序的元素，在一轮的循环之后，可以让未排序的最大元素上浮到右侧。</p><p><strong>每一次循环都会有一个位置的元素</strong>确定。</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">bubbleSort</span><span class="params">(<span class="keyword">int</span>[] arr)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(arr==<span class="keyword">null</span>||arr.length&lt;<span class="number">2</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;arr.length;i++)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j=i+<span class="number">1</span>;j&lt;arr.length;j++)&#123;</span><br><span class="line">            <span class="keyword">if</span>(arr[i]&gt;arr[j])&#123;</span><br><span class="line">                <span class="keyword">int</span> tmp = arr[i];</span><br><span class="line">                arr[i] = arr[j];</span><br><span class="line">                arr[j] = tmp;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="选择排序"><a href="#选择排序" class="headerlink" title="选择排序"></a>选择排序</h3><p>与冒泡排序差不多,与冒泡排序最大的区别就就是它的交换元素每一次只交换一次，<strong>选择排序是不稳定的</strong>。</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">selectSort</span><span class="params">(<span class="keyword">int</span>[] arr)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(arr==<span class="keyword">null</span>||arr.length&lt;<span class="number">2</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> minindex = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>;i&lt;arr.length;i++)&#123;</span><br><span class="line">        minindex = i;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> j = i+<span class="number">1</span>;j&lt;arr.length;j++)&#123;</span><br><span class="line">            <span class="keyword">if</span>(arr[j]&lt;arr[minindex])&#123;</span><br><span class="line">                minindex = j;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">int</span> tmp = arr[i];</span><br><span class="line">        arr[i] = arr[minindex];</span><br><span class="line">        arr[minindex] = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="插入排序"><a href="#插入排序" class="headerlink" title="插入排序"></a>插入排序</h3><p>时间复杂度最差是O(n^2)，逆序的情况下，最好是O(n)，顺序的情况下。</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><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">insertSort</span><span class="params">(<span class="keyword">int</span>[] arr)</span></span>&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>;i&lt;arr.length;i++)&#123;</span><br><span class="line">        <span class="keyword">int</span> j=i-<span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span>(j&gt;=<span class="number">0</span>&amp;&amp;arr[i]&gt;arr[j])&#123;</span><br><span class="line">            swap(arr,i,j);</span><br><span class="line">            i =j;</span><br><span class="line">            j=j-<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="堆排序"><a href="#堆排序" class="headerlink" title="堆排序"></a>堆排序</h3><h5 id="堆结构"><a href="#堆结构" class="headerlink" title="堆结构"></a>堆结构</h5><p>堆的<strong>插入删除时间复杂度是logN，即树的高度，因此，效率很高</strong>。</p><p><strong>堆实际上是一个完全二叉树</strong>，堆可以用数组来表示，位置 k 的节点的父节点位置为 （k-1）/2，而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置，是为了更清晰地描述节点的位置关系。</p><p>大顶堆：父节点的值大于他所有子孙的值。</p><p>小顶堆：父节点的值小于他所有子孙的值。</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//上浮操作</span></span><br><span class="line"><span class="comment">//与祖先节点进行比较，假如小于祖先节点，那么替换掉祖先节点,某个点父节点为(i-1)/2</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">heapInsert</span><span class="params">(<span class="keyword">int</span>[] arr,<span class="keyword">int</span> i)</span></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(arr[i]&gt;arr[(i-<span class="number">1</span>)/<span class="number">2</span>])&#123;</span><br><span class="line">        swap(arr,i,(i-<span class="number">1</span>)/<span class="number">2</span>);</span><br><span class="line">        i = (i-<span class="number">1</span>)/<span class="number">2</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//下沉操作</span></span><br><span class="line"><span class="comment">//heapsize为边界</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">heapify</span><span class="params">(<span class="keyword">int</span>[] arr,<span class="keyword">int</span> i,<span class="keyword">int</span> heapsize)</span></span>&#123;</span><br><span class="line">    <span class="comment">//i的左节点</span></span><br><span class="line">    <span class="keyword">int</span> left = i*<span class="number">2</span>+<span class="number">1</span>;</span><br><span class="line">    <span class="comment">//假如该节点它的某个子孙节点小，那么，就将二者交换</span></span><br><span class="line">    <span class="keyword">while</span>(left &lt;= heapsize)&#123;</span><br><span class="line">        <span class="comment">//获取左右节点最大值</span></span><br><span class="line">        <span class="keyword">int</span> right = left+<span class="number">1</span>;</span><br><span class="line">        <span class="keyword">int</span> largest = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">if</span>(right&lt;=heapsize)&#123;</span><br><span class="line">            largest = arr[right]&gt;arr[left]?right:left;</span><br><span class="line">        &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">            largest = left;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//该节点与其孩子节点进行比较</span></span><br><span class="line">        largest = arr[i]&gt;arr[largest]?i:largest;</span><br><span class="line">        <span class="comment">//假如该节点大于其左右孩子，那么直接结束循环</span></span><br><span class="line">        <span class="keyword">if</span>(largest==i)&#123;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//该节点小于左或者右孩子，进行交换，继续循环</span></span><br><span class="line">        swap(arr,i,largest);</span><br><span class="line">        i = largest;</span><br><span class="line">        left = i*<span class="number">2</span>+<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 1.构建堆，通过上浮来完成</span></span><br><span class="line"><span class="comment">     * 2.从构建好的堆中取根节点，并将最后一个节点填补上来</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">heapSort</span><span class="params">(<span class="keyword">int</span>[] arr)</span></span>&#123;</span><br><span class="line">    <span class="comment">//构建堆</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;arr.length;i++)&#123;</span><br><span class="line">        heapInsert(arr,i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//取节点</span></span><br><span class="line">    <span class="keyword">int</span> heapsize = arr.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(heapsize&gt;<span class="number">0</span>)&#123;</span><br><span class="line">        swap(arr,<span class="number">0</span>,heapsize);</span><br><span class="line">        heapsize--;</span><br><span class="line">        heapify(arr,<span class="number">0</span>,heapsize);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (arr == <span class="keyword">null</span> || arr.length &lt; <span class="number">2</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="非基于比较器的排序"><a href="#非基于比较器的排序" class="headerlink" title="非基于比较器的排序"></a>非基于比较器的排序</h3><p>桶排序，基数排序，计数排序。</p><p><img src="/images/leetcode%E5%9F%BA%E7%A1%80%E7%AE%97%E6%B3%95/1576392783112.png" alt="1576392783112"></p><p>采用桶的思想来解决。</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 假如数组有n个元素，那么准备n+1个桶</span></span><br><span class="line"><span class="comment">     * 遍历一次数组，求出最大值最小值，将各个桶按照最大值最小值均分，比如，min=0,max=99，则桶为0~9,10~19.....90~99</span></span><br><span class="line"><span class="comment">     * 这样的话，第一个桶必定有一个元素，即最小值，最后一个桶必定会有一个最大值</span></span><br><span class="line"><span class="comment">     * 因此，需要将n-2个元素插入剩下的n+1个桶中，这样必定至少会有一个空桶</span></span><br><span class="line"><span class="comment">     * 这样的话，空桶的左右两侧肯定各有一个非空桶，这样的话，最大差值一定不可能在桶内元素，而是在桶间元素</span></span><br><span class="line"><span class="comment">     * 因此，我们只需要记录各个桶的最大值最小值，然后跨桶的最小值-最大值中必定含有最大差值</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxGap</span><span class="params">(<span class="keyword">int</span>[] arr)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(arr==<span class="keyword">null</span>||arr.length&lt;<span class="number">2</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> length = arr.length;</span><br><span class="line">    <span class="comment">//寻找min max</span></span><br><span class="line">    <span class="keyword">int</span> min = Integer.MAX_VALUE;</span><br><span class="line">    <span class="keyword">int</span> max = Integer.MIN_VALUE;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;length;i++)&#123;</span><br><span class="line">        min = Math.min(min,arr[i]);</span><br><span class="line">        max = Math.max(max,arr[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(min==max)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//桶是否有数据，各桶最大值，最小值</span></span><br><span class="line">    <span class="keyword">boolean</span>[] hasNum = <span class="keyword">new</span> <span class="keyword">boolean</span>[length+<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">int</span>[] maxs = <span class="keyword">new</span> <span class="keyword">int</span>[length+<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">int</span>[] mins = <span class="keyword">new</span> <span class="keyword">int</span>[length+<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">int</span> bucketNum=<span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;length;i++)&#123;</span><br><span class="line">        <span class="comment">//计算属于哪一个桶</span></span><br><span class="line">        bucketNum = getBucket(arr[i],length,min,max);</span><br><span class="line">        <span class="comment">//桶内最大值，最小值</span></span><br><span class="line">        maxs[bucketNum] = hasNum[bucketNum]?Math.max(arr[i],maxs[bucketNum]):arr[i];</span><br><span class="line">        mins[bucketNum] = hasNum[bucketNum]?Math.min(arr[i],mins[bucketNum]):arr[i];</span><br><span class="line">        hasNum[bucketNum] = <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//获取桶间元素最大值</span></span><br><span class="line">    <span class="keyword">int</span> maxBetweenBucket = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> lastMax = maxs[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>;i&lt;length+<span class="number">1</span>;i++)&#123;</span><br><span class="line">        <span class="keyword">if</span>(hasNum[i]) &#123;</span><br><span class="line">            maxBetweenBucket = mins[i] - lastMax &gt; maxBetweenBucket ? (mins[i] - lastMax) : maxBetweenBucket;</span><br><span class="line">            lastMax = maxs[i];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> maxBetweenBucket;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="递归程序时间复杂度计算"><a href="#递归程序时间复杂度计算" class="headerlink" title="递归程序时间复杂度计算"></a>递归程序时间复杂度计算</h2><p><img src="/images/leetcode%E5%9F%BA%E7%A1%80%E7%AE%97%E6%B3%95/1576392803920.png" alt="1576392803920"></p><p>例如：</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 后序遍历二叉树。</span></span><br><span class="line"><span class="comment">     * 左子树返回不为空，右子树返回不为空，则该node必定是公共祖先</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> TreeNode <span class="title">lowestCommonAncestor</span><span class="params">(TreeNode root, TreeNode p, TreeNode q)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//当前节点==p或者==q，那么该点必定是祖先</span></span><br><span class="line">    <span class="keyword">if</span>(root==<span class="keyword">null</span>||root==p||root==q)&#123;</span><br><span class="line">        <span class="keyword">return</span> root;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//递归左右子树</span></span><br><span class="line">    TreeNode left = lowestCommonAncestor(root.left,p,q);</span><br><span class="line">    TreeNode right = lowestCommonAncestor(root.right,p,q);</span><br><span class="line">    <span class="comment">//假如左右子树返回均不为空，那么当前节点就是公共祖先</span></span><br><span class="line">    <span class="keyword">if</span>(left!=<span class="keyword">null</span>&amp;&amp;right!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> root;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//只有一个子树返回的不是空</span></span><br><span class="line">    <span class="keyword">return</span> left!=<span class="keyword">null</span>?left:right;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>该递归程序每次需要递归两次子区间，则a = 2，每个递归子区间大小是N/2，因此b = 2，而每次执行完还需要做O(1)的操作，因此，d= 0,log(b,a)=1&gt;d,所以复杂度为O(N^log(2,2))=O(N)</p><p>工程中的排序算法</p><p>一般来说，是综合多种排序算法的。</p><p>假如数据量很小，使用插入排序；样本量很大，数据类型是基础类型，使用快排，数据类型是类，使用归并排序，可以保证数据稳定性。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;排序算法&quot;&gt;&lt;a href=&quot;#排序算法&quot; class=&quot;headerlink&quot; title=&quot;排序算法&quot;&gt;&lt;/a&gt;排序算法&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;算法&lt;/th&gt;
&lt;th&gt;稳定性&lt;/th&gt;
&lt;th&gt;时间复杂度&lt;/th&gt;
&lt;th&gt;
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>leetcode之链表问题</title>
    <link href="http://yoursite.com/2019/12/02/leetcode%E4%B9%8B%E9%93%BE%E8%A1%A8%E9%97%AE%E9%A2%98/"/>
    <id>http://yoursite.com/2019/12/02/leetcode之链表问题/</id>
    <published>2019-12-02T05:19:13.000Z</published>
    <updated>2019-12-23T05:56:32.887Z</updated>
    
    <content type="html"><![CDATA[<h2 id="19-删除链表的倒数第N个节点"><a href="#19-删除链表的倒数第N个节点" class="headerlink" title="19.删除链表的倒数第N个节点"></a>19.删除链表的倒数第N个节点</h2><p>给定一个链表，删除链表的倒数第 <em>n</em> 个节点，并且返回链表的头结点。</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">removeNthFromEnd</span><span class="params">(ListNode head, <span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 因为要删除某个节点，必须先要获得它的前一个结点</span></span><br><span class="line"><span class="comment">         * 因为有可能删除头节点，所以最好在头节点之前插入一个虚拟头结点</span></span><br><span class="line"><span class="comment">         * 删除倒数第n个节点，需要找到倒数n+1个节点，最后一个节点与倒数n+1个节点相差n个节点</span></span><br><span class="line"><span class="comment">         * 所以，准备first，second两个节点，保证他们距离是n，当second指到尾节点的时候，first恰好指向倒数n+1个节点</span></span><br><span class="line"><span class="comment">         * */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//虚拟头节点</span></span><br><span class="line">    ListNode dummy = <span class="keyword">new</span> ListNode(<span class="number">0</span>);</span><br><span class="line">    dummy.next = head;</span><br><span class="line">    ListNode first = dummy;</span><br><span class="line">    ListNode second = dummy;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;n;i++)&#123;</span><br><span class="line">        first = first.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span>(first.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        first = first.next;</span><br><span class="line">        second = second.next;</span><br><span class="line">    &#125;</span><br><span class="line">    second.next = second.next.next;</span><br><span class="line">    <span class="keyword">return</span> dummy.next;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="237-删除链表中的节点"><a href="#237-删除链表中的节点" class="headerlink" title="237. 删除链表中的节点"></a>237. 删除链表中的节点</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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使其可以删除某个链表中给定的（非末尾）节点，你将只被给定要求被删除的节点。</span></span><br><span class="line"><span class="comment">     * 将该节点的值设置为下一个节点的值，并将下一个节点删除</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">deleteNode</span><span class="params">(ListNode node)</span> </span>&#123;</span><br><span class="line">    node.data = node.next.data;</span><br><span class="line">    node.next = node.next.next;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="83-删除排序链表中的重复元素"><a href="#83-删除排序链表中的重复元素" class="headerlink" title="83. 删除排序链表中的重复元素"></a>83. 删除排序链表中的重复元素</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></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">    * 给定一个排序链表，删除所有重复的元素，使得每个元素只出现一次。</span></span><br><span class="line"><span class="comment">    *</span></span><br><span class="line"><span class="comment">    * 当某个元素与后继元素相等时，直接删除；不等时，指针后移</span></span><br><span class="line"><span class="comment">    * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">deleteDuplicates</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">    ListNode cur = head;</span><br><span class="line">    <span class="keyword">while</span>(cur!=<span class="keyword">null</span>&amp;&amp;cur.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">if</span>(cur.val == cur.next.val)&#123;</span><br><span class="line">            cur.next = cur.next.next;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            cur = cur.next;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> head;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="61-旋转链表"><a href="#61-旋转链表" class="headerlink" title="61.旋转链表"></a>61.旋转链表</h2><p>给定一个链表，旋转链表，将链表每个节点向右移动 <em>k</em> 个位置，其中 <em>k</em> 是非负数。</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">rotateRight</span><span class="params">(ListNode head, <span class="keyword">int</span> k)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//尾指针指向头节点，倒数第k+1个节点指向null,头指针指向倒数第k个</span></span><br><span class="line">    <span class="keyword">if</span>(head==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//求链表长度</span></span><br><span class="line">    ListNode p =head;</span><br><span class="line">    <span class="keyword">int</span> n =<span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span>(p!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        n++;</span><br><span class="line">        p=p.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> len = k%n;</span><br><span class="line">    ListNode first = head;</span><br><span class="line">    ListNode second = head;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;len;i++)&#123;</span><br><span class="line">        first = first.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span>(first.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        first = first.next;</span><br><span class="line">        second = second.next;</span><br><span class="line">    &#125;</span><br><span class="line">    first.next = head;</span><br><span class="line">    head =second.next;</span><br><span class="line">    second.next = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">return</span> head;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="24-两两交换链表中的节点"><a href="#24-两两交换链表中的节点" class="headerlink" title="24.两两交换链表中的节点"></a>24.两两交换链表中的节点</h2><p>给定一个链表，两两交换其中相邻的节点，并返回交换后的链表。</p><p><strong>你不能只是单纯的改变节点内部的值</strong>，而是需要实际的进行节点交换。</p><p><img src="/images/leetcode%E4%B9%8B%E9%93%BE%E8%A1%A8%E9%97%AE%E9%A2%98/1575286645787.png" alt="1575286645787"></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></pre></td><td class="code"><pre><span class="line"><span class="comment">//需要交换a，b两个节点时</span></span><br><span class="line">p.next = b</span><br><span class="line">a.next = b.next</span><br><span class="line">b.next = a</span><br><span class="line">p =a</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">swapPairs</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//因为头节点也可能会改变，所以需要一个哑节点</span></span><br><span class="line">    ListNode dummy = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">    dummy.next = head;</span><br><span class="line">    ListNode cur = dummy;</span><br><span class="line">    <span class="keyword">while</span>(cur.next!=<span class="keyword">null</span>&amp;&amp;cur.next.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        ListNode a= cur.next;</span><br><span class="line">        ListNode b = a.next;</span><br><span class="line">        cur.next = b;</span><br><span class="line">        a.next = b.next;</span><br><span class="line">        b.next = a;</span><br><span class="line">        cur = a;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> dummy.next;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="206-反转链表"><a href="#206-反转链表" class="headerlink" title="206.反转链表"></a>206.反转链表</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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">reverseList</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(head==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ListNode pre = head;</span><br><span class="line">    ListNode cur = head.next;</span><br><span class="line">    <span class="keyword">while</span>(cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        ListNode tmp = cur.next;</span><br><span class="line">        cur.next = pre;</span><br><span class="line">        pre = cur;</span><br><span class="line">        cur = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">    head.next=<span class="keyword">null</span>;</span><br><span class="line">    head = pre;</span><br><span class="line">    <span class="keyword">return</span> head;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="92-反转链表2"><a href="#92-反转链表2" class="headerlink" title="92.反转链表2"></a>92.反转链表2</h2><p><img src="/images/leetcode%E4%B9%8B%E9%93%BE%E8%A1%A8%E9%97%AE%E9%A2%98/1575293242449.png" alt="1575293242449"></p><p><img src="/images/leetcode%E4%B9%8B%E9%93%BE%E8%A1%A8%E9%97%AE%E9%A2%98/1575294593614.png" alt="1575294593614"></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><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="function"><span class="keyword">public</span> ListNode <span class="title">reverseBetween</span><span class="params">(ListNode head, <span class="keyword">int</span> m, <span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(head==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(m==n)&#123;</span><br><span class="line">        <span class="keyword">return</span> head;</span><br><span class="line">    &#125;</span><br><span class="line">    ListNode dummy = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">    dummy.next = head;</span><br><span class="line">    <span class="comment">//首先，需要找到prem以及nextn</span></span><br><span class="line">    ListNode premNode = dummy,nextnNode=dummy;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;m-<span class="number">1</span>;i++)&#123;</span><br><span class="line">        premNode = premNode.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;n+<span class="number">1</span>;i++)&#123;</span><br><span class="line">        nextnNode = nextnNode.next;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    ListNode pre = premNode;</span><br><span class="line">    ListNode cur = premNode.next;</span><br><span class="line">    ListNode mNode = cur;</span><br><span class="line">    <span class="comment">//将m，n之间元素全部反转</span></span><br><span class="line">    <span class="keyword">while</span>(cur!=<span class="keyword">null</span>&amp;&amp;cur!=nextnNode)&#123;</span><br><span class="line">        ListNode tmp = cur.next;</span><br><span class="line">        cur.next = pre;</span><br><span class="line">        pre = cur;</span><br><span class="line">        cur = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//重新指向</span></span><br><span class="line">    premNode.next = pre;</span><br><span class="line">    mNode.next = nextnNode;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> dummy.next;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="160-相交链表"><a href="#160-相交链表" class="headerlink" title="160.相交链表"></a>160.相交链表</h2><p><img src="/images/leetcode%E4%B9%8B%E9%93%BE%E8%A1%A8%E9%97%AE%E9%A2%98/1575377792658.png" alt="1575377792658"></p><p>编写一个程序，找到两个单链表相交的起始节点。</p><p>求相交的点，两个指针，第一个指针从a走，走a+c，到达尾部，再从b走；</p><p>第二个指针从b走，走b+c，到达尾部，再从a走。</p><p>这样，两个指针都走了a+b+c，相交点即为所求。</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">getIntersectionNode</span><span class="params">(ListNode headA, ListNode headB)</span> </span>&#123;</span><br><span class="line">    ListNode first = headA;</span><br><span class="line">    ListNode second = headB;</span><br><span class="line">    <span class="keyword">while</span>(first!=second)&#123;</span><br><span class="line">        <span class="keyword">if</span>(first!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            first = first.next;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            first = headB;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span>(second!=<span class="keyword">null</span>)&#123;</span><br><span class="line">            second = second.next;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            second = headA;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> first;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="234-回文链表"><a href="#234-回文链表" class="headerlink" title="234. 回文链表"></a><a href="https://leetcode-cn.com/problems/palindrome-linked-list/" target="_blank" rel="noopener">234. 回文链表</a></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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 遍历链表，将值入栈。</span></span><br><span class="line"><span class="comment">     * 从头遍历链表，将栈顶元素出栈，出栈顺序就是链表元素的逆序元素</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isPalindrome</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">    Stack&lt;Integer&gt; help = <span class="keyword">new</span> Stack&lt;&gt;();</span><br><span class="line">    ListNode cur = head;</span><br><span class="line">    <span class="comment">//链表元素入栈</span></span><br><span class="line">    <span class="keyword">while</span>(cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        help.push(cur.val);</span><br><span class="line">        cur = cur.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//从头重新遍历链表，与栈内元素比较，出栈即为链表的逆序</span></span><br><span class="line">    cur = head;</span><br><span class="line">    <span class="keyword">while</span> (cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">int</span> val = help.pop();</span><br><span class="line">        <span class="keyword">if</span>(val==cur.val)&#123;</span><br><span class="line">            cur = cur.next;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>空间复杂度为O(1)的方法。</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><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 空间复杂度为O(1)的情况。</span></span><br><span class="line"><span class="comment">     * 两个指针，快指针走两步，慢指针走一步。当快指针走完的时候，慢指针刚好走到终点，</span></span><br><span class="line"><span class="comment">     * 从中点开始，往后逆转链表，这样，就会变成1-&gt;2-&gt;3&lt;-2&lt;-1</span></span><br><span class="line"><span class="comment">     * 这样，两个指针，一个从头开始，一个从尾部开始，遍历链表，直到两者相遇</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isPalindrome</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(head==<span class="keyword">null</span>||head.next==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ListNode slow = head;</span><br><span class="line">    ListNode fast = head;</span><br><span class="line">    <span class="keyword">while</span>(fast!=<span class="keyword">null</span>&amp;&amp;fast.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        fast = fast.next.next;</span><br><span class="line">        slow = slow.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//反转链表</span></span><br><span class="line">    ListNode pre = slow;</span><br><span class="line">    ListNode cur = slow.next;</span><br><span class="line">    slow.next = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">while</span>(cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        ListNode tmp = cur.next;</span><br><span class="line">        cur.next = pre;</span><br><span class="line">        pre = cur;</span><br><span class="line">        cur = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//头尾两个指针遍历</span></span><br><span class="line">    ListNode first = head;</span><br><span class="line">    ListNode second = pre;</span><br><span class="line">    <span class="keyword">while</span>(second!=<span class="keyword">null</span>&amp;&amp;first!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">if</span>(first.val!=second.val)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            first = first.next;</span><br><span class="line">            second = second.next;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//将逆转的链表恢复</span></span><br><span class="line">    ListNode n1 = pre;</span><br><span class="line">    ListNode n2 = pre.next;</span><br><span class="line">    pre.next=<span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">while</span>(n2!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        ListNode tmp = n2.next;</span><br><span class="line">        n2.next = n1;</span><br><span class="line">        n1 = n2;</span><br><span class="line">        n2 = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="86-分隔链表"><a href="#86-分隔链表" class="headerlink" title="86. 分隔链表"></a><a href="https://leetcode-cn.com/problems/partition-list/" target="_blank" rel="noopener">86. 分隔链表</a></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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">partition</span><span class="params">(ListNode head, <span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(head==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ListNode small = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">    ListNode large = <span class="keyword">new</span> ListNode(-<span class="number">1</span>);</span><br><span class="line">    ListNode small_tail = small;</span><br><span class="line">    ListNode large_tail = large;</span><br><span class="line">    ListNode cur = head;</span><br><span class="line">    <span class="keyword">while</span>(cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">int</span> val = cur.val;</span><br><span class="line">        <span class="keyword">if</span>(val&lt;x)&#123;</span><br><span class="line">            ListNode node = <span class="keyword">new</span> ListNode(val);</span><br><span class="line">            small_tail.next = node;</span><br><span class="line">            small_tail = node;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            ListNode node = <span class="keyword">new</span> ListNode(val);</span><br><span class="line">            large_tail.next = node;</span><br><span class="line">            large_tail = node;</span><br><span class="line">        &#125;</span><br><span class="line">        cur = cur.next;</span><br><span class="line">    &#125;</span><br><span class="line">    small_tail.next = <span class="keyword">null</span>;</span><br><span class="line">    large_tail.next =<span class="keyword">null</span>;</span><br><span class="line">    small_tail.next = large.next;</span><br><span class="line">    <span class="keyword">return</span> small.next;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="138-复制带随机指针的链表"><a href="#138-复制带随机指针的链表" class="headerlink" title="138. 复制带随机指针的链表"></a><a href="https://leetcode-cn.com/problems/copy-list-with-random-pointer/" target="_blank" rel="noopener">138. 复制带随机指针的链表</a></h2><p>通过哈希表来解决，空间复杂度O(n)</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> Node <span class="title">copyRandomList</span><span class="params">(Node head)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(head==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Map&lt;Node,Node&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">    Node cur = head;</span><br><span class="line">    <span class="comment">//遍历链表，建立map映射</span></span><br><span class="line">    <span class="keyword">while</span>(cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        Node copy = <span class="keyword">new</span> Node(cur.val,<span class="keyword">null</span>,<span class="keyword">null</span>);</span><br><span class="line">        map.put(cur,copy);</span><br><span class="line">        cur = cur.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//对链表指针进行拷贝</span></span><br><span class="line">    cur = head;</span><br><span class="line">    <span class="keyword">while</span>(cur!=<span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (cur.next != <span class="keyword">null</span>) &#123;</span><br><span class="line">            map.get(cur).next = map.get(cur.next);</span><br><span class="line">        &#125;</span><br><span class="line">        map.get(cur).random = map.get(cur.random);</span><br><span class="line">        cur = cur.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> map.get(head);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>空间复杂度为O(1)</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><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="comment">/**遍历链表，建立一个包含原节点以及复制节点1-&gt;1'-&gt;2-&gt;2'-&gt;3-&gt;3'</span></span><br><span class="line"><span class="comment">     * 对复制节点处理random指针</span></span><br><span class="line"><span class="comment">     * 从链表中提取复制节点</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> head</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> Node <span class="title">copyRandomList</span><span class="params">(Node head)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(head==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//1-&gt;1'-&gt;2-&gt;2'-&gt;3-&gt;3'</span></span><br><span class="line">    Node cur = head;</span><br><span class="line">    <span class="keyword">while</span> (cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        Node copy = <span class="keyword">new</span> Node(cur.val,<span class="keyword">null</span>,<span class="keyword">null</span>);</span><br><span class="line">        Node tmp = cur.next;</span><br><span class="line">        copy.next = cur.next;</span><br><span class="line">        cur.next = copy;</span><br><span class="line">        cur = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//处理random 1' random就是1 random.next.next</span></span><br><span class="line">    cur = head;</span><br><span class="line">    <span class="keyword">while</span>(cur!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        cur.next.random =cur.random==<span class="keyword">null</span>?<span class="keyword">null</span>:cur.random.next;</span><br><span class="line">        cur = cur.next.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//分离链表</span></span><br><span class="line">    cur = head;</span><br><span class="line">    Node copyHead = head.next;</span><br><span class="line">    <span class="keyword">while</span>(cur.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        Node tmp = cur.next;</span><br><span class="line">        cur.next = cur.next.next;</span><br><span class="line">        cur = tmp;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> copyHead;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="两个链表相交问题"><a href="#两个链表相交问题" class="headerlink" title="两个链表相交问题"></a>两个链表相交问题</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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">       * 两个可能存在环的链表，需要多种情况讨论：</span></span><br><span class="line"><span class="comment">       *    1.两个链表都没有环，判断相交</span></span><br><span class="line"><span class="comment">       *    2.一个有环，一个没有环，必定不可能相交</span></span><br><span class="line"><span class="comment">       *    3.两个都有环，判断相交</span></span><br><span class="line"><span class="comment">       *    判断是否有环：快慢指针</span></span><br><span class="line"><span class="comment">       *    判断无环链表相交：遍历两个链表，记录长度以及尾部节点，若两个尾部节点不等，不相交；若相等，寻找相交点。</span></span><br><span class="line"><span class="comment">       *        短的链表先走len1-len2步，然后两个链表一起走，两个链表相等的时候就是交点。</span></span><br><span class="line"><span class="comment">       *    判断两个有环链表相交：</span></span><br><span class="line"><span class="comment">       *        分为三种情况：</span></span><br><span class="line"><span class="comment">       *            loop1=loop2，必定有交点，可以转化为无环链表相交问题</span></span><br><span class="line"><span class="comment">       *            loop1!=loop2</span></span><br><span class="line"><span class="comment">       *                相交以及不相交</span></span><br><span class="line"><span class="comment">       *                从链表a的环入点开始走，假如走完一圈没有碰到链表b的环入点，那么就是不相交的。</span></span><br><span class="line"><span class="comment">       * */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">getIntersectNode</span><span class="params">(ListNode head1,ListNode head2)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(head1==<span class="keyword">null</span>||head2==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ListNode loop1 = detectCycle(head1);</span><br><span class="line">    ListNode loop2 = detectCycle(head2);</span><br><span class="line">    <span class="comment">//均没有环，都有环</span></span><br><span class="line">    <span class="keyword">if</span>(loop1==<span class="keyword">null</span>&amp;&amp;loop2==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> bothLoop(head1,head2,loop1,loop2);</span><br><span class="line">    &#125;<span class="keyword">else</span> <span class="keyword">if</span>(loop1!=<span class="keyword">null</span>&amp;&amp;loop2!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> noLoop(head1,head2);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//一个有环一个没有环必定不相交</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//两个有环交点的判断</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">bothLoop</span><span class="params">(ListNode head1,ListNode head2,ListNode loop1,ListNode loop2)</span></span>&#123;</span><br><span class="line">    <span class="comment">//假如loop1==loop2，可以看作是尾部节点是loop的两个无环链表相交问题</span></span><br><span class="line">    <span class="keyword">if</span>(loop1==loop2)&#123;</span><br><span class="line">        ListNode cur1 = head1;</span><br><span class="line">        ListNode cur2 = head2;</span><br><span class="line">        <span class="keyword">int</span> n=<span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (cur1!=loop1)&#123;</span><br><span class="line">            n++;</span><br><span class="line">            cur1 = cur1.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (cur2!=loop2)&#123;</span><br><span class="line">            n--;</span><br><span class="line">            cur2 = cur2.next;</span><br><span class="line">        &#125;</span><br><span class="line">        ListNode first = head1;</span><br><span class="line">        ListNode second = head2;</span><br><span class="line">        <span class="keyword">if</span>(n&gt;<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;n;i++) &#123;</span><br><span class="line">                first = first.next;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;Math.abs(n);i++)&#123;</span><br><span class="line">                second = second.next;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (first!=second)&#123;</span><br><span class="line">            first = first.next;</span><br><span class="line">            second = second.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> first;</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="comment">//假如loop1!=loo2，从loop1开始走一圈，若有相交点，走这一圈中必定有loop1==loop2</span></span><br><span class="line">        ListNode cur = loop1.next;</span><br><span class="line">        <span class="keyword">while</span>(cur!=loop1)&#123;</span><br><span class="line">            <span class="keyword">if</span>(cur==loop2)&#123;</span><br><span class="line">                <span class="keyword">return</span> loop1;</span><br><span class="line">            &#125;<span class="keyword">else</span> &#123;</span><br><span class="line">                cur = cur.next;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//无环链表的交点判断</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">noLoop</span><span class="params">(ListNode head1, ListNode head2)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(head1==<span class="keyword">null</span>||head2==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//获取两个节点的尾部节点以及长度</span></span><br><span class="line">    ListNode cur1 = head1;</span><br><span class="line">    <span class="keyword">int</span> length = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> (cur1.next != <span class="keyword">null</span>) &#123;</span><br><span class="line">        length++;</span><br><span class="line">        cur1 = cur1.next;</span><br><span class="line">    &#125;</span><br><span class="line">    ListNode cur2 = head2;</span><br><span class="line">    <span class="keyword">while</span> (cur2.next != <span class="keyword">null</span>) &#123;</span><br><span class="line">        length--;</span><br><span class="line">        cur2 = cur2.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (cur1 != cur2) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//短的先走</span></span><br><span class="line">    ListNode first = head1;</span><br><span class="line">    ListNode second = head2;</span><br><span class="line">    <span class="keyword">if</span> (length &lt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;Math.abs(length);i++) &#123;</span><br><span class="line">            second = second.next;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;length;i++) &#123;</span><br><span class="line">            first = first.next;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//同时走，寻找相交点</span></span><br><span class="line">    <span class="keyword">while</span> (first != second) &#123;</span><br><span class="line">        first = first.next;</span><br><span class="line">        second = second.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> first;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">       * 寻找环的入口处</span></span><br><span class="line"><span class="comment">       * */</span></span><br><span class="line"><span class="comment">//寻找环的入口点</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">detectCycle</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(head==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ListNode interact = getInteract(head);</span><br><span class="line">    <span class="keyword">if</span>(interact==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ListNode first = head;</span><br><span class="line">    ListNode second = interact;</span><br><span class="line">    <span class="keyword">while</span>(first!=second)&#123;</span><br><span class="line">        first = first.next;</span><br><span class="line">        second = second.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> first;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//寻找相遇点</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">getInteract</span><span class="params">(ListNode head)</span></span>&#123;</span><br><span class="line">    ListNode slow = head;</span><br><span class="line">    ListNode fast = head;</span><br><span class="line">    <span class="keyword">while</span>(fast!=<span class="keyword">null</span>&amp;&amp;fast.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        fast = fast.next.next;</span><br><span class="line">        slow = slow.next;</span><br><span class="line">        <span class="keyword">if</span>(fast==slow)&#123;</span><br><span class="line">            <span class="keyword">return</span> fast;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="哑节点问题"><a href="#哑节点问题" class="headerlink" title="哑节点问题"></a>哑节点问题</h2><p>假如<strong>需要操纵节点的前置节点</strong>，那么在头节点前面添加一个哑节点。</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></pre></td><td class="code"><pre><span class="line"><span class="comment">//跳出while循环，此时cur指向的是最后一个节点</span></span><br><span class="line"><span class="keyword">while</span>(cur.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;19-删除链表的倒数第N个节点&quot;&gt;&lt;a href=&quot;#19-删除链表的倒数第N个节点&quot; class=&quot;headerlink&quot; title=&quot;19.删除链表的倒数第N个节点&quot;&gt;&lt;/a&gt;19.删除链表的倒数第N个节点&lt;/h2&gt;&lt;p&gt;给定一个链表，删除链表的倒数第 &lt;e
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>数据库原理</title>
    <link href="http://yoursite.com/2019/11/04/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%9F%E7%90%86/"/>
    <id>http://yoursite.com/2019/11/04/数据库原理/</id>
    <published>2019-11-04T12:45:29.000Z</published>
    <updated>2019-11-05T09:55:37.025Z</updated>
    
    <content type="html"><![CDATA[<h1 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h1><p>一个数据库事务通常包含对数据库进行读或写的一个操作序列。</p><p>事务有四大特性：原子性，一致性，持久性，隔离性。</p><p><strong>事务就是由一跳或者多条SQL语句组成的，事务中的操作要么不做，要么全做。</strong></p><h2 id="ACID"><a href="#ACID" class="headerlink" title="ACID"></a>ACID</h2><h3 id="原子性"><a href="#原子性" class="headerlink" title="原子性"></a>原子性</h3><p>事务的所有操作<strong>要么全部执行成功，要么全部失败回滚</strong>。要做就全做，不然不做。</p><p>回滚可以用回滚日志来实现，回滚日志记录着事务所执行的修改操作，在回滚时反向执行这些修改操作即可。</p><h3 id="一致性"><a href="#一致性" class="headerlink" title="一致性"></a>一致性</h3><p>事务应确保数据库的状态从一个一致状态转变为另一个一致状态。在事务开始之前以及事务结束之后，<strong>数据库的完整性约束没有被破坏</strong>。</p><h3 id="隔离性"><a href="#隔离性" class="headerlink" title="隔离性"></a>隔离性</h3><p>隔离性是当多个用户并发访问数据库时，比如操作同一张表时，数据库为每一个用户开启的事务，不能被其他事务的操作所干扰，多个并发事务之间要相互隔离。</p><h3 id="持久性"><a href="#持久性" class="headerlink" title="持久性"></a>持久性</h3><p>一旦事务提交，则其所做的修改将会永远保存到数据库中。即使系统发生崩溃，事务执行的结果也不能丢失。</p><p>使用重做日志来保证持久性。</p><h2 id="事务分类"><a href="#事务分类" class="headerlink" title="事务分类"></a>事务分类</h2><p>主要分为扁平事务，带保存点的扁平事务，链事务，嵌套事务，分布式事务。</p><h3 id="扁平事务"><a href="#扁平事务" class="headerlink" title="扁平事务"></a>扁平事务</h3><p>begin work 开始，commit work或者rollback work结束。</p><p>要么都执行，要么从头开始回滚。</p><p><strong>他的限制是无法回滚或者提交数据的一部分，一旦回滚就得回滚所有</strong>。</p><h3 id="带保存点的事务"><a href="#带保存点的事务" class="headerlink" title="带保存点的事务"></a>带保存点的事务</h3><p>回滚操作可以选择回滚到某一个保存点。rollback work: 2，回滚到第二个保存点。</p><h2 id="并发事务带来的问题"><a href="#并发事务带来的问题" class="headerlink" title="并发事务带来的问题"></a>并发事务带来的问题</h2><p>多个事务并发执行，经常会发生多个事务操作相同的数据，这就会导致一定的一致性问题。</p><h3 id="丢失修改"><a href="#丢失修改" class="headerlink" title="丢失修改"></a>丢失修改</h3><p>T1 和 T2 两个事务都对一个数据进行修改，T1 先修改，T2 随后修改，T2 的修改覆盖了 T1 的修改。T1再读取的时候就不是自己修改的数据了，而是T2修改之后的。</p><p><a href="https://camo.githubusercontent.com/d780b004d38b8d8270b27b15282dea5bed88d440/68747470733a2f2f63732d6e6f7465732d313235363130393739362e636f732e61702d6775616e677a686f752e6d7971636c6f75642e636f6d2f37353138346235382d633632372d346564632d386463662d3630353736326562623733332e706e67" target="_blank" rel="noopener"><img src="/images/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%9F%E7%90%86/68747470733a2f2f63732d6e6f7465732d313235363130393739362e636f732e61702d6775616e677a686f752e6d7971636c6f75642e636f6d2f37353138346235382d633632372d346564632d386463662d3630353736326562623733332e706e67.png" alt="img"></a></p><h3 id="读脏数据"><a href="#读脏数据" class="headerlink" title="读脏数据"></a>读脏数据</h3><p>T1 修改一个数据，T2 随后读取这个数据。如果 T1 撤销了这次修改，那么 T2 读取的数据是脏数据。</p><p><a href="https://camo.githubusercontent.com/fbb1a9dc084bca74f89434f6642cd21508ae26cf/68747470733a2f2f63732d6e6f7465732d313235363130393739362e636f732e61702d6775616e677a686f752e6d7971636c6f75642e636f6d2f61663065393464392d353032642d343533312d393338662d6434366464323964653532642e706e67" target="_blank" rel="noopener"><img src="/images/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%9F%E7%90%86/68747470733a2f2f63732d6e6f7465732d313235363130393739362e636f732e61702d6775616e677a686f752e6d7971636c6f75642e636f6d2f61663065393464392d353032642d343533312d393338662d6434366464323964653532642e706e67.png" alt="img"></a></p><h3 id="不可重复读"><a href="#不可重复读" class="headerlink" title="不可重复读"></a>不可重复读</h3><p>指在一个事务内多次读同一数据。在这个事务还没有结束时，另一个事务也访问该数据。那么，在第一个事务中的两次读数据之间，由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况，因此称为不可重复读。</p><p><a href="https://camo.githubusercontent.com/f2e8d99ddd25f1dc8680634c7ec0be20a03ddb7e/68747470733a2f2f63732d6e6f7465732d313235363130393739362e636f732e61702d6775616e677a686f752e6d7971636c6f75642e636f6d2f36366165313634632d616434372d343930352d383935652d3531666533386365373937612e706e67" target="_blank" rel="noopener"><img src="/images/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%9F%E7%90%86/68747470733a2f2f63732d6e6f7465732d313235363130393739362e636f732e61702d6775616e677a686f752e6d7971636c6f75642e636f6d2f36366165313634632d616434372d343930352d383935652d3531666533386365373937612e706e67.png" alt="img"></a></p><h3 id="幻影读"><a href="#幻影读" class="headerlink" title="幻影读"></a>幻影读</h3><p> 幻读与不可重复读类似。它发生在一个事务（T1）读取了几行数据，接着另一个并发事务（T2）插入了一些数据时。在随后的查询中，第一个事务（T1）就会发现多了一些原本不存在的记录，就好像发生了幻觉一样，所以称为幻读。</p><p><img src="/images/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%9F%E7%90%86/68747470733a2f2f63732d6e6f7465732d313235363130393739362e636f732e61702d6775616e677a686f752e6d7971636c6f75642e636f6d2f38666463353737642d353532642d346234332d623565342d6138663938626332636235312e706e67.png" alt="img"></p><p><strong>不可重复读的重点是修改</strong>，<strong>幻读的重点在于新增或者删除</strong>。</p><h2 id="事务隔离级别"><a href="#事务隔离级别" class="headerlink" title="事务隔离级别"></a>事务隔离级别</h2><p>通过事务隔离可以解决上面的问题。</p><h3 id="读取未提交"><a href="#读取未提交" class="headerlink" title="读取未提交"></a>读取未提交</h3><p>最低的隔离级别，即使没有提交，其他事务对于该事务操作也是可见的。</p><p><strong>可能会导致脏读、幻读或不可重复读</strong>。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;事务&quot;&gt;&lt;a href=&quot;#事务&quot; class=&quot;headerlink&quot; title=&quot;事务&quot;&gt;&lt;/a&gt;事务&lt;/h1&gt;&lt;p&gt;一个数据库事务通常包含对数据库进行读或写的一个操作序列。&lt;/p&gt;
&lt;p&gt;事务有四大特性：原子性，一致性，持久性，隔离性。&lt;/p&gt;
&lt;p&gt;&lt;s
      
    
    </summary>
    
      <category term="数据库" scheme="http://yoursite.com/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
    
      <category term="数据库" scheme="http://yoursite.com/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
  </entry>
  
  <entry>
    <title>leetcode之二分查找问题</title>
    <link href="http://yoursite.com/2019/11/03/leetcode%E4%B9%8B%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E9%97%AE%E9%A2%98/"/>
    <id>http://yoursite.com/2019/11/03/leetcode之二分查找问题/</id>
    <published>2019-11-03T12:13:33.000Z</published>
    <updated>2020-01-08T08:30:24.070Z</updated>
    
    <content type="html"><![CDATA[<ul><li>单调性问题</li><li>存在着两段性的性质，即一半满足某一个性质，另一半不满足某个性质。</li></ul><p>均可以使用二分查找。</p><p><img src="/images/leetcode%E4%B9%8B%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E9%97%AE%E9%A2%98/1575181703866.png" alt="1575181703866"></p><p>红色表示满足某一个性质，绿色表示不满足某一个性质。</p><h3 id="模板一"><a href="#模板一" class="headerlink" title="模板一"></a>模板一</h3><p>求红色的右边界情况。</p><p>if mid in 红    [L,R]-&gt;[M,R]  L=M</p><p>else  mid in 绿   [L,R]-&gt;[L,M-1] R=M-1</p><p>注意，mid应该是取(L+R)/2+1，防止死循环</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><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span>(l&lt;r)&#123;</span><br><span class="line">    <span class="keyword">int</span> mid = start+(end-start+<span class="number">1</span>)/<span class="number">2</span>;</span><br><span class="line">    <span class="keyword">if</span>(check(mid))&#123;</span><br><span class="line">        l = mid;</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        r = mid-<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> l;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="模板二"><a href="#模板二" class="headerlink" title="模板二"></a>模板二</h3><p>求绿色的左边界情况</p><p>if mid in 绿  [L,R]-&gt;[L,M]  R=M</p><p>else mid in 红  [L,R]-&gt;[M+1,R] L=M+1</p><p>mid取值是(L+R)/2</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><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span>(l&lt;r)&#123;</span><br><span class="line">    <span class="keyword">int</span> mid = l+(r-l)/<span class="number">2</span>;</span><br><span class="line">    <span class="keyword">if</span>(check(mid))&#123;</span><br><span class="line">        r = mid;</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        l = mid+<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> l;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="二分流程"><a href="#二分流程" class="headerlink" title="二分流程"></a>二分流程</h3><p>确定二分边界：left = 0,right=x</p><p>编写二分代码框架</p><p>设定一个性质</p><p>判断区间如何更新</p><p>如果更新方式是l=mid,r=mid-1，那么mid上取整</p><h2 id="69-求开方"><a href="#69-求开方" class="headerlink" title="69.求开方"></a>69.求开方</h2><p>按照框架来做：</p><p>设定一个性质：t*t&lt;=x</p><p>区间如何更新：满足区间的右边界点</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><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//check:mid*mid&lt;=target 取左侧边界 </span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">mySqrt</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(x&lt;=<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> x;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> left = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> right = x;</span><br><span class="line">    <span class="keyword">while</span>(left&lt;right)&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = left+(right-left+<span class="number">1</span>)/<span class="number">2</span>;</span><br><span class="line">        <span class="comment">//防止溢出</span></span><br><span class="line">        <span class="keyword">if</span>(mid&lt;=x/mid)&#123;</span><br><span class="line">            left = mid;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            right = mid-<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> left;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="35-搜索插入位置？"><a href="#35-搜索插入位置？" class="headerlink" title="35.搜索插入位置？"></a>35.搜索插入位置？</h2><p><strong>边界判断</strong></p><p>给定一个排序数组和一个目标值，在数组中找到目标值，并返回其索引。如果目标值不存在于数组中，返回它将会被按顺序插入的位置。</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><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></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">searchInsert</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(nums[nums.length-<span class="number">1</span>]&lt;target)&#123;</span><br><span class="line">        <span class="keyword">return</span> nums.length;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//设定一个性质，t&gt;=target，所以取右侧的左边界点</span></span><br><span class="line">    <span class="keyword">int</span> l = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> r = nums.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(l&lt;r)&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = l+(r-l)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>(nums[mid]&gt;=target)&#123;</span><br><span class="line">            r= mid;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            l = mid+<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> l;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="34-在排序数组中查找元素的第一个和最后一个位置"><a href="#34-在排序数组中查找元素的第一个和最后一个位置" class="headerlink" title="34. 在排序数组中查找元素的第一个和最后一个位置"></a>34. 在排序数组中查找元素的第一个和最后一个位置</h2><p>给定一个按照升序排列的整数数组 <code>nums</code>，和一个目标值 <code>target</code>。找出给定目标值在数组中的开始位置和结束位置.</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><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="keyword">int</span>[] searchRange(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target) &#123;</span><br><span class="line">    <span class="keyword">if</span>(nums.length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[]&#123;-<span class="number">1</span>,-<span class="number">1</span>&#125;;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span>[] res = <span class="keyword">new</span> <span class="keyword">int</span>[<span class="number">2</span>];</span><br><span class="line">    <span class="comment">//寻找左边界，check:nums[mid]&lt;target  右侧的边界点作为结果</span></span><br><span class="line">    <span class="keyword">int</span> l= <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> r= nums.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span> (l&lt;r)&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = l+(r-l)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>(nums[mid]&lt;target)&#123;</span><br><span class="line">            l = mid+<span class="number">1</span>;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            r = mid;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(nums[left]!=target)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[]&#123;-<span class="number">1</span>,-<span class="number">1</span>&#125;;</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">        res[<span class="number">0</span>] = left;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//寻找右边界.check:nums[mid]&lt;=target, 左侧的边界点作为结果</span></span><br><span class="line">    l = <span class="number">0</span>;</span><br><span class="line">    r = nums.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(l&lt;r)&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = l+(r-l+<span class="number">1</span>)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>(nums[mid]&lt;=target)&#123;</span><br><span class="line">            l = mid;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            r = mid-<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    res[<span class="number">1</span>] = left;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="74-搜索二维矩阵"><a href="#74-搜索二维矩阵" class="headerlink" title="74.搜索二维矩阵"></a>74.搜索二维矩阵</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></pre></td><td class="code"><pre><span class="line"><span class="comment">//check:nums[mid]&lt;=target 左侧边界值</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">searchMatrix</span><span class="params">(<span class="keyword">int</span>[][] matrix, <span class="keyword">int</span> target)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(matrix.length==<span class="number">0</span>||matrix[<span class="number">0</span>].length==<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> l = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> m = matrix.length;</span><br><span class="line">    <span class="keyword">int</span> n = matrix[<span class="number">0</span>].length;</span><br><span class="line">    <span class="keyword">int</span> r = m*n-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(l&lt;r)&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = l+(r-l+<span class="number">1</span>)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">int</span> first_dim = mid/n;</span><br><span class="line">        <span class="keyword">int</span> second_dim = mid%n;</span><br><span class="line">        <span class="keyword">if</span>(matrix[first_dim][second_dim]&lt;=target)&#123;</span><br><span class="line">            l = mid;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            r = mid-<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> matrix[l/n][l%n]==target;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="162-寻找峰值"><a href="#162-寻找峰值" class="headerlink" title="162.寻找峰值"></a>162.寻找峰值</h2><p>峰值元素是指其值大于左右相邻值的元素。</p><p>给定一个输入数组 nums，其中 nums[i] ≠ nums[i+1]，找到峰值元素并返回其索引。</p><p>数组可能包含多个峰值，在这种情况下，返回任何一个峰值所在位置即可。</p><p>你可以假设 nums[-1] = nums[n] = -∞。</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 寻找峰值元素，当nums[mid]&lt;nums[mid+1]时，表明mid右侧是有增加的，因为nums[n] = -∞，</span></span><br><span class="line"><span class="comment">     * 所以mid右侧必定会有一个峰值点</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">findPeakElement</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> left = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> right = nums.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(left&lt;right)&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = left+(right-left)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>(nums[mid]&lt;=nums[mid+<span class="number">1</span>])&#123;</span><br><span class="line">            left = mid+<span class="number">1</span>;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            right = mid;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> left;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="基本的二分查找"><a href="#基本的二分查找" class="headerlink" title="基本的二分查找"></a>基本的二分查找</h2><p>搜索一个数。</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><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></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">binarySearch</span><span class="params">(<span class="keyword">int</span> [] arr,<span class="keyword">int</span> val)</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> start = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> end = arr.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(start&lt;=end)&#123;<span class="comment">//</span></span><br><span class="line">        <span class="keyword">int</span> mid = start+(end-start)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>(arr[mid]&gt;val)&#123;</span><br><span class="line">            end = mid-<span class="number">1</span>;<span class="comment">//</span></span><br><span class="line">        &#125;<span class="keyword">else</span> <span class="keyword">if</span>(arr[mid]&lt;val)&#123;</span><br><span class="line">            start = end+<span class="number">1</span>;<span class="comment">//</span></span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> mid;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="744-寻找比目标字母大的最小字母"><a href="#744-寻找比目标字母大的最小字母" class="headerlink" title="744.寻找比目标字母大的最小字母"></a>744.寻找比目标字母大的最小字母</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></pre></td><td class="code"><pre><span class="line"><span class="comment">//check:letters[mid]&lt;=target 右侧边界</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">char</span> <span class="title">nextGreatestLetter</span><span class="params">(<span class="keyword">char</span>[] letters, <span class="keyword">char</span> target)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(target&gt;=letters[letters.length-<span class="number">1</span>])&#123;</span><br><span class="line">        <span class="keyword">return</span> letters[<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> start = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> end = letters.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span> (start&lt;end)&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = start+(end-start)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>(letters[mid]&lt;=target)&#123;</span><br><span class="line">            start = mid+<span class="number">1</span>;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            end = mid;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> letters[start];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="540-有序数组的-Single-Element"><a href="#540-有序数组的-Single-Element" class="headerlink" title="540.有序数组的 Single Element"></a>540.有序数组的 Single Element</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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 给定一个只包含整数的有序数组，每个元素都会出现两次，唯有一个数只会出现一次，找出这个数</span></span><br><span class="line"><span class="comment"> * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">singleNonDuplicate</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//当数组长度为1的时候</span></span><br><span class="line">    <span class="keyword">if</span>(nums.length==<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> nums[<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//当单一元素在第一个位置或者在最后一个位置</span></span><br><span class="line">    <span class="keyword">if</span>(nums[<span class="number">0</span>]!=nums[<span class="number">1</span>])&#123;</span><br><span class="line">        <span class="keyword">return</span> nums[<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(nums[nums.length-<span class="number">1</span>]!=nums[nums.length-<span class="number">2</span>])&#123;</span><br><span class="line">        <span class="keyword">return</span> nums[nums.length-<span class="number">1</span>];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> start = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> end = nums.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(start&lt;end)&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = start+(end - start)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>((nums[mid]!=nums[mid-<span class="number">1</span>])&amp;&amp;(nums[mid]!=nums[mid+<span class="number">1</span>]))&#123;</span><br><span class="line">            <span class="keyword">return</span> nums[mid];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">/**mid为偶数，前面必定是偶数，因此，当nums[mid] == nums[mid-1]， （奇数个） 3 3，因此，单个元素必定在前半段</span></span><br><span class="line"><span class="comment">             * 当nums[mid] != nums[mid-1]， （奇数个）2 3，因此，单个元素必定在后半段</span></span><br><span class="line"><span class="comment">             * mid</span></span><br><span class="line"><span class="comment">             * **/</span></span><br><span class="line">        <span class="keyword">if</span> (mid % <span class="number">2</span> == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span>(nums[mid] == nums[mid-<span class="number">1</span>]) &#123;</span><br><span class="line">                end = mid -<span class="number">1</span>;</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                start = mid;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">/**mid 为奇数，前面必定为奇数，因此，当nums[mid] == nums[mid-1]， （偶数个） 3 3，因此，单个元素必定在后半段</span></span><br><span class="line"><span class="comment">             * 当nums[mid] != nums[mid-1]， （偶数个）2 3，因此，单个元素必定在前</span></span><br><span class="line"><span class="comment">             *</span></span><br><span class="line"><span class="comment">             * */</span></span><br><span class="line">        <span class="keyword">if</span> (mid % <span class="number">2</span> == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span>(nums[mid] == nums[mid-<span class="number">1</span>]) &#123;</span><br><span class="line">                start = mid;</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                end = mid-<span class="number">1</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="153-旋转数组的最小数字"><a href="#153-旋转数组的最小数字" class="headerlink" title="153.旋转数组的最小数字?"></a>153.旋转数组的最小数字?</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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 假设按照升序排序的数组在预先未知的某个点上进行了旋转。</span></span><br><span class="line"><span class="comment"> * ( 例如，数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。</span></span><br><span class="line"><span class="comment"> * 请找出其中最小的元素。</span></span><br><span class="line"><span class="comment"> * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">findMin</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//假如nums[mid]&gt;最后一个元素，那么必定在[mid+1,r]之间</span></span><br><span class="line">    <span class="keyword">int</span> l = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> r = nums.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span> (l&lt;r)&#123;</span><br><span class="line">        <span class="keyword">int</span> mid = l+(r-l)/<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>(nums[mid]&gt;nums[r])&#123;</span><br><span class="line">            l = mid+<span class="number">1</span>;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            r = mid;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> nums[l];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;ul&gt;
&lt;li&gt;单调性问题&lt;/li&gt;
&lt;li&gt;存在着两段性的性质，即一半满足某一个性质，另一半不满足某个性质。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;均可以使用二分查找。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/leetcode%E4%B9%8B%E4%BA%8C%E5%88%
      
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>leetcode之双指针问题</title>
    <link href="http://yoursite.com/2019/11/02/leetcode%E4%B9%8B%E5%8F%8C%E6%8C%87%E9%92%88%E9%97%AE%E9%A2%98/"/>
    <id>http://yoursite.com/2019/11/02/leetcode之双指针问题/</id>
    <published>2019-11-02T07:07:02.000Z</published>
    <updated>2020-01-08T08:51:23.999Z</updated>
    
    <content type="html"><![CDATA[<p>shuangzhi双指针可以将时间复杂度从O(n*n)到o(n)</p><p>而在双指针的概念中，我们可以将双指针分为两种类型：快慢指针、相向指针，同向指针。</p><blockquote><p>左右指针中间夹，快慢指针走到头，后序指针往回走.</p></blockquote><a id="more"></a><h2 id="快慢指针"><a href="#快慢指针" class="headerlink" title="快慢指针"></a>快慢指针</h2><p>快慢指针，顾名思义就是在使用时朝相同方向移动，<strong>一个指针的移动速度慢而另一个指针移动速度快</strong>，通过两个指针之间的移动所带来的差值，从而确定应用指针所在的数据结构中的某些数据或规律。</p><h3 id="142-找出环型链表的入口处"><a href="#142-找出环型链表的入口处" class="headerlink" title="142.找出环型链表的入口处"></a>142.找出环型链表的入口处</h3><p>判断是否有环。</p><ul><li>准备两个指针，快指针一次走两步，慢指针一次走一步。</li><li>假如链表中有环的话，那么两个指针一定会相遇。</li></ul><p>寻找入口处。</p><p><img src="/images/leetcode%E4%B9%8B%E5%8F%8C%E6%8C%87%E9%92%88%E9%97%AE%E9%A2%98/99987d4e679fdfbcfd206a4429d9b076b46ad09bd2670f886703fb35ef130635-image.png" alt="image.png"></p><p>因为快指针一次两步，慢指针一次一步，所以快指针走的距离始终是慢指针的两倍。fast = 2*slow</p><p>即：<br>$$<br>2<em>(F+a) = F+n(a+b)+a,n为快指针跑了多少圈<br>$$<br>即：<br>$$<br>F = (n-1)</em>(a+b)+b<br>$$<br>因为a+b就是一圈环，所以，我们直接就可以看作F = b，即从头节点到入口处 = 第一次相遇点到入口处。</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><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="comment">/**</span></span><br><span class="line"><span class="comment">     * 判断链表中一个环的入口处</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">getInteract</span><span class="params">(ListNode head)</span></span>&#123;</span><br><span class="line">    <span class="comment">//注意判断head是否为null</span></span><br><span class="line">    <span class="keyword">if</span>(head==<span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    ListNode slow = head;</span><br><span class="line">    ListNode fast = head;</span><br><span class="line">    <span class="keyword">while</span>(fast!=<span class="keyword">null</span>&amp;&amp;fast.next!=<span class="keyword">null</span>)&#123;</span><br><span class="line">        slow = slow.next;</span><br><span class="line">        fast = fast.next.next;</span><br><span class="line">        <span class="keyword">if</span>(fast==slow)&#123;</span><br><span class="line">            <span class="keyword">return</span> fast;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> ListNode <span class="title">detectCycle</span><span class="params">(ListNode head)</span> </span>&#123;</span><br><span class="line">    ListNode interact = getInteract(head);</span><br><span class="line">    <span class="keyword">if</span>(interact==<span class="keyword">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    ListNode start = head;</span><br><span class="line">    <span class="keyword">while</span>(start!=interact)&#123;</span><br><span class="line">        start=start.next;</span><br><span class="line">        interact=interact.next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> start;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>参考：<a href="https://leetcode-cn.com/problems/linked-list-cycle-ii/solution/huan-xing-lian-biao-ii-by-leetcode/" target="_blank" rel="noopener">环型链表官方题解</a></p><h2 id="头尾指针"><a href="#头尾指针" class="headerlink" title="头尾指针"></a>头尾指针</h2><h3 id="有序数组的-Two-Sum"><a href="#有序数组的-Two-Sum" class="headerlink" title="有序数组的 Two Sum"></a>有序数组的 Two Sum</h3><p>题目描述：在有序数组中找出两个数，使它们的和为 target。</p><p>通过头尾指针来解决。</p><p>当头指针+尾指针&gt;value，尾指针–；</p><p>当头指针+尾指针&lt;value，头指针++；</p><p>两者相等，返回。</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使用头尾指针来解决</span></span><br><span class="line"><span class="comment">     * 当头+尾&gt;target,头指针左移</span></span><br><span class="line"><span class="comment">     * 当头+尾&lt;target，头指针右移</span></span><br><span class="line"><span class="comment">     * 头+尾=target，所求结果</span></span><br><span class="line"><span class="comment">     * */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">int</span>[] calTwoSum(<span class="keyword">int</span>[] numbers, <span class="keyword">int</span> target) &#123;</span><br><span class="line">    <span class="keyword">int</span> head = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> tail = numbers.length-<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span>[] result ;</span><br><span class="line">    <span class="keyword">while</span>(head&lt;tail)&#123;</span><br><span class="line">        <span class="keyword">if</span>(numbers[head]+numbers[tail]&lt;target)</span><br><span class="line">            head++;</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span>(numbers[head]+numbers[tail]&gt;target)</span><br><span class="line">            tail--;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[]&#123;head,tail&#125;;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="两数平方和"><a href="#两数平方和" class="headerlink" title="两数平方和"></a>两数平方和</h3><p>题目描述：判断一个非负整数是否为两个整数的平方和。</p><p>可以看成是在元素为 0~target 的有序数组中查找两个数，使得这两个数的平方和为 target，如果能找到，则返回 true，表示 target 是两个整数的平方和。</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *给定一个非负整数 c ，你要判断是否存在两个整数 a 和 b，使得a^2 + b^2 = c。</span></span><br><span class="line"><span class="comment"> * 使用头尾指针来解决</span></span><br><span class="line"><span class="comment"> * 取head = 0，tail = sqrt(c)</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">judgeSquareSum</span><span class="params">(<span class="keyword">int</span> c)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(c&lt;<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> head = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> tail = (<span class="keyword">int</span>)Math.sqrt(c);</span><br><span class="line">    <span class="keyword">while</span>(head&lt;=tail)&#123;</span><br><span class="line">        <span class="keyword">if</span>(head*head+tail*tail&lt;c)</span><br><span class="line">            head++;</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span>(head*head+tail*tail&gt;c)</span><br><span class="line">            tail--;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="回文字符串"><a href="#回文字符串" class="headerlink" title="回文字符串"></a>回文字符串</h3><p>题目描述：可以删除一个字符，判断是否能构成回文字符串。</p><p>所谓的回文字符串，是指具有左右对称特点的字符串，例如 “abcba” 就是一个回文字符串。</p><p><strong>使用双指针可以很容易判断一个字符串是否是回文字符串</strong>：令一个指针从左到右遍历，一个指针从右到左遍历，这两个指针同时移动一个位置，每次都判断两个指针指向的字符是否相同，如果都相同，字符串才是具有左右对称性质的回文字符串。</p><p>本题的关键是处理删除一个字符。在使用双指针遍历字符串时，如果出现两个指针指向的字符不相等的情况，我们就试着删除一个字符，再判断删除完之后的字符串是否是回文字符串。</p><p>在判断是否为回文字符串时，我们不需要判断整个字符串，因为左指针左边和右指针右边的字符之前已经判断过具有对称性质，所以只需要判断中间的子字符串即可。</p><p>在试着删除字符时，我们既可以删除左指针指向的字符，也可以删除右指针指向的字符。</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><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">validPalindrome</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> head = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> tail = s.length()-<span class="number">1</span>;</span><br><span class="line">    <span class="comment">/***假如头尾指针相等，继续移动</span></span><br><span class="line"><span class="comment">         * 头尾指针不等，分别删除head以及tail元素，看剩下的是否是回文的。</span></span><br><span class="line"><span class="comment">         * */</span></span><br><span class="line">    <span class="keyword">while</span>(head&lt;tail)&#123;</span><br><span class="line">        <span class="keyword">if</span>(s.charAt(head)==s.charAt(tail))&#123;</span><br><span class="line">            head++;</span><br><span class="line">            tail--;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="comment">//判断删除了一个字符会不会回文，两种情况，删除左指针以及右指针</span></span><br><span class="line">            <span class="keyword">return</span> (isPalindrome(s,head+<span class="number">1</span>,tail)||isPalindrome(s,head,tail-<span class="number">1</span>));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isPalindrome</span><span class="params">(String s,<span class="keyword">int</span> start,<span class="keyword">int</span> end)</span></span>&#123;</span><br><span class="line">    <span class="keyword">while</span> (start&lt;end)&#123;</span><br><span class="line">        <span class="keyword">if</span>(s.charAt(start)==s.charAt(end))&#123;</span><br><span class="line">            start++;</span><br><span class="line">            end--;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="两个头指针"><a href="#两个头指针" class="headerlink" title="两个头指针"></a>两个头指针</h2><h3 id="最长子序列-524"><a href="#最长子序列-524" class="headerlink" title="最长子序列(524)"></a>最长子序列(524)</h3><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><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 给定一个字符串和一个字符串字典，找到字典里面最长的字符串，该字符串可以通过删除给定字符串的某些字符来得到。</span></span><br><span class="line"><span class="comment"> * 如果答案不止一个，返回长度最长且字典顺序最小的字符串。如果答案不存在，则返回空字符串。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * **/</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">findLongestWord</span><span class="params">(String s, List&lt;String&gt; d)</span> </span>&#123;</span><br><span class="line">    String result = <span class="string">""</span>;</span><br><span class="line">    <span class="keyword">if</span>(s.equals(<span class="string">""</span>))&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">""</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(String ele:d)&#123;</span><br><span class="line">        <span class="keyword">if</span>(ele!=<span class="keyword">null</span>&amp;&amp;!(ele.equals(<span class="string">""</span>))&amp;&amp;isSub(s,ele))&#123;</span><br><span class="line">            <span class="keyword">if</span>(ele.length()&gt;result.length())&#123;</span><br><span class="line">                result=ele;</span><br><span class="line">            &#125;<span class="keyword">else</span> <span class="keyword">if</span>(ele.length()==result.length())&#123;</span><br><span class="line">                <span class="keyword">if</span>(ele.compareTo(result)&lt;<span class="number">0</span>)&#123;</span><br><span class="line">                    result = ele;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**判断一个字符串是不是另一个字符串</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">subLength</span><span class="params">(String s ,String ele)</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> sHead = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> eleHead = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> length = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span>(eleHead&lt;ele.length()&amp;&amp;sHead&lt;s.length())&#123;</span><br><span class="line">        <span class="keyword">if</span>(s.charAt(sHead)==ele.charAt(eleHead))&#123;</span><br><span class="line">            length++;</span><br><span class="line">            sHead++;</span><br><span class="line">            eleHead++;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            sHead++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> ele.length()==length;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="26-删除排序数组中的重复项"><a href="#26-删除排序数组中的重复项" class="headerlink" title="26. 删除排序数组中的重复项?"></a><a href="https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/" target="_blank" rel="noopener">26. 删除排序数组中的重复项</a>?</h3><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></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">removeDuplicates</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(nums.length&lt;=<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> nums.length;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> first = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> second = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(second&lt;nums.length)&#123;</span><br><span class="line">        <span class="keyword">if</span>(nums[first]==nums[second])&#123;</span><br><span class="line">            second++;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            first++;</span><br><span class="line">            nums[first] = nums[second];</span><br><span class="line">            second++;</span><br><span class="line">            index++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> first+<span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>基础技巧：分治、二分、贪心</li><li>排序算法：快速排序、归并排序、计数排序</li><li>搜索算法：回溯、递归、深度优先遍历，广度优先遍历，二叉搜索树等</li><li>图论：最短路径、最小生成树</li><li>动态规划：背包问题、最长子序列</li></ul><p>数据结构，主要有如下几种：</p><ul><li>数组与链表：单 / 双向链表</li><li>栈与队列</li><li>哈希表</li><li>堆：最大堆 ／ 最小堆</li><li>树与图：最近公共祖先、并查集</li><li>字符串：前缀树（字典树） ／ 后缀树</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;shuangzhi双指针可以将时间复杂度从O(n*n)到o(n)&lt;/p&gt;
&lt;p&gt;而在双指针的概念中，我们可以将双指针分为两种类型：快慢指针、相向指针，同向指针。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;左右指针中间夹，快慢指针走到头，后序指针往回走.&lt;/p&gt;
&lt;/blockquote&gt;
    
    </summary>
    
      <category term="leetcode" scheme="http://yoursite.com/categories/leetcode/"/>
    
    
      <category term="leetcode" scheme="http://yoursite.com/tags/leetcode/"/>
    
  </entry>
  
</feed>
