Repository navigation
Expand file tree
/
Copy pathsearch.xml
More file actions
303 lines (146 loc) · 167 KB
/
Copy pathsearch.xml
File metadata and controls
303 lines (146 loc) · 167 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>子序列问题</title>
<link href="/%E5%AD%90%E5%BA%8F%E5%88%97%E9%97%AE%E9%A2%98/"/>
<url>/%E5%AD%90%E5%BA%8F%E5%88%97%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<h2 id="1-连续子序列"><a href="#1-连续子序列" class="headerlink" title="1. 连续子序列"></a>1. 连续子序列</h2><h4 id="1-和最大连续子序列"><a href="#1-和最大连续子序列" class="headerlink" title="1. 和最大连续子序列"></a>1. 和最大连续子序列</h4><ol><li>状态转移方程<code>dp[i] = Math.max(array[i], dp[i - 1] + array[i]);</code>dp[i - 1]若为负则会使总值变小所以直接为array[i];</li></ol><h6 id="1-LeetCode-53-最大子序和"><a href="#1-LeetCode-53-最大子序和" class="headerlink" title="1. LeetCode 53 (最大子序和)"></a>1. <a href="https://leetcode-cn.com/problems/maximum-subarray/" target="_blank" rel="noopener">LeetCode 53</a> (最大子序和)</h6><p>给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。</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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> <span class="keyword">int</span> len = nums.length;</span><br><span class="line"> <span class="keyword">int</span> currNum = nums[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">int</span> maxNum = 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">1</span>; i < len; i++) {</span><br><span class="line"> currNum = Math.max(currNum + nums[i], nums[i]);</span><br><span class="line"> maxNum = Math.max(maxNum, currNum);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> maxNum;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="2-乘积最大连续子序列"><a href="#2-乘积最大连续子序列" class="headerlink" title="2. 乘积最大连续子序列"></a>2. 乘积最大连续子序列</h4><ol><li>维护一个dpMax, 一个dpMin, 当`nums[i] < 0的时候交换dpMax, dpMin;</li></ol><h6 id="1-LeetCode-152-乘积最大子数组"><a href="#1-LeetCode-152-乘积最大子数组" class="headerlink" title="1. LeetCode 152 (乘积最大子数组)"></a>1. <a href="https://leetcode-cn.com/problems/maximum-product-subarray/solution/hua-jie-suan-fa-152-cheng-ji-zui-da-zi-xu-lie-by-g/" target="_blank" rel="noopener">LeetCode 152</a> (乘积最大子数组)</h6><p>给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。</p><p><strong>题解</strong><br>dp方程可以理解为若当前nums[i]可乘就乘,否则丢弃从当前nums[i]开始。代表当前位置最大子串。<br>本题可以维护一个dpMin一旦nums[i]是负数,则最大变最小,最小变最大,即可以交换dpMax, dpMin。</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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxProduct</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> len = nums.length;</span><br><span class="line"> <span class="keyword">int</span> dpMax = nums[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">int</span> dpMin = nums[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">int</span> maxNum = 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">1</span>; i < len; i++) {</span><br><span class="line"> <span class="keyword">if</span> (nums[i] < <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">int</span> temp = dpMax;</span><br><span class="line"> dpMax = dpMin;</span><br><span class="line"> dpMin = temp;</span><br><span class="line"> }</span><br><span class="line"> dpMax = Math.max(nums[i], dpMax * nums[i]);</span><br><span class="line"> dpMin = Math.min(nums[i], dpMin * nums[i]);</span><br><span class="line"> maxNum = Math.max(maxNum, dpMax);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> maxNum;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="3-含有某个值的最短连续子序列"><a href="#3-含有某个值的最短连续子序列" class="headerlink" title="3. 含有某个值的最短连续子序列"></a>3. 含有某个值的最短连续子序列</h4><ol><li><code>leftMap</code>第一次出现的索引位置,<code>rightMap</code>最后一次出现的索引位置;<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//只put第一次索引;</span></span><br><span class="line"><span class="keyword">if</span> (!leftMap.containsKey(nums[i])) {</span><br><span class="line"> leftMap.put(nums[i], i);</span><br><span class="line">}</span><br><span class="line"><span class="comment">//刷新索引,即最后一次索引;</span></span><br><span class="line">rightMap.put(nums[i], i);</span><br></pre></td></tr></table></figure><h6 id="1-LeetCode-697-数组的度"><a href="#1-LeetCode-697-数组的度" class="headerlink" title="1. LeetCode 697 (数组的度)"></a>1. <a href="https://leetcode-cn.com/problems/degree-of-an-array/solution/shu-zu-de-du-by-leetcode/" target="_blank" rel="noopener">LeetCode 697</a> (数组的度)</h6>给定一个非空且只包含非负数的整数数组 nums, 数组的度的定义是指数组里任一元素出现频数的最大值。</li></ol><p>你的任务是找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。<br><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><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">findShortestSubArray</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>{</span><br><span class="line"> HashMap<Integer, Integer> leftMap = <span class="keyword">new</span> HashMap<>();</span><br><span class="line"> HashMap<Integer, Integer> rightMap = <span class="keyword">new</span> HashMap<>();</span><br><span class="line"> HashMap<Integer, Integer> countMap = <span class="keyword">new</span> HashMap<>();</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < nums.length; i++) {</span><br><span class="line"> <span class="comment">//只put第一次索引;</span></span><br><span class="line"> <span class="keyword">if</span> (!leftMap.containsKey(nums[i])) {</span><br><span class="line"> leftMap.put(nums[i], i);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//刷新索引,即最后一次索引;</span></span><br><span class="line"> rightMap.put(nums[i], i);</span><br><span class="line"> countMap.put(nums[i], countMap.getOrDefault(nums[i], <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">int</span> maxCount = Collections.max(countMap.values());</span><br><span class="line"> <span class="keyword">int</span> minLen = Integer.MAX_VALUE;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> key : countMap.keySet()) {</span><br><span class="line"> <span class="keyword">if</span> (countMap.get(key) == maxCount) {</span><br><span class="line"> minLen = Math.min(minLen, rightMap.get(key) - leftMap.get(key) + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> minLen;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="4-最长01连续子序列"><a href="#4-最长01连续子序列" class="headerlink" title="4. 最长01连续子序列"></a>4. 最长01连续子序列</h4><ol><li>将0当做-1,则建一个count[], 保存每次和当前nums[i]加的结果;</li><li>count相等的两个索引之间0, 1数量是相等的;</li><li>所以map存放第一次出现的count值的索引,类似上题;</li><li>没出现一次map中有的count, 就比较当前索引和map里的索引的差值,最终保存最大的即为结果;</li></ol><h6 id="1-LeetCode-525-连续数组"><a href="#1-LeetCode-525-连续数组" class="headerlink" title="1. LeetCode 525 (连续数组)"></a>1. <a href="https://leetcode-cn.com/problems/contiguous-array/solution/lian-xu-shu-zu-by-leetcode/" target="_blank" rel="noopener">LeetCode 525</a> (连续数组)</h6><p>给定一个二进制数组, 找到含有相同数量的 0 和 1 的最长连续子数组(的长度)。</p><p><strong>题解</strong><br>用HashMap记录第一个count的index;(count : index);count相等代表第一次出现该count的索引到此索引之间的0, 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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><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>{</span><br><span class="line"> HashMap<Integer, Integer> map = <span class="keyword">new</span> HashMap<>();</span><br><span class="line"> map.put(<span class="number">0</span>, -<span class="number">1</span>); <span class="comment">//防止整个数组为子串的特例;</span></span><br><span class="line"> <span class="keyword">int</span> length = nums.length;</span><br><span class="line"> <span class="keyword">int</span> maxLen = <span class="number">0</span>, count = <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 < length; i++) {</span><br><span class="line"> count += (nums[i] == <span class="number">1</span>) ? <span class="number">1</span> : -<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (map.containsKey(count)) {</span><br><span class="line"> maxLen = Math.max(maxLen, i - map.get(count));</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> map.put(count, i);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> maxLen;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="2-子序列(非连续)"><a href="#2-子序列(非连续)" class="headerlink" title="2. 子序列(非连续)"></a>2. 子序列(非连续)</h2><h4 id="1-最长递增子序列"><a href="#1-最长递增子序列" class="headerlink" title="1. 最长递增子序列"></a>1. 最长递增子序列</h4><ol><li><p>动态规划,双循环,第二层循环如果<code>nums[i] > nums[j]</code>就遍历寻找[0, i) 之间最大的子序列并加上1;</p></li><li><p>否则不能加上nums[i], 即dp[j]的最大值就是dp[i]的值;</p></li><li><p>二分dp优化O(nlogn), 维护一个tail[]数组,当做每轮给这个最长序列增加的值,二分也是为了后序如果有更小的值就实时替换维护一个每个位置都最小的情况;</p></li><li><p>遍历nums时每次二分寻找到可以替换的值即比该数大的,如果没有则末尾追加一个,同时res++; 利用<code>right = mid</code>向左逼近;</p></li></ol><h6 id="1-LeetCode-300-最长上升子序列"><a href="#1-LeetCode-300-最长上升子序列" class="headerlink" title="1. LeetCode 300 (最长上升子序列)"></a>1. <a href="https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/zui-chang-shang-sheng-zi-xu-lie-dong-tai-gui-hua-2/" target="_blank" rel="noopener">LeetCode 300</a> (最长上升子序列)</h6><p><strong>题解一</strong><br>动态规划,双循环,第二层循环如果nums[i]大于nums[j]就遍历寻找[0, i) 之间最大的子序列并加上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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lengthOfLIS</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (nums.length == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</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"> Arrays.fill(dp, <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">int</span> res = <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 < nums.length; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j < i; j++) {</span><br><span class="line"> <span class="keyword">if</span> (nums[i] > nums[j]) {</span><br><span class="line"> dp[i] = Math.max(dp[i], dp[j] + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> res = Math.max(res, dp[i]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>题解二</strong><br>二分dp优化O(nlogn), 维护一个tail[]数组,遍历nums时每次二分寻找到可以替换的值即比该数大的,如果没有则末尾追加一个,同时res++; 利用<code>right = mid</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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lengthOfLIS</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (nums.length == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</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>[] tail = <span class="keyword">new</span> <span class="keyword">int</span>[nums.length];</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> num : nums) {</span><br><span class="line"> <span class="keyword">int</span> i = <span class="number">0</span>, j = res;</span><br><span class="line"> <span class="keyword">while</span> (i < j) {</span><br><span class="line"> <span class="keyword">int</span> mid = (i + j) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (num > tail[mid]) {</span><br><span class="line"> i = mid + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> j = mid;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//i == j;</span></span><br><span class="line"> tail[i] = num;</span><br><span class="line"> <span class="comment">//判断是否插在了末尾;</span></span><br><span class="line"> <span class="keyword">if</span> (j == res) {</span><br><span class="line"> res++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h6 id="2-LeetCode-354(俄罗斯套娃)"><a href="#2-LeetCode-354(俄罗斯套娃)" class="headerlink" title="2. LeetCode 354(俄罗斯套娃)"></a>2. <a href="https://leetcode-cn.com/problems/russian-doll-envelopes/solution/e-luo-si-tao-wa-xin-feng-wen-ti-by-leetcode/" target="_blank" rel="noopener">LeetCode 354</a>(俄罗斯套娃)</h6><p>给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。</p><p>请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。</p><blockquote><p>说明:<br>不允许旋转信封。</p></blockquote><p><strong>题解</strong><br>先按w升序排序,即可转化为h的最长子序列题,但w可能相等,这种情况就按h的降序排序,即筛掉w相等的情况;</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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">maxEnvelopes</span><span class="params">(<span class="keyword">int</span>[][] envelopes)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (envelopes.length == <span class="number">0</span> || envelopes[<span class="number">0</span>].length == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//排序;</span></span><br><span class="line"> Arrays.sort(envelopes, (<span class="keyword">int</span>[] arr1, <span class="keyword">int</span>[] arr2) -> {</span><br><span class="line"> <span class="keyword">if</span> (arr1[<span class="number">0</span>] == arr2[<span class="number">0</span>]) {</span><br><span class="line"> <span class="keyword">return</span> arr2[<span class="number">1</span>] - arr1[<span class="number">1</span>];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> arr1[<span class="number">0</span>] - arr2[<span class="number">0</span>];</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">int</span>[] sec = <span class="keyword">new</span> <span class="keyword">int</span>[envelopes.length];</span><br><span class="line"> <span class="comment">//遍历赋值所有的h;</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < envelopes.length; i++) {</span><br><span class="line"> sec[i] = envelopes[i][<span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> lis(sec);</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">int</span> <span class="title">lis</span><span class="params">(<span class="keyword">int</span>[] sec)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span>[] tail = <span class="keyword">new</span> <span class="keyword">int</span>[sec.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">for</span> (<span class="keyword">int</span> num : sec) {</span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">0</span>, right = res;</span><br><span class="line"> <span class="keyword">while</span> (left < right) {</span><br><span class="line"> <span class="keyword">int</span> mid = (left + right) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (tail[mid] < num) {</span><br><span class="line"> left = mid + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> right = mid;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> tail[left] = num;</span><br><span class="line"> <span class="keyword">if</span> (left == res) {</span><br><span class="line"> res++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="2-最长回文子序列"><a href="#2-最长回文子序列" class="headerlink" title="2. 最长回文子序列"></a>2. 最长回文子序列</h4><ol><li>二维动态规划,<code>dp[0][s.length() - 1]</code>代表该区间字符串的最长回文子序列;</li><li>先初始化<code>dp[i][i]</code>为1, 因为每个字母都是回文串;</li><li>从后往前遍历,<code>j = i + 1</code><ol><li>若<code>s.charAt(i) == s.charAt(j)</code>则转移方程为<code>dp[i][j] = dp[i + 1][j - 1] + 2</code></li><li>否则为<code>max(dp[i + 1][j], dp[i][j - 1])</code></li></ol></li></ol><h6 id="1-LeetCode-516-最长回文子序列"><a href="#1-LeetCode-516-最长回文子序列" class="headerlink" title="1. LeetCode 516 (最长回文子序列)"></a>1. <a href="https://leetcode-cn.com/problems/longest-palindromic-subsequence/" target="_blank" rel="noopener">LeetCode 516</a> (最长回文子序列)</h6><p>给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。可以假设 s 的最大长度为 1000</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><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">longestPalindromeSubseq</span><span class="params">(String s)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[s.length()][s.length()];</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < s.length(); i++) {</span><br><span class="line"> dp[i][i] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = s.length() - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = i + <span class="number">1</span>; j < s.length(); j++) {</span><br><span class="line"> <span class="keyword">if</span> (s.charAt(i) == s.charAt(j)) {</span><br><span class="line"> dp[i][j] = dp[i + <span class="number">1</span>][j - <span class="number">1</span>] + <span class="number">2</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> dp[i][j] = Math.max(dp[i + <span class="number">1</span>][j], dp[i][j - <span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[<span class="number">0</span>][s.length() - <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h6 id="2-LeetCode-1312-让字符串成为回文串的最少插入次数"><a href="#2-LeetCode-1312-让字符串成为回文串的最少插入次数" class="headerlink" title="2. LeetCode 1312 (让字符串成为回文串的最少插入次数)"></a>2. <a href="https://leetcode-cn.com/problems/minimum-insertion-steps-to-make-a-string-palindrome/" target="_blank" rel="noopener">LeetCode 1312</a> (让字符串成为回文串的最少插入次数)</h6><p>给你一个字符串s, 每一次操作你都可以在字符串的任意位置插入任意字符</p><p>请你返回让s成为回文串的<strong>最少操作次数</strong></p><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><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">minInsertions</span><span class="params">(String s)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (s == <span class="keyword">null</span> || s.length() == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[s.length()][s.length()];</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < s.length(); i++) {</span><br><span class="line"> dp[i][i] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = s.length() - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = i + <span class="number">1</span>; j < s.length(); j++) {</span><br><span class="line"> <span class="keyword">if</span> (s.charAt(i) == s.charAt(j)) {</span><br><span class="line"> dp[i][j] = dp[i + <span class="number">1</span>][j - <span class="number">1</span>] + <span class="number">2</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> dp[i][j] = Math.max(dp[i + <span class="number">1</span>][j], dp[i][j - <span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> s.length() - dp[<span class="number">0</span>][s.length() - <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 算法 </category>
<category> LeetCode </category>
<category> 动态规划 </category>
</categories>
<tags>
<tag> 动态规划 </tag>
</tags>
</entry>
<entry>
<title>二叉树结构判断问题</title>
<link href="/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%BB%93%E6%9E%84%E5%88%A4%E6%96%AD%E9%97%AE%E9%A2%98/"/>
<url>/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%BB%93%E6%9E%84%E5%88%A4%E6%96%AD%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<h1 id="1-判断二叉树是否相同或者对称"><a href="#1-判断二叉树是否相同或者对称" class="headerlink" title="1. 判断二叉树是否相同或者对称"></a>1. 判断二叉树是否相同或者对称</h1><h2 id="1-对称二叉树"><a href="#1-对称二叉树" class="headerlink" title="1. 对称二叉树"></a>1. 对称二叉树</h2><p><a href="https://leetcode-cn.com/problems/symmetric-tree/" target="_blank" rel="noopener">101. Symmetric Tree</a><br>给定一个二叉树,检查它是否是镜像对称的。</p><h3 id="题解一"><a href="#题解一" class="headerlink" title="题解一"></a>题解一</h3><ol><li>递归判断左子树是否等于右子树</li><li><code>check()</code>方法是<a href="https://leetcode-cn.com/problems/same-tree/" target="_blank" rel="noopener">100. Same Tree</a>代码</li></ol><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> <span class="keyword">return</span> check(root, root);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">boolean</span> <span class="title">check</span><span class="params">(TreeNode root1, TreeNode root2)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (root1 == <span class="keyword">null</span> && root2 == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//过滤了全null</span></span><br><span class="line"> <span class="keyword">if</span> (root1 == <span class="keyword">null</span> || root2 == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> root1.val == root2.val && check(root1.left, root2.right) && check(root1.right, root2.left);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>时间O(n), 空间O(n)</strong></p><h3 id="题解二"><a href="#题解二" class="headerlink" title="题解二"></a>题解二</h3><ol><li>用迭代的方法,新建一个队列</li><li>每次加入两个值,若发现不对称直接返回false, 否则按照左右,右左加入队列中。</li></ol><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> Queue<TreeNode> queue = <span class="keyword">new</span> LinkedList<>();</span><br><span class="line"> queue.add(root);</span><br><span class="line"> queue.add(root);</span><br><span class="line"> <span class="keyword">while</span> (!queue.isEmpty()){</span><br><span class="line"> TreeNode node1 = queue.poll();</span><br><span class="line"> TreeNode node2 = queue.poll();</span><br><span class="line"> <span class="comment">//判断</span></span><br><span class="line"> <span class="keyword">if</span>(node1 == <span class="keyword">null</span> && node2 == <span class="keyword">null</span>){</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(node1 == <span class="keyword">null</span> || node2 == <span class="keyword">null</span>){</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(node1.val != node2.val){</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//左右右左</span></span><br><span class="line"> queue.add(node1.left);</span><br><span class="line"> queue.add(node2.right);</span><br><span class="line"> queue.add(node1.right);</span><br><span class="line"> queue.add(node2.left);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>时间O(n), 空间O(n)</strong></p><h1 id="2-判断二叉树的子树以及子结构"><a href="#2-判断二叉树的子树以及子结构" class="headerlink" title="2. 判断二叉树的子树以及子结构"></a>2. 判断二叉树的子树以及子结构</h1><h2 id="1-另一个树的子树"><a href="#1-另一个树的子树" class="headerlink" title="1. 另一个树的子树"></a>1. 另一个树的子树</h2><p><a href="https://leetcode-cn.com/problems/subtree-of-another-tree/" target="_blank" rel="noopener">572. Subtree of Another Tree</a><br>给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。</p><h3 id="题解"><a href="#题解" class="headerlink" title="题解"></a>题解</h3><ol><li>本题是求子树,区别于子结构,子树需要一直追溯到叶子节点</li></ol><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="comment">//子树不同于子结构</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isSubtree</span><span class="params">(TreeNode s, TreeNode t)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (t == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//能走到这一步证明t != null而s == null则错误</span></span><br><span class="line"> <span class="keyword">if</span> (s == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> isSameTree(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t);</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">boolean</span> <span class="title">isSameTree</span><span class="params">(TreeNode s, TreeNode t)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (s == <span class="keyword">null</span> && t == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//过滤都为null情况</span></span><br><span class="line"> <span class="keyword">if</span> (s == <span class="keyword">null</span> || t == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (s.val != t.val) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//当前节点一致的情况</span></span><br><span class="line"> <span class="keyword">return</span> isSameTree(s.left, t.left) && isSameTree(s.right, t.right);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 算法 </category>
<category> LeetCode </category>
<category> 二叉树 </category>
</categories>
<tags>
<tag> 二叉树 </tag>
<tag> 递归 </tag>
</tags>
</entry>
<entry>
<title>单调栈问题</title>
<link href="/%E5%8D%95%E8%B0%83%E6%A0%88%E9%97%AE%E9%A2%98/"/>
<url>/%E5%8D%95%E8%B0%83%E6%A0%88%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<h1 id="1-最大矩形面积问题"><a href="#1-最大矩形面积问题" class="headerlink" title="1. 最大矩形面积问题"></a>1. 最大矩形面积问题</h1><h2 id="1-柱状图中最大的矩形"><a href="#1-柱状图中最大的矩形" class="headerlink" title="1. 柱状图中最大的矩形"></a>1. 柱状图中最大的矩形</h2><p><a href="https://leetcode-cn.com/problems/largest-rectangle-in-histogram/" target="_blank" rel="noopener">84. Largest Rectangle in Histogram</a><br>给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。<br>求在该柱状图中,能够勾勒出来的矩形的最大面积。</p><h3 id="题解"><a href="#题解" class="headerlink" title="题解"></a>题解</h3><ol><li>维护一个单调递增的栈,当遇到一个比自己矮的值就扩散底部的长度,底为<code>(i - pop后的peek值 - 1)</code>, 否则将其加入栈中;</li><li>遍历完整个数组的时候<code>i == 数组的最后一个索引 + 1</code>, 因此底为<code>(height.length - pop后的peek值 - 1)</code>.</li></ol><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>[] heights)</span> </span>{</span><br><span class="line"> Deque<Integer> stack = <span class="keyword">new</span> ArrayDeque<>();</span><br><span class="line"> <span class="comment">//设为哨兵</span></span><br><span class="line"> stack.add(-<span class="number">1</span>);</span><br><span class="line"> <span class="keyword">int</span> area = <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 < heights.length; i++) {</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">//底的宽度就是当前i - 前一个出栈后的栈顶索引 - 1</span></span><br><span class="line"> <span class="keyword">while</span> (stack.peekLast() != -<span class="number">1</span> && heights[stack.peekLast()] >= heights[i]) {</span><br><span class="line"> area = Math.max(area, heights[stack.pollLast()] * (i - stack.peekLast() - <span class="number">1</span>));</span><br><span class="line"> }</span><br><span class="line"> stack.add(i);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//底的宽度从当前i变成最末索引 - 前一个出栈后的栈顶索引 - 1</span></span><br><span class="line"> <span class="keyword">while</span> (stack.peekLast() != -<span class="number">1</span>) {</span><br><span class="line"> area = Math.max(area, heights[stack.pollLast()] * (heights.length - stack.peekLast() - <span class="number">1</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> area;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>时间O(n), 空间O(n)</strong></p><h1 id="2-数组后续更大元素问题"><a href="#2-数组后续更大元素问题" class="headerlink" title="2. 数组后续更大元素问题"></a>2. 数组后续更大元素问题</h1><h2 id="1-每日温度"><a href="#1-每日温度" class="headerlink" title="1. 每日温度"></a>1. 每日温度</h2><p><a href="https://leetcode-cn.com/problems/daily-temperatures/" target="_blank" rel="noopener">739. Daily Temperatures</a><br>根据每日气温列表,请重新生成一个列表,对应位置的输出是需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用0来代替。<br>例如,给定一个列表<code>temperatures = [73, 74, 75, 71, 69, 72, 76, 73]</code>,你的输出应该是<code>[1, 1, 4, 2, 1, 1, 0, 0]</code>。</p><blockquote><p>提示:气温列表长度的范围是<code>[1, 30000]</code>。每个气温的值的均为华氏度,都是在<code>[30, 100]</code>范围内的整数。</p></blockquote><h3 id="题解-1"><a href="#题解-1" class="headerlink" title="题解"></a>题解</h3><ol><li>维护一个单调递减的栈,当遇到比栈顶元素大的值,出栈并计算出栈索引对应的结果</li><li>结果为<code>当前索引i - 出栈索引</code></li></ol><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span>[] dailyTemperatures(<span class="keyword">int</span>[] T) {</span><br><span class="line"> Deque<Integer> stack = <span class="keyword">new</span> ArrayDeque<>();</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 < T.length; i++) {</span><br><span class="line"> <span class="comment">//单调递减栈</span></span><br><span class="line"> <span class="keyword">while</span> (!stack.isEmpty() && T[i] > T[stack.peek()]) {</span><br><span class="line"> <span class="keyword">int</span> temp = stack.pop();</span><br><span class="line"> res[temp] = i - temp;</span><br><span class="line"> }</span><br><span class="line"> stack.push(i);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 算法 </category>
<category> LeetCode </category>
<category> 单调栈 </category>
</categories>
<tags>
<tag> 单调栈 </tag>
</tags>
</entry>
<entry>
<title>路径系列问题</title>
<link href="/%E8%B7%AF%E5%BE%84%E7%B3%BB%E5%88%97%E9%97%AE%E9%A2%98/"/>
<url>/%E8%B7%AF%E5%BE%84%E7%B3%BB%E5%88%97%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<ol><li>这种类型的题首先是要初始化dp的初始值,即第一行第一列的值;</li><li>新开<code>dp[]</code>则代表有几种路径;</li><li>或者以原数组为<code>dp[]</code>代表当前为是否会对后续有影响,没有则赋值0;</li><li>前一种状态为左 + 上,即<code>dp[i - 1][j] + dp[i][j - 1]</code>。</li></ol><h1 id="1-左上到右下的路径问题"><a href="#1-左上到右下的路径问题" class="headerlink" title="1. 左上到右下的路径问题"></a>1. 左上到右下的路径问题</h1><h2 id="1-不同路径I"><a href="#1-不同路径I" class="headerlink" title="1. 不同路径I"></a>1. 不同路径I</h2><p><a href="https://leetcode-cn.com/problems/unique-paths/" target="_blank" rel="noopener">62. Unique Paths</a><br>一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。<br>机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。<br>问总共有多少条不同的路径?</p><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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">uniquePaths</span><span class="params">(<span class="keyword">int</span> m, <span class="keyword">int</span> n)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (m == <span class="number">0</span> || n == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</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="comment">//动态规划一定要考虑清楚初始条件</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < m; i++) {</span><br><span class="line"> dp[i][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < n; i++) {</span><br><span class="line"> dp[<span class="number">0</span>][i] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i < m; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j < n; j++) {</span><br><span class="line"> dp[i][j] = dp[i - <span class="number">1</span>][j] + dp[i][j - <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> }</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"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>时间O(m * n), 空间O(m * n)</strong></p><h2 id="2-不同路径II"><a href="#2-不同路径II" class="headerlink" title="2. 不同路径II"></a>2. 不同路径II</h2><p><a href="https://leetcode-cn.com/problems/unique-paths-ii/" target="_blank" rel="noopener">63. Unique Paths II</a><br>一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。<br>机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。<br>现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?</p><h3 id="题解-1"><a href="#题解-1" class="headerlink" title="题解"></a>题解</h3><ol><li>该题利用原数组作为动态规划数组;</li><li>初始化第一行第一列的时候,遇到障碍之前都为1,遇到了障碍将其设为0,以及后续都为0代表无路可走;</li><li>没有障碍物的时候,状态为<code>obstacleGrid[i - 1][j] + obstacleGrid[i][j - 1]</code>;</li><li>否则设为0,代表此路不通,即该点对后续路径无贡献。</li></ol><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">uniquePathsWithObstacles</span><span class="params">(<span class="keyword">int</span>[][] obstacleGrid)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> m = obstacleGrid.length;</span><br><span class="line"> <span class="keyword">int</span> n = obstacleGrid[<span class="number">0</span>].length;</span><br><span class="line"> <span class="keyword">if</span> (obstacleGrid[<span class="number">0</span>][<span class="number">0</span>] == <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> obstacleGrid[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">1</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">1</span>; i < m; i++) {</span><br><span class="line"> obstacleGrid[i][<span class="number">0</span>] = (obstacleGrid[i][<span class="number">0</span>] == <span class="number">0</span> && obstacleGrid[i - <span class="number">1</span>][<span class="number">0</span>] == <span class="number">1</span>) ? <span class="number">1</span> : <span class="number">0</span>; </span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i < n; i++) {</span><br><span class="line"> obstacleGrid[<span class="number">0</span>][i] = (obstacleGrid[<span class="number">0</span>][i] == <span class="number">0</span> && obstacleGrid[<span class="number">0</span>][i - <span class="number">1</span>] == <span class="number">1</span>) ? <span class="number">1</span> : <span class="number">0</span>; </span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i < m; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j < n; j++) {</span><br><span class="line"> <span class="keyword">if</span> (obstacleGrid[i][j] == <span class="number">0</span>) {</span><br><span class="line"> obstacleGrid[i][j] = obstacleGrid[i - <span class="number">1</span>][j] + obstacleGrid[i][j - <span class="number">1</span>];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> obstacleGrid[i][j] = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> obstacleGrid[m - <span class="number">1</span>][n - <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="3-最小路径和"><a href="#3-最小路径和" class="headerlink" title="3. 最小路径和"></a>3. 最小路径和</h2><p><a href="https://leetcode-cn.com/problems/minimum-path-sum/" target="_blank" rel="noopener">64. Minimum Path Sum</a><br>给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。<br>说明:每次只能向下或者向右移动一步。</p><h3 id="题解-2"><a href="#题解-2" class="headerlink" title="题解"></a>题解</h3><ol><li>该题也是利用原数组做dp数组;</li><li>初始化第一行第一列;</li><li>该点必定是从左或者上来所以娶妻最小值相加。</li></ol><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</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>{</span><br><span class="line"> <span class="keyword">if</span> (grid == <span class="keyword">null</span> || grid[<span class="number">0</span>].length == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">int</span> m = grid.length, n = grid[<span class="number">0</span>].length;</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">1</span>; i < m; i++) {</span><br><span class="line"> grid[i][<span class="number">0</span>] += grid[i - <span class="number">1</span>][<span class="number">0</span>];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i < n; i++) {</span><br><span class="line"> grid[<span class="number">0</span>][i] += grid[<span class="number">0</span>][i - <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i < m; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j < n; j++) {</span><br><span class="line"> grid[i][j] += Math.min(grid[i - <span class="number">1</span>][j], grid[i][j - <span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> grid[m - <span class="number">1</span>][n - <span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h1 id="2-三角形路径问题"><a href="#2-三角形路径问题" class="headerlink" title="2. 三角形路径问题"></a>2. 三角形路径问题</h1><h2 id="1-三角形最小路径和"><a href="#1-三角形最小路径和" class="headerlink" title="1. 三角形最小路径和"></a>1. 三角形最小路径和</h2><p><a href="https://leetcode-cn.com/problems/triangle/" target="_blank" rel="noopener">120. Triangle</a><br>给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。<br>相邻的结点在这里指的是下标与上一层结点下标相同或者等于上一层结点下标 + 1 的两个结点。<br><strong>空间为O(n)</strong></p><h3 id="题解-3"><a href="#题解-3" class="headerlink" title="题解"></a>题解</h3><ol><li>先初始化最后一层,然后由于当前的状态只和下面一层的<code>j, j + 1</code>相关,所以只需要一维数组;</li><li>利用<code>triangle.get(i).get(j)</code>获取当前行的<code>j</code>值与下一行的<code>j, j + 1</code>较小的相加。</li></ol><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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<List<Integer>> triangle)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> m = triangle.size();</span><br><span class="line"> List<Integer> list = triangle.get(m - <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">int</span>[] dp = <span class="keyword">new</span> <span class="keyword">int</span>[m];</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 < list.size(); i++) {</span><br><span class="line"> dp[i] = list.get(i);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = m - <span class="number">2</span>; i >= <span class="number">0</span>; i--) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j < triangle.get(i).size(); j++) {</span><br><span class="line"> dp[j] = Math.min(dp[j], dp[j + <span class="number">1</span>]) + triangle.get(i).get(j);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[<span class="number">0</span>];</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 算法 </category>
<category> LeetCode </category>
<category> 动态规划 </category>
</categories>
<tags>
<tag> 动态规划 </tag>
</tags>
</entry>
<entry>
<title>子数组和问题</title>
<link href="/%E5%AD%90%E6%95%B0%E7%BB%84%E5%92%8C%E9%97%AE%E9%A2%98/"/>
<url>/%E5%AD%90%E6%95%B0%E7%BB%84%E5%92%8C%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<h1 id="1-子数组和问题"><a href="#1-子数组和问题" class="headerlink" title="1. 子数组和问题"></a>1. 子数组和问题</h1><ol><li>子数组和问题一般考虑使用前缀和来解</li><li>[i,j]的子数组和问题和<code>pre[j] - pre[i - 1]</code>相关</li><li>用map统计频数,并且初始化map.put(0, 1);</li></ol><h2 id="1-和为K的子数组"><a href="#1-和为K的子数组" class="headerlink" title="1. 和为K的子数组"></a>1. 和为K的子数组</h2><p><a href="https://leetcode-cn.com/problems/subarray-sum-equals-k/" target="_blank" rel="noopener">560. Subarray Sum Equals K</a><br>给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。</p><h3 id="题解"><a href="#题解" class="headerlink" title="题解"></a>题解</h3><ol><li><code>pre[i] - pre[j - 1] == k</code> => <code>pre[j - 1] == pre[i] - k</code></li><li><code>pre[i]</code>代表当前前缀和, <code>pre[j - 1]</code>为之前的前缀和,相减就是<code>(j, i)</code>的子数组之和;</li><li>因此只需要累加以<code>i</code>为结尾的前缀和为<code>pre[i - 1] - k</code>值的频数即可;</li><li>而<code>pre[i] == pre[i - 1] + nums[i]</code>, 这一步可以当做状态转移方程,即当前的前缀和;</li></ol><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> <span class="keyword">int</span> count = <span class="number">0</span>, pre = <span class="number">0</span>;</span><br><span class="line"> Map<Integer, Integer> map = <span class="keyword">new</span> HashMap<>();</span><br><span class="line"> <span class="comment">//初始化前缀和为0的个数为1</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 < nums.length; i++) {</span><br><span class="line"> <span class="comment">//pre[i], 当前的前缀和</span></span><br><span class="line"> pre += nums[i];</span><br><span class="line"> <span class="comment">//pre[j - 1] == pre[i] - k, 之前的前缀和</span></span><br><span class="line"> <span class="keyword">if</span> (map.containsKey(pre - k)) {</span><br><span class="line"> count += map.get(pre - k);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//存放目前的前缀和,之后进入下一个循环就变成pre[i - 1]</span></span><br><span class="line"> map.put(pre, map.getOrDefault(pre, <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> count;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>时间O(n), 空间O(n)</strong></p><h2 id="2-和可被-K-整除的子数组"><a href="#2-和可被-K-整除的子数组" class="headerlink" title="2. 和可被 K 整除的子数组"></a>2. 和可被 K 整除的子数组</h2><p><a href="https://leetcode-cn.com/problems/subarray-sums-divisible-by-k/" target="_blank" rel="noopener">974. Subarray Sums Divisible by K</a><br>给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目。</p><h3 id="题解-1"><a href="#题解-1" class="headerlink" title="题解"></a>题解</h3><ol><li><code>(pre[i] - pre[j - 1]) mod k == 0</code> => <code>pre[j - 1] mod k == pre[i] mod k</code></li><li>即找到前缀和取余相等的值即可</li></ol><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">subarraysDivByK</span><span class="params">(<span class="keyword">int</span>[] A, <span class="keyword">int</span> K)</span> </span>{</span><br><span class="line"> Map<Integer, Integer> map = <span class="keyword">new</span> HashMap<>();</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">int</span> ans = <span class="number">0</span>, sum = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i : A) {</span><br><span class="line"> <span class="comment">//前缀和</span></span><br><span class="line"> sum += i;</span><br><span class="line"> <span class="comment">//Java负数取余为负数,所以这里将其变为正数</span></span><br><span class="line"> <span class="keyword">int</span> modulus = (sum % K + K) % K;</span><br><span class="line"> <span class="comment">//pre[j] mod k == pre[i - 1] mod k即前缀和取余相等</span></span><br><span class="line"> <span class="comment">//代表i,j的子数组取余为0</span></span><br><span class="line"> <span class="comment">//map中缓存的是取余相等的子数组数量</span></span><br><span class="line"> <span class="keyword">int</span> same = map.getOrDefault(modulus, <span class="number">0</span>);</span><br><span class="line"> <span class="comment">//计数</span></span><br><span class="line"> ans += same;</span><br><span class="line"> map.put(modulus, same + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ans;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>时间O(n), 空间O(min(n, k))</strong></p>]]></content>
<categories>
<category> 算法 </category>
<category> LeetCode </category>
<category> 动态规划 </category>
</categories>
<tags>
<tag> 前缀和 </tag>
</tags>
</entry>
<entry>
<title>判圈问题</title>
<link href="/%E5%88%A4%E5%9C%88%E9%97%AE%E9%A2%98/"/>
<url>/%E5%88%A4%E5%9C%88%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<h1 id="1-寻找数组中仅有的重复数"><a href="#1-寻找数组中仅有的重复数" class="headerlink" title="1. 寻找数组中仅有的重复数"></a>1. 寻找数组中仅有的重复数</h1><h2 id="1-寻找重复数"><a href="#1-寻找重复数" class="headerlink" title="1. 寻找重复数"></a>1. 寻找重复数</h2><p><a href="https://leetcode-cn.com/problems/find-the-duplicate-number/" target="_blank" rel="noopener">287. Find the Duplicate Number</a><br>给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知<strong>至少存在一个重复</strong>的整数。假设只有一个重复的整数,找出这个重复的数。</p><p>说明:</p><blockquote><p><strong>不能更改原数组</strong>(假设数组是只读的)。<br> 只能使用额外的 O(1) 的空间。<br> 时间复杂度小于 O(n2) 。<br> 数组中只有一个重复的数字,但它可能不止重复出现一次。</p></blockquote><h3 id="题解一"><a href="#题解一" class="headerlink" title="题解一"></a>题解一</h3><ol><li>题目要求数组不可变,所以区别于剑指offer那题的原地swap题解</li><li>采用Floyd判圈法,简单证明如下:</li></ol><ul><li>假设环长为L,从起点到环的入口的步数是a,从环的入口继续走b步到达相遇位置,从相遇位置继续走c步回到环的入口,则有<code>b+c=L</code>,其中L、a、b、c都是正整数;</li><li>根据上述定义,慢指针走了<code>a+b</code>步,快指针走了<code>2(a+b)</code>步。从另一个角度考虑,在相遇位置,快指针比慢指针多走了若干圈,因此快指针走的步数还可以表示成<code>a+b+kL</code>,其中k表示快指针在环上走的圈数。联立等式,可以得到<code>2(a+b)=a+b+kL</code>;</li><li>解得 a=kL-ba=kL−b,整理可得<code>a=(k−1)L+(L−b)=(k−1)L+c</code></li><li>从上述等式可知,如果慢指针从起点出发,快指针从相遇位置出发,每次两个指针都移动一步,则慢指针走了a步之后到达环的入口,快指针在环里走了k-1圈之后又走了c步,由于从相遇位置继续走c步即可回到环的入口,因此快指针也到达环的入口。两个指针在环的入口相遇,相遇点就是答案。</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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">findDuplicate</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> slow = <span class="number">0</span>, fast = <span class="number">0</span>;</span><br><span class="line"> <span class="comment">//区别于环形链表,没有尾部的概念</span></span><br><span class="line"> <span class="keyword">do</span> {</span><br><span class="line"> slow = nums[slow];</span><br><span class="line"> fast = nums[nums[fast]];</span><br><span class="line"> } <span class="keyword">while</span> (slow != fast);</span><br><span class="line"> <span class="comment">//第二阶段</span></span><br><span class="line"> slow = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (slow != fast) {</span><br><span class="line"> slow = nums[slow];</span><br><span class="line"> fast = nums[fast];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> slow;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>时间O(n), 空间O(1)</strong></p><h3 id="题解二"><a href="#题解二" class="headerlink" title="题解二"></a>题解二</h3><a name="link" />二分法+鸽巢原理<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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">findDuplicate</span><span class="params">(<span class="keyword">int</span>[] nums)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">1</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (left < right) {</span><br><span class="line"> <span class="keyword">int</span> mid = (left + right) >>> <span class="number">1</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">//统计小于等于n / 2的数量</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> num : nums) {</span><br><span class="line"> <span class="keyword">if</span> (num <= mid) {</span><br><span class="line"> count++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//数量比n / 2的值多,则重复数一定在左边</span></span><br><span class="line"> <span class="comment">//抽屉原理</span></span><br><span class="line"> <span class="keyword">if</span> (count > mid) {</span><br><span class="line"> right = mid;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> left = mid + <span class="number">1</span>;</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="keyword">return</span> left;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>时间O(nlogn), 空间O(1)</strong></p><h1 id="2-环形链表"><a href="#2-环形链表" class="headerlink" title="2. 环形链表"></a>2. 环形链表</h1><h2 id="1-环形链表II"><a href="#1-环形链表II" class="headerlink" title="1. 环形链表II"></a>1. 环形链表II</h2><p><a href="https://leetcode-cn.com/problems/linked-list-cycle-ii/" target="_blank" rel="noopener">环形链表 II</a><br>给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。<br>为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。</p><p>说明:不允许修改给定的链表。</p><h3 id="题解"><a href="#题解" class="headerlink" title="题解"></a>题解</h3><p>Floyd判环</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> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> <span class="keyword">if</span> (head == <span class="keyword">null</span> || head.next == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line"> }</span><br><span class="line"> ListNode slow = head;</span><br><span class="line"> ListNode fast = head;</span><br><span class="line"> <span class="comment">//无环则到尾端退出</span></span><br><span class="line"> <span class="keyword">while</span> (fast != <span class="keyword">null</span> && fast.next != <span class="keyword">null</span>) {</span><br><span class="line"> slow = slow.next;</span><br><span class="line"> fast = fast.next.next;</span><br><span class="line"> <span class="comment">//第二阶段</span></span><br><span class="line"> <span class="keyword">if</span> (slow == fast) {</span><br><span class="line"> ListNode slow1 = head;</span><br><span class="line"> <span class="keyword">while</span> (slow != slow1) {</span><br><span class="line"> slow = slow.next;</span><br><span class="line"> slow1 = slow1.next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> slow;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 算法 </category>
<category> LeetCode </category>
<category> 双指针 </category>
</categories>
<tags>
<tag> 二分法 </tag>
<tag> 快慢指针 </tag>
<tag> Floyd判圈法 </tag>
</tags>
</entry>
<entry>
<title>LRU设计题</title>
<link href="/LRU%E8%AE%BE%E8%AE%A1%E9%A2%98/"/>
<url>/LRU%E8%AE%BE%E8%AE%A1%E9%A2%98/</url>
<content type="html"><![CDATA[<h1 id="1-LRU设计题"><a href="#1-LRU设计题" class="headerlink" title="1. LRU设计题"></a>1. LRU设计题</h1><h2 id="1-146-LRU-Cache"><a href="#1-146-LRU-Cache" class="headerlink" title="1. 146. LRU Cache"></a>1. <a href="https://leetcode-cn.com/problems/lru-cache/" target="_blank" rel="noopener">146. LRU Cache</a></h2><p>运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。</p><p>获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。<br>写入数据 put(key, value) - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。</p><h3 id="题解"><a href="#题解" class="headerlink" title="题解"></a>题解</h3><p>利用LinkedList和HashMap, <strong>注意remove需要Integer</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><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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LRUCache</span> </span>{</span><br><span class="line"> LinkedList<Integer> list;</span><br><span class="line"> Map<Integer, Integer> map;</span><br><span class="line"> <span class="keyword">int</span> capacity;</span><br><span class="line"></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>{</span><br><span class="line"> list = <span class="keyword">new</span> LinkedList<>();</span><br><span class="line"> map = <span class="keyword">new</span> HashMap<>();</span><br><span class="line"> <span class="keyword">this</span>.capacity = capacity;</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">get</span><span class="params">(<span class="keyword">int</span> key)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (map.containsKey(key)) {</span><br><span class="line"> <span class="comment">//如果是remove(int)移除的则是索引</span></span><br><span class="line"> list.remove((Integer)key);</span><br><span class="line"> list.addFirst(key);</span><br><span class="line"> <span class="keyword">return</span> map.get(key);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> -<span class="number">1</span>;</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">void</span> <span class="title">put</span><span class="params">(<span class="keyword">int</span> key, <span class="keyword">int</span> value)</span> </span>{</span><br><span class="line"> <span class="comment">//先判断是否存在</span></span><br><span class="line"> <span class="keyword">if</span> (map.containsKey(key)) {</span><br><span class="line"> list.remove((Integer)key);</span><br><span class="line"> list.addFirst(key);</span><br><span class="line"> map.put(key, value);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//不存在若到达上限,则移除map里面list末尾的元素</span></span><br><span class="line"> <span class="keyword">if</span> (list.size() == capacity) {</span><br><span class="line"> map.remove(list.removeLast());</span><br><span class="line"> map.put(key, value);</span><br><span class="line"> list.addFirst(key);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> map.put(key, value);</span><br><span class="line"> list.addFirst(key);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 算法 </category>
<category> LeetCode </category>
<category> 设计题 </category>
</categories>
<tags>
<tag> 设计题 </tag>
</tags>
</entry>
<entry>
<title>L.A. Confidential (1997)</title>
<link href="/L.A.%20Confidential%20(1997)/"/>
<url>/L.A.%20Confidential%20(1997)/</url>
<content type="html"><![CDATA[<p><a href="https://www.blu-ray.com/movies/LA-Confidential-Blu-ray/185095/" target="_blank" rel="noopener">20th Century Fox | Germany | 20th Anniversary Edition</a></p><details><summary>BDInfo:</summary>DISC INFO:<p>Disc Title: L.A.Confidential.1997.1080p.EUR.Blu-ray.AVC.DTS-HD.MA.5.1-TAiCHi<br>Disc Size: 49,071,773,904 bytes<br>Protection: AACS<br>BD-Java: Yes<br>BDInfo: 0.5.8</p><p>PLAYLIST REPORT:</p><p>Name: 00800.MPLS<br>Length: 2:17:41.336 (h:m:s.ms)<br>Size: 36,452,302,848 bytes<br>Total Bitrate: 35.30 Mbps</p><p>(*) Indicates included stream hidden by this playlist.</p><p>VIDEO:</p><p>Codec Bitrate Description<br>MPEG-4 AVC Video 24551 kbps 1080p / 23.976 fps / 16:9 / High Profile 4.1</p><p>AUDIO:</p><p>Codec Language Bitrate Description<br>DTS-HD Master Audio English 4041 kbps 5.1 / 48 kHz / 4041 kbps / 24-bit (DTS Core: 5.1 / 48 kHz / 1509 kbps / 24-bit)<br>DTS Audio French 768 kbps 5.1 / 48 kHz / 768 kbps / 24-bit<br>DTS Audio German 768 kbps 5.1 / 48 kHz / 768 kbps / 24-bit<br>DTS Audio Italian 768 kbps 5.1 / 48 kHz / 768 kbps / 24-bit<br>Dolby Digital Audio Japanese 224 kbps 2.0 / 48 kHz / 224 kbps / Dolby Surround<br>Dolby Digital Audio Japanese 192 kbps 1.0 / 48 kHz / 192 kbps<br>Dolby Digital Audio Chinese 448 kbps 5.1 / 48 kHz / 448 kbps<br>Dolby Digital Audio English 224 kbps 2.0 / 48 kHz / 224 kbps<br>Dolby Digital Audio English 448 kbps 5.1 / 48 kHz / 448 kbps</p><p>SUBTITLES:</p><p>Codec Language Bitrate Description<br>Presentation Graphics Japanese 22.393 kbps<br>Presentation Graphics English 34.575 kbps<br>Presentation Graphics French 26.176 kbps<br>Presentation Graphics Dutch 25.658 kbps<br>Presentation Graphics German 35.748 kbps<br>Presentation Graphics Italian 31.252 kbps<br>Presentation Graphics Japanese 0.512 kbps<br>Presentation Graphics Japanese 2.652 kbps<br>Presentation Graphics Korean 24.813 kbps<br>Presentation Graphics Arabic 15.218 kbps<br>Presentation Graphics Bulgarian 29.199 kbps<br>Presentation Graphics Croatian 29.556 kbps<br>Presentation Graphics Czech 28.617 kbps<br>Presentation Graphics Greek 30.739 kbps<br>Presentation Graphics Hebrew 23.059 kbps<br>Presentation Graphics Icelandic 32.181 kbps<br>Presentation Graphics Chinese 31.438 kbps<br>Presentation Graphics Polish 28.552 kbps<br>Presentation Graphics Portuguese 30.814 kbps<br>Presentation Graphics Romanian 31.698 kbps<br>Presentation Graphics Serbian 31.284 kbps<br>Presentation Graphics Slovenian 30.088 kbps<br>Presentation Graphics Turkish 28.571 kbps<br>Presentation Graphics French 44.369 kbps<br>Presentation Graphics German 57.742 kbps<br>Presentation Graphics Japanese 33.099 kbps</p></details></br><p><a href="https://www.blu-ray.com/movies/LA-Confidential-Blu-ray/3085/" target="_blank" rel="noopener">TFC | Japan</a></p><details><summary>Mediainfo:</summary>GeneralUnique ID : 251988301504169898649172629068296874931 (0xBD932E7A133048238965D740A881EBB3)Complete Name : L.A.Confidential.1997.JPN.1080p.BluRay.DTSHD-MA.h264.Remux-decibeL.mkvFormat : MatroskaFormat version : Version 2File Size : 33.0 GiBDuration : 2h 17mnOverall bit rate mode : VariableOverall Bit rate : 34.2 MbpsMovie name : L.A.Confidential.1997.JPN.1080p.BluRay.DTSHD-MA.h264.Remux-decibeLEncoded date : UTC 2012-02-04 19:12:29Writing application : mkvmerge v5.0.1 ('Es ist Sommer') built on Oct 13 2011 11:02:45Writing library : libebml v1.2.2 + libmatroska v1.3.0<p>Video<br>ID : 1<br>Format : AVC<br>Format/Info : Advanced Video Codec<br>Format profile : <a href="mailto:High@L4.1">High@L4.1</a><br>Format settings, CABAC : Yes<br>Format settings, ReFrames : 4 frames<br>Codec ID : V_MPEG4/ISO/AVC<br>Duration : 2h 17mn<br>Bit rate mode : Variable<br>Bit rate : 29.9 Mbps<br>Maximum Bit rate : 37.0 Mbps<br>Width: 1 920 pixels<br>Height: 1 080 pixels<br>Display aspect ratio : 16:9<br>Frame Rate: 23.976 fps<br>Standard : NTSC<br>Color space : YUV<br>Chroma subsampling : 4:2:0<br>Bit depth : 8 bits<br>Scan Type : Progressive<br>Bits/(Pixel*Frame) : 0.601<br>Stream size : 28.8 GiB (87%)<br>Title : MPEG-4 AVC Video 29872 kbps 1080p / 23.976 fps / 16:9 / High Profile 4.1<br>Color primaries : BT.709-5, BT.1361, IEC 61966-2-4, SMPTE RP177<br>Transfer characteristics : BT.709-5, BT.1361<br>Matrix coefficients : BT.709-5, BT.1361, IEC 61966-2-4 709, SMPTE RP177</p><p>Audio #1<br>ID : 2<br>Format : DTS<br>Format/Info : Digital Theater Systems<br>Format profile : MA / Core<br>Codec ID : A_DTS<br>Duration : 2h 17mn<br>Bit rate mode : Variable<br>Bit rate : 1 576 Kbps / 1 510 Kbps<br>Channel(s): 6 channels<br>Channel positions : Front: L C R, Side: L R, LFE<br>Sampling rate : 48.0 KHz<br>Bit depth : 16 bits<br>Compression mode : Lossless / Lossy<br>Title : DTS-HD Master Audio English 2028 kbps 5.1 / 48 kHz / 2028 kbps / 16-bit (DTS Core: 5.1 / 48 kHz / 1509 kbps / 16-bit)<br>Language : English</p><p>Audio #2<br>ID : 3<br>Format : DTS<br>Format/Info : Digital Theater Systems<br>Format profile : MA / Core<br>Codec ID : A_DTS<br>Duration : 2h 17mn<br>Bit rate mode : Variable<br>Bit rate : 1 639 Kbps / 1 510 Kbps<br>Channel(s) : 6 channels<br>Channel positions : Front: L C R, Side: L R, LFE<br>Sampling rate : 48.0 KHz<br>Bit depth : 16 bits<br>Compression mode : Lossless / Lossy<br>Title : Isolated Musical Score<br>Language : English</p><p>Audio #3<br>ID : 4<br>Format : AC-3<br>Format/Info : Audio Coding 3<br>Mode extension : CM (complete main)<br>Codec ID : A_AC3<br>Duration : 2h 17mn<br>Bit rate mode : Constant<br>Bit Rate : 448 Kbps<br>Channel(s) : 2 channels<br>Channel positions : Front: L R<br>Sampling rate : 48.0 KHz<br>Bit depth : 16 bits<br>Compression mode : Lossy<br>Stream size : 442 MiB (1%)<br>Title : Commentary Track<br>Language : English</p><p>Text<br>ID : 5<br>Format : PGS<br>Codec ID : S_HDMV/PGS<br>Codec ID/Info : The same subtitle format used on BDs/HD-DVDs<br>Language : English</p><p>Menu<br>00:00:00.000 : en:Come to La<br>00:16:20.938 : en:Meet Bud White<br>00:24:27.549 : en:Meet the Big V<br>00:30:01.966 : en:Meet Ed Exley<br>00:36:45.995 : en:Mystery Woman<br>00:45:59.631 : en:Premiere Pot Bust!<br>00:56:08.031 : en:Bloody Christmas<br>01:02:27.618 : en:Will You Testify?<br>01:07:45.644 : en:A Muscle Job<br>01:14:33.010 : en:Dreamland<br>01:24:27.145 : en:Sten’s Last Day<br>01:36:37.291 : en:Nite Owl Massacre<br>01:40:50.127 : en:Whatever You Desire<br>01:51:31.309 : en:Lake Look-Alike<br>01:58:18.800 : en:Maroon Merc<br>02:07:05.951 : en:Interrogation<br>02:13:01.640 : en:Justice for Inez</p></details></br><p><a href="https://www.blu-ray.com/movies/LA-Confidential-Blu-ray/2403/" target="_blank" rel="noopener">Warner Bros | United Kingdom</a></p><details><summary>BDInfo:</summary>VIDEO:<p>Codec Bitrate Description<br>VC-1 Video 23591 kbps 1080p / 23.976 fps / 16:9 / Advanced Profile 3</p><p>AUDIO:</p><p>Codec Language Bitrate Description<br>Dolby Digital Audio English 640 kbps 5.1 / 48 kHz / 640 kbps<br>Dolby TrueHD Audio English 1411 kbps 5.1 / 48 kHz / 1411 kbps / 16-bit (AC3 Core: 5.1 / 48 kHz / 640 kbps)<br>Dolby Digital Audio French 640 kbps 5.1 / 48 kHz / 640 kbps<br>Dolby Digital Audio French 640 kbps 5.1 / 48 kHz / 640 kbps<br>Dolby Digital Audio German 640 kbps 5.1 / 48 kHz / 640 kbps<br>Dolby Digital Audio Italian 640 kbps 5.1 / 48 kHz / 640 kbps<br>Dolby Digital Audio Spanish 640 kbps 5.1 / 48 kHz / 640 kbps<br>Dolby Digital Audio Spanish 192 kbps 2.0 / 48 kHz / 192 kbps / Dolby Surround<br>Dolby Digital Audio English 192 kbps 2.0 / 48 kHz / 192 kbps / Dolby Surround<br>Dolby Digital Audio English 640 kbps 5.1 / 48 kHz / 640 kbps</p><p>SUBTITLES:</p><p>Codec Language Bitrate Description<br>Presentation Graphics English 44.870 kbps<br>Presentation Graphics French 37.617 kbps<br>Presentation Graphics German 50.276 kbps<br>Presentation Graphics Italian 45.332 kbps<br>Presentation Graphics Italian 47.325 kbps<br>Presentation Graphics Spanish 45.875 kbps<br>Presentation Graphics Dutch 33.772 kbps<br>Presentation Graphics Chinese 50.607 kbps<br>Presentation Graphics Spanish 48.485 kbps<br>Presentation Graphics Danish 37.135 kbps<br>Presentation Graphics Finnish 39.073 kbps<br>Presentation Graphics Norwegian 35.004 kbps<br>Presentation Graphics Portuguese 44.944 kbps<br>Presentation Graphics Swedish 41.239 kbps<br>Presentation Graphics Chinese 47.691 kbps<br>Presentation Graphics English 1.822 kbps</p></details></br><ul><li>I think GER(20th Anniversary Edition) has better PQ, and I like Kim Basinger’s lipstick’s color in GER edition.</li></ul><p> GER vs JPN vs GBR<br><a href="https://z4a.net/image/eMAMpL" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/27.png" alt="27.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAISN" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/26.png" alt="26.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAttw" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/25.png" alt="25.png" align="left" width="33%" height="33%"></a><br><a href="https://z4a.net/image/eMAnTC" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/24d182a98790eaa504.png" alt="24d182a98790eaa504.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAEa6" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/23.png" alt="23.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAxsn" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/22.png" alt="22.png" align="left" width="33%" height="33%"></a><br><a href="https://z4a.net/image/eMAwHv" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/21.png" alt="21.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAAbT" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/20.png" alt="20.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAu1P" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/19.png" alt="19.png" align="left" width="33%" height="33%"></a><br><a href="https://z4a.net/image/eMAkAa" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/18.png" alt="18.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAOpj" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/17.png" alt="17.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAWS0" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/16.png" alt="16.png" align="left" width="33%" height="33%"></a><br><a href="https://z4a.net/image/eMAHnK" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/15.png" alt="15.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAyTO" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/14.png" alt="14.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAVZJ" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/13.png" alt="13.png" align="left" width="33%" height="33%"></a><br><a href="https://z4a.net/image/eMA2hr" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/12-3.png" alt="12-3.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAgHA" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/12-2.png" alt="12-2.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAeRi" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/12-1.png" alt="12-1.png" align="left" width="33%" height="33%"></a><br><a href="https://z4a.net/image/eMuqYf" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/12.png" alt="12.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMA7AE" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/11.png" alt="11.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMupSU" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/10.png" alt="10.png" align="left" width="33%" height="33%"></a><br><a href="https://z4a.net/image/eMuYnI" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/09.png" alt="09.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMuNeG" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/08.png" alt="08.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMAUJp" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/07.png" alt="07.png" align="left" width="33%" height="33%"></a><br><a href="https://z4a.net/image/eMurZ2" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/06.png" alt="06.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMulhh" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/05.png" alt="05.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMuKRH" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/04.png" alt="04.png" align="left" width="33%" height="33%"></a><br><a href="https://z4a.net/image/eMu5ub" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/03.png" alt="03.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMuFJ9" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/02466b0e7bef02c720.png" alt="02466b0e7bef02c720.png" align="left" width="33%" height="33%"></a><a href="https://z4a.net/image/eMuby5" target="_blank" rel="noopener"><img src="https://z4a.net/images/2020/01/25/016d304d15cb8e8e9c.png" alt="016d304d15cb8e8e9c.png" align="left" width="33%" height="33%"></a></p>]]></content>
<categories>
<category> Movie </category>
<category> Blu-ray </category>
</categories>
<tags>
<tag> Blu-ray Comparsion </tag>
</tags>
</entry>
<entry>
<title>中位数问题</title>
<link href="/%E4%B8%AD%E4%BD%8D%E6%95%B0%E9%97%AE%E9%A2%98/"/>
<url>/%E4%B8%AD%E4%BD%8D%E6%95%B0%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<h1 id="1-寻找有序数组中位数"><a href="#1-寻找有序数组中位数" class="headerlink" title="1. 寻找有序数组中位数"></a>1. 寻找有序数组中位数</h1><h2 id="1-寻找两个正序数组的中位数"><a href="#1-寻找两个正序数组的中位数" class="headerlink" title="1. 寻找两个正序数组的中位数"></a>1. 寻找两个正序数组的中位数</h2><p><a href="https://leetcode-cn.com/problems/median-of-two-sorted-arrays/" target="_blank" rel="noopener">4. Median of Two Sorted Arrays</a><br>给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2;<br>请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n));<br>你可以假设 nums1 和 nums2 不会同时为空。</p><h3 id="题解"><a href="#题解" class="headerlink" title="题解"></a>题解</h3><ol><li>定义<code>halfLen = (m + n + 1) / 2</code>则<ol><li>偶数个元素中位数为<code>(nums[halfLen] + nums[halfLen - 1]) / 2</code>;</li><li>奇数个元素中位数为<code>nums[halfLen]</code>;</li></ol></li><li>本题使用二分法寻找这样的中位线使得中位线左右个数相等或者左边比右边多1;<br><img src="https://z4a.net/images/2020/05/24/82f47d2c1f0106c7590c51d85fc4973b.png" alt="82f47d2c1f0106c7590c51d85fc4973b.png"></li><li>图中第一行为<code>nums1</code>, 第二行为<code>nums2</code>, 改中位线要满足<code>nums1[i - 1] < nums2[j]</code>, <code>nums1[i] > nums2[j - 1]</code>,即线左边要比线右边小;</li><li><code>nums1[i - 1] > nums2[j]</code>则证明中位线的左边画多了,<code>right = i - 1</code>;</li><li><code>nums1[i] < nums2[j - 1]</code>则证明中位线的右边画少了,<code>left = i + 1</code>;</li><li>否则中位线划分的正好,这时候就计算线左边的最大值和右边的最小值,根据数据个数的奇偶性计算相应的中位数。</li></ol><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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">double</span> <span class="title">findMedianSortedArrays</span><span class="params">(<span class="keyword">int</span>[] nums1, <span class="keyword">int</span>[] nums2)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> m = nums1.length, n = nums2.length;</span><br><span class="line"> <span class="keyword">if</span> (m > n) {</span><br><span class="line"> <span class="keyword">return</span> findMedianSortedArrays(nums2, nums1);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">0</span>, right = m;</span><br><span class="line"> <span class="comment">//中位值的左边的数量</span></span><br><span class="line"> <span class="keyword">int</span> totalHalf = (m + n + <span class="number">1</span>) / <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">while</span> (left <= right) {</span><br><span class="line"> <span class="keyword">int</span> i = (left + right) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">int</span> j = totalHalf - i;</span><br><span class="line"> <span class="comment">//寻找分线</span></span><br><span class="line"> <span class="keyword">if</span> (i > <span class="number">0</span> && nums1[i - <span class="number">1</span>] > nums2[j]) {</span><br><span class="line"> right = i - <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (i < m && nums1[i] < nums2[j - <span class="number">1</span>]) {</span><br><span class="line"> left = i + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">//找到分线左边和右边各自最大最小值</span></span><br><span class="line"> <span class="keyword">int</span> maxLeft = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> (i == <span class="number">0</span>) {</span><br><span class="line"> maxLeft = nums2[j - <span class="number">1</span>];</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (j == <span class="number">0</span>) {</span><br><span class="line"> maxLeft = nums1[i - <span class="number">1</span>];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> maxLeft = Math.max(nums1[i - <span class="number">1</span>], nums2[j - <span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (((m + n) & <span class="number">1</span>) == <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">return</span> (<span class="keyword">double</span>)maxLeft;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">int</span> maxRight = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> (i == m) {</span><br><span class="line"> maxRight = nums2[j];</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (j == n) {</span><br><span class="line"> maxRight = nums1[i];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> maxRight = Math.min(nums1[i], nums2[j]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> (<span class="keyword">double</span>)(maxLeft + maxRight) / <span class="number">2.0</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0.0</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 算法 </category>
<category> LeetCode </category>
<category> 二分法 </category>
</categories>
<tags>
<tag> 二分法 </tag>
<tag> 中位数 </tag>
</tags>
</entry>
<entry>
<title>二分系列经典问题</title>
<link href="/%E4%BA%8C%E5%88%86%E7%B3%BB%E5%88%97%E7%BB%8F%E5%85%B8%E9%97%AE%E9%A2%98/"/>
<url>/%E4%BA%8C%E5%88%86%E7%B3%BB%E5%88%97%E7%BB%8F%E5%85%B8%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<h1 id="1-旋转数组问题"><a href="#1-旋转数组问题" class="headerlink" title="1. 旋转数组问题"></a>1. 旋转数组问题</h1><h2 id="1-旋转数组最小值"><a href="#1-旋转数组最小值" class="headerlink" title="1. 旋转数组最小值"></a>1. 旋转数组最小值</h2><ol><li><code>nums[mid]</code>和<code>nums[right]</code>比较</li><li><code><</code>证明后半部分有序,则最小值在前半部分,<code>right = mid</code>;</li><li><code>></code>证明前半部分有序,则最小值在后半部分,<code>left = mid + 1</code>;</li><li>若数组可重复,即<code>==</code>,则<code>right--</code>;</li></ol><h3 id="LeetCode-153"><a href="#LeetCode-153" class="headerlink" title="LeetCode 153"></a><a href="https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/solution/find-minimum-in-rotated-sorted-array-er-fen-fa-by-/" target="_blank" rel="noopener">LeetCode 153</a></h3><p>假设按照升序排序的数组在预先未知的某个点上进行了旋转。 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] 。<br>请找出其中最小的元素。你可以假设数组中<strong>不存在重复</strong>元素。</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><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (left < right) {</span><br><span class="line"> <span class="keyword">int</span> mid = (left + right) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (nums[mid] > nums[right]) {</span><br><span class="line"> left = mid + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] < nums[right]) {</span><br><span class="line"> right = mid;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> nums[left];</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="LeetCode-154"><a href="#LeetCode-154" class="headerlink" title="LeetCode 154"></a><a href="https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/solution/154-find-minimum-in-rotated-sorted-array-ii-by-jyd/" target="_blank" rel="noopener">LeetCode 154</a></h3><p>假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] 。<br>请找出其中最小的元素。注意数组中<strong>可能存在重复</strong>的元素。</p><h4 id="题解-1"><a href="#题解-1" 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><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line"> <span class="comment">//跳出循环条件为left == right</span></span><br><span class="line"> <span class="keyword">while</span> (left < right) {</span><br><span class="line"> <span class="keyword">int</span> mid = (left + right) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (nums[mid] > nums[right]) {</span><br><span class="line"> left = mid + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] < nums[right]) {</span><br><span class="line"> right = mid;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> right--; <span class="comment">//对比153题多了这一步判断</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> nums[left];</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="2-旋转数组target"><a href="#2-旋转数组target" class="headerlink" title="2. 旋转数组target"></a>2. 旋转数组target</h2><ol><li><code>nums[left] <= nums[mid]</code>,则前半部分有序,<code>nums[left] <= target < nums[mid]</code>时<code>right = mid - 1</code>,否则<code>left = mid + 1</code>;</li><li>否则,后半部有序,<code>nums[mid] < target <= nums[right]</code>时<code>left = mid + 1</code>,否则<code>right = mid - 1</code>;</li><li>若数组可重复,判断<code>nums[left] == nums[mid]</code>时<code>left++</code>;</li></ol><h3 id="LeetCode-33"><a href="#LeetCode-33" class="headerlink" title="LeetCode 33"></a><a href="https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/ji-bai-liao-9983de-javayong-hu-by-reedfan/" target="_blank" rel="noopener">LeetCode 33</a></h3><p>假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2]。<br>搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。你可以假设数组中<strong>不存在重复的元素。</strong></p><h4 id="题解-2"><a href="#题解-2" 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><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">search</span><span class="params">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (left <= right) {</span><br><span class="line"> <span class="keyword">int</span> mid = (left + right) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (nums[mid] == target) {</span><br><span class="line"> <span class="keyword">return</span> mid;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//前半部分有序,注意此处用小于等于,为了匹配最后只剩两个数;</span></span><br><span class="line"> <span class="keyword">if</span> (nums[left] <= nums[mid]) {</span><br><span class="line"> <span class="comment">//target可能比num[left]还小,跑右边去了所以要加限定,限定在左边</span></span><br><span class="line"> <span class="keyword">if</span> (nums[left] <= target && target < nums[mid]) {</span><br><span class="line"> right = mid - <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> left = mid + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] < nums[right]) {</span><br><span class="line"> <span class="comment">//同理将其限定在右边</span></span><br><span class="line"> <span class="keyword">if</span> (nums[mid] < target && target <= nums[right]) {</span><br><span class="line"> left = mid + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> right = mid - <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="LeetCode-81"><a href="#LeetCode-81" class="headerlink" title="LeetCode 81"></a><a href="https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/solution/zai-javazhong-ji-bai-liao-100de-yong-hu-by-reedfan/" target="_blank" rel="noopener">LeetCode 81</a></h3><p>假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2]。<br>编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。</p><h4 id="题解-3"><a href="#题解-3" 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><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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">(<span class="keyword">int</span>[] nums, <span class="keyword">int</span> target)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (left <= right) {</span><br><span class="line"> <span class="keyword">int</span> mid = (left + right) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (target == nums[mid]) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//主要是判断左边有序还是右边有序,所以直接++排除干扰项</span></span><br><span class="line"> <span class="keyword">if</span> (nums[left] == nums[mid]) {</span><br><span class="line"> left++;</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (nums[left] <= nums[mid]) {</span><br><span class="line"> <span class="keyword">if</span> (nums[left] <= target && target < nums[mid]) {</span><br><span class="line"> right = mid - <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> left = mid + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span> (nums[mid] < target && target <= nums[right]) {</span><br><span class="line"> left = mid + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> right = mid - <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h1 id="2-可重复排序数组"><a href="#2-可重复排序数组" class="headerlink" title="2. 可重复排序数组"></a>2. 可重复排序数组</h1><h2 id="1-可重复排序数组元素位置-第一次出现-插入位置"><a href="#1-可重复排序数组元素位置-第一次出现-插入位置" class="headerlink" title="1. 可重复排序数组元素位置/第一次出现/插入位置"></a>1. 可重复排序数组元素位置/第一次出现/插入位置</h2><ol><li><code>right = mid</code>找到元素最左索引,然后遍历;</li></ol><h3 id="LeetCode-34"><a href="#LeetCode-34" class="headerlink" title="LeetCode 34"></a><a href="https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/er-fen-cha-zhao-suan-fa-xi-jie-xiang-jie-by-labula/" target="_blank" rel="noopener">LeetCode 34</a></h3><h4 id="题解-4"><a href="#题解-4" class="headerlink" title="题解"></a>题解</h4><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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><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) {</span><br><span class="line"> <span class="keyword">if</span> (nums == <span class="keyword">null</span> || nums.length == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[]{-<span class="number">1</span>, -<span class="number">1</span>};</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">0</span>, right = nums.length;</span><br><span class="line"> <span class="keyword">while</span> (left < right) {</span><br><span class="line"> <span class="keyword">int</span> mid = (left + right) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (target == nums[mid]) {</span><br><span class="line"> right = mid;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (target < nums[mid]) {</span><br><span class="line"> right = mid;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (target > nums[mid]) {</span><br><span class="line"> left = mid + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (left == nums.length || nums[left] != target) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[]{-<span class="number">1</span>, -<span class="number">1</span>};</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">int</span> i = left;</span><br><span class="line"> <span class="keyword">while</span> (i < nums.length) {</span><br><span class="line"> <span class="comment">//注意越界;</span></span><br><span class="line"> <span class="keyword">if</span> (nums[i] == target) {</span><br><span class="line"> i++;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="keyword">int</span>[]{left, i - <span class="number">1</span>};</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h1 id="3-有序矩阵找target"><a href="#3-有序矩阵找target" class="headerlink" title="3. 有序矩阵找target"></a>3. 有序矩阵找target</h1><h2 id="1-各行各列递增矩阵"><a href="#1-各行各列递增矩阵" class="headerlink" title="1. 各行各列递增矩阵"></a>1. 各行各列递增矩阵</h2><ol><li>从左下角向上遍历,target大<code>right++</code>,target小<code>up--</code>;</li></ol><h3 id="Leetcode-240"><a href="#Leetcode-240" class="headerlink" title="Leetcode 240"></a><a href="https://leetcode-cn.com/problems/search-a-2d-matrix-ii/" target="_blank" rel="noopener">Leetcode 240</a></h3><p>编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:</p><ul><li>每行的元素从左到右升序排列。</li><li>每列的元素从上到下升序排列。</li></ul><h4 id="题解-5"><a href="#题解-5" class="headerlink" title="题解"></a>题解</h4><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="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">Find</span><span class="params">(<span class="keyword">int</span> target, <span class="keyword">int</span>[][] array)</span> </span>{</span><br><span class="line"> <span class="comment">//防止array[0]越界</span></span><br><span class="line"> <span class="keyword">if</span> (array.length == <span class="number">0</span> || array[<span class="number">0</span>].length == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">int</span> up = array.length - <span class="number">1</span>, right = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">int</span> len = array[<span class="number">0</span>].length - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (up >= <span class="number">0</span> && right <= len) {</span><br><span class="line"> <span class="keyword">int</span> temp = array[up][right];</span><br><span class="line"> <span class="keyword">if</span> (temp == target) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (target < temp) {</span><br><span class="line"> up = up - <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (target > temp) {</span><br><span class="line"> right = right + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="2-所有数严格递增"><a href="#2-所有数严格递增" class="headerlink" title="2. 所有数严格递增"></a>2. 所有数严格递增</h2><ol><li>展开成一维,中间元素位置<code>matrix[mid / n][mid % n]</code>;</li></ol><h3 id="Leetcode-74"><a href="#Leetcode-74" class="headerlink" title="Leetcode 74"></a><a href="https://leetcode-cn.com/problems/search-a-2d-matrix/" target="_blank" rel="noopener">Leetcode 74</a></h3><p>编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:</p><ul><li>每行中的整数从左到右按升序排列。</li><li>每行的第一个整数大于前一行的最后一个整数。</li></ul><h4 id="题解-6"><a href="#题解-6" class="headerlink" title="题解"></a>题解</h4><p>当做长度为m * n的数组,row = idx / n, col = idx % n;</p><ul><li>初始化左右序号<br>left = 0 和 right = m x n - 1。</li><li>While left < right :<ul><li>选取虚数组最中间的序号作为中间序号: pivot_idx = (left + right) / 2。</li><li>该序号对应于原矩阵中的 row = pivot_idx // n行 col = pivot_idx % n 列, 由此可以拿到中间元素pivot_element。该元素将虚数组分为两部分。</li><li>比较 pivot_element 与 target 以确定在哪一部分进行进一步查找。<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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> <span class="keyword">int</span> m = matrix.length;</span><br><span class="line"> <span class="keyword">if</span> (m == <span class="number">0</span>) <span class="keyword">return</span> <span class="keyword">false</span>;</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="comment">// 二分查找</span></span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">0</span>, right = m * n - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">int</span> pivotIdx, pivotElement;</span><br><span class="line"> <span class="keyword">while</span> (left <= right) {</span><br><span class="line"> pivotIdx = (left + right) / <span class="number">2</span>;</span><br><span class="line"> pivotElement = matrix[pivotIdx / n][pivotIdx % n];</span><br><span class="line"> <span class="keyword">if</span> (target == pivotElement) <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span> (target < pivotElement) right = pivotIdx - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">else</span> left = pivotIdx + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul></li></ul><h1 id="4-山峰问题"><a href="#4-山峰问题" class="headerlink" title="4. 山峰问题"></a>4. 山峰问题</h1><h2 id="1-寻找任意一个峰值"><a href="#1-寻找任意一个峰值" class="headerlink" title="1. 寻找任意一个峰值"></a>1. 寻找任意一个峰值</h2><ol><li>若<code>nums[mid] < nums[mid + 1]</code>证明峰值还在右边所以<code>left = mid + 1</code>;</li><li>若<code>nums[mid] > nums[mid + 1]</code>证明峰值还在左边所以<code>right = mid</code>;</li></ol><h3 id="LeetCode-162"><a href="#LeetCode-162" class="headerlink" title="LeetCode 162"></a><a href="https://leetcode-cn.com/problems/find-peak-element/solution/xun-zhao-feng-zhi-by-leetcode/" target="_blank" rel="noopener">LeetCode 162</a></h3><p>峰值元素是指其值大于左右相邻值的元素。</p><p>给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。</p><p>数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。</p><h4 id="题解-7"><a href="#题解-7" 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><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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> <span class="keyword">if</span> (nums == <span class="keyword">null</span> || nums.length == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">int</span> left = <span class="number">0</span>, right = nums.length - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> (left < right) {</span><br><span class="line"> <span class="keyword">int</span> mid = (left + right) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (nums[mid] > nums[mid + <span class="number">1</span>]) {</span><br><span class="line"> right = mid;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> left = mid + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> left;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h1 id="5-技巧型二分"><a href="#5-技巧型二分" class="headerlink" title="5. 技巧型二分"></a>5. 技巧型二分</h1><h2 id="1-求平方根"><a href="#1-求平方根" class="headerlink" title="1. 求平方根"></a>1. 求平方根</h2><p><a href="https://leetcode-cn.com/problems/sqrtx/solution/er-fen-cha-zhao-niu-dun-fa-python-dai-ma-by-liweiw/" target="_blank" rel="noopener">69. Sqrt(x)</a><br>实现 int sqrt(int x) 函数。计算并返回 x 的平方根,其中 x 是非负整数。<br>由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。</p><h3 id="题解一"><a href="#题解一" class="headerlink" title="题解一"></a>题解一</h3><ol><li>target在左侧时<code>right = mid - 1</code>,否则<code>left = mid</code>;</li><li>所以mid必须取右中值,防止剩两个元素时死循环;<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="class"><span class="keyword">class</span> <span class="title">Solution</span> </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>{</span><br><span class="line"> <span class="keyword">long</span> start = <span class="number">0</span>, end = Integer.MAX_VALUE;</span><br><span class="line"> <span class="comment">//最后用到start, 所以保证跳出循环时left=right;</span></span><br><span class="line"> <span class="keyword">while</span> (start < end) {</span><br><span class="line"> <span class="comment">//必须取右中位数,否则start=mid一直死循环;</span></span><br><span class="line"> <span class="keyword">long</span> mid = (start + end + <span class="number">1</span>) >>> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (mid * mid > x) {</span><br><span class="line"> end = mid - <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> start = mid;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> (<span class="keyword">int</span>) start;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h2 id="2-寻找重复数"><a href="#2-寻找重复数" class="headerlink" title="2. 寻找重复数"></a>2. <a href="/判圈问题#link">寻找重复数</a></h2>]]></content>
<categories>
<category> 算法 </category>
<category> LeetCode </category>
<category> 二分法 </category>
</categories>
<tags>
<tag> 二分法 </tag>
</tags>
</entry>
</search>