mirror of
https://github.com/CyC2018/Interview-Notebook.git
synced 2026-10-26 21:13:43 +00:00
Update Leetcode 题解 - 双指针.md
补充三数之和、接雨水、最小覆盖子串,并配图说明接雨水的水位计算。
This commit is contained in:
@@ -8,6 +8,9 @@
|
||||
* [5. 归并两个有序数组](#5-归并两个有序数组)
|
||||
* [6. 判断链表是否存在环](#6-判断链表是否存在环)
|
||||
* [7. 最长子序列](#7-最长子序列)
|
||||
* [8. 三数之和](#8-三数之和)
|
||||
* [9. 接雨水](#9-接雨水)
|
||||
* [10. 最小覆盖子串](#10-最小覆盖子串)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
|
||||
@@ -290,3 +293,124 @@ private boolean isSubstr(String s, String target) {
|
||||
return j == target.length();
|
||||
}
|
||||
```
|
||||
|
||||
## 8. 三数之和
|
||||
|
||||
15\. 3Sum (Medium)
|
||||
|
||||
[Leetcode](https://leetcode.com/problems/3sum/) / [力扣](https://leetcode.cn/problems/3sum/)
|
||||
|
||||
```text
|
||||
Input: nums = [-1, 0, 1, 2, -1, -4]
|
||||
Output: [[-1, -1, 2], [-1, 0, 1]]
|
||||
```
|
||||
|
||||
题目描述:找出所有和为 0 且不重复的三元组。
|
||||
|
||||
先排序,然后枚举第一个数 nums[i],在它右边用第 1 题的双指针方法寻找和为 -nums[i] 的两个数。去重的关键是跳过相同的值:i 跳过与前一个数相同的值,找到一组解之后,两个指针也跳过相同的值。时间复杂度为 O(N<sup>2</sup>)。
|
||||
|
||||
```java
|
||||
public List<List<Integer>> threeSum(int[] nums) {
|
||||
Arrays.sort(nums);
|
||||
List<List<Integer>> ret = new ArrayList<>();
|
||||
for (int i = 0; i < nums.length - 2; i++) {
|
||||
if (i > 0 && nums[i] == nums[i - 1]) {
|
||||
continue;
|
||||
}
|
||||
int l = i + 1, h = nums.length - 1;
|
||||
while (l < h) {
|
||||
int sum = nums[i] + nums[l] + nums[h];
|
||||
if (sum < 0) {
|
||||
l++;
|
||||
} else if (sum > 0) {
|
||||
h--;
|
||||
} else {
|
||||
ret.add(Arrays.asList(nums[i], nums[l], nums[h]));
|
||||
while (l < h && nums[l] == nums[l + 1]) {
|
||||
l++;
|
||||
}
|
||||
while (l < h && nums[h] == nums[h - 1]) {
|
||||
h--;
|
||||
}
|
||||
l++;
|
||||
h--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 接雨水
|
||||
|
||||
42\. Trapping Rain Water (Hard)
|
||||
|
||||
[Leetcode](https://leetcode.com/problems/trapping-rain-water/) / [力扣](https://leetcode.cn/problems/trapping-rain-water/)
|
||||
|
||||
```text
|
||||
Input: height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
|
||||
Output: 6
|
||||
```
|
||||
|
||||
位置 i 上方能存的水,取决于它左边最高的柱子和右边最高的柱子中较矮的那一个:water[i] = min(leftMax, rightMax) - height[i]。
|
||||
|
||||
用两个指针从两端向中间移动,分别维护 leftMax 和 rightMax。如果 leftMax < rightMax,左指针处的水位只由 leftMax 决定,因为右边已经有一根不低于 rightMax 的柱子,可以直接结算左指针并右移;反之结算右指针并左移。
|
||||
|
||||
<div align="center"> <img src="pics/trapping-rain-water.png" width="560px"/> </div><br>
|
||||
|
||||
```java
|
||||
public int trap(int[] height) {
|
||||
int l = 0, r = height.length - 1;
|
||||
int leftMax = 0, rightMax = 0, ret = 0;
|
||||
while (l < r) {
|
||||
leftMax = Math.max(leftMax, height[l]);
|
||||
rightMax = Math.max(rightMax, height[r]);
|
||||
if (leftMax < rightMax) {
|
||||
ret += leftMax - height[l++];
|
||||
} else {
|
||||
ret += rightMax - height[r--];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
|
||||
## 10. 最小覆盖子串
|
||||
|
||||
76\. Minimum Window Substring (Hard)
|
||||
|
||||
[Leetcode](https://leetcode.com/problems/minimum-window-substring/) / [力扣](https://leetcode.cn/problems/minimum-window-substring/)
|
||||
|
||||
```text
|
||||
Input: s = "ADOBECODEBANC", t = "ABC"
|
||||
Output: "BANC"
|
||||
```
|
||||
|
||||
题目描述:找出 s 中包含 t 所有字符(包括重复字符)的最短子串。
|
||||
|
||||
使用滑动窗口。need[c] 表示窗口还缺几个字符 c,missing 表示一共还缺几个字符。右指针不断扩大窗口,直到 missing 为 0,此时窗口包含了 t 的所有字符;然后移动左指针缩小窗口,在窗口仍然满足条件时更新答案。
|
||||
|
||||
```java
|
||||
public String minWindow(String s, String t) {
|
||||
int[] need = new int[128];
|
||||
for (char c : t.toCharArray()) {
|
||||
need[c]++;
|
||||
}
|
||||
int missing = t.length(), start = 0, minLen = Integer.MAX_VALUE;
|
||||
for (int l = 0, r = 0; r < s.length(); r++) {
|
||||
if (need[s.charAt(r)]-- > 0) {
|
||||
missing--;
|
||||
}
|
||||
while (missing == 0) {
|
||||
if (r - l + 1 < minLen) {
|
||||
minLen = r - l + 1;
|
||||
start = l;
|
||||
}
|
||||
if (++need[s.charAt(l++)] > 0) {
|
||||
missing++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);
|
||||
}
|
||||
```
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1,67 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="290" viewBox="0 0 600 290">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #666; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #777; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.sub { font-size: 11px; fill: #888; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #666; stroke-width: 1.3; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #666; stroke-width: 1.3; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #C0C0C0; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1 L9,5 L1,9" fill="none" stroke="#666" stroke-width="1.6"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1 L9,5 L1,9" fill="none" stroke="#C0605A" stroke-width="1.6"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1 L9,5 L1,9" fill="none" stroke="#6A9F68" stroke-width="1.6"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="300" y="28" class="title">接雨水</text>
|
||||
<text x="78" y="246" class="c sub">0</text>
|
||||
<rect x="98" y="190" width="36" height="40" fill="#9E9E9E"/>
|
||||
<text x="116" y="246" class="c sub">1</text>
|
||||
<rect x="136" y="190" width="36" height="40" fill="#D6EEF8"/>
|
||||
<text x="154" y="246" class="c sub">2</text>
|
||||
<rect x="174" y="150" width="36" height="80" fill="#9E9E9E"/>
|
||||
<text x="192" y="246" class="c sub">3</text>
|
||||
<rect x="212" y="150" width="36" height="40" fill="#D6EEF8"/>
|
||||
<rect x="212" y="190" width="36" height="40" fill="#9E9E9E"/>
|
||||
<text x="230" y="246" class="c sub">4</text>
|
||||
<rect x="250" y="150" width="36" height="80" fill="#D6EEF8"/>
|
||||
<text x="268" y="246" class="c sub">5</text>
|
||||
<rect x="288" y="150" width="36" height="40" fill="#D6EEF8"/>
|
||||
<rect x="288" y="190" width="36" height="40" fill="#9E9E9E"/>
|
||||
<text x="306" y="246" class="c sub">6</text>
|
||||
<rect x="326" y="110" width="36" height="120" fill="#9E9E9E"/>
|
||||
<text x="344" y="246" class="c sub">7</text>
|
||||
<rect x="364" y="150" width="36" height="80" fill="#9E9E9E"/>
|
||||
<text x="382" y="246" class="c sub">8</text>
|
||||
<rect x="402" y="150" width="36" height="40" fill="#D6EEF8"/>
|
||||
<rect x="402" y="190" width="36" height="40" fill="#9E9E9E"/>
|
||||
<text x="420" y="246" class="c sub">9</text>
|
||||
<rect x="440" y="150" width="36" height="80" fill="#9E9E9E"/>
|
||||
<text x="458" y="246" class="c sub">10</text>
|
||||
<rect x="478" y="190" width="36" height="40" fill="#9E9E9E"/>
|
||||
<text x="496" y="246" class="c sub">11</text>
|
||||
<line x1="54" y1="230" x2="516" y2="230" class="line"/>
|
||||
<line x1="174" y1="150" x2="364" y2="150" class="line dash"/>
|
||||
<text x="168" y="144" class="e note">leftMax = 2</text>
|
||||
<text x="368" y="124" class="note">rightMax = 3</text>
|
||||
<line x1="268" y1="86" x2="268" y2="146" class="arrow red"/>
|
||||
<text x="208" y="80" class="c">位置 5 存水 min(2, 3) - 0 = 2</text>
|
||||
<text x="300" y="278" class="c sub">灰色为柱子,浅蓝色为积水,总共 6</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
Reference in New Issue
Block a user