Skip to content

Commit

Permalink
leetcode: Add index file to 0532
Browse files Browse the repository at this point in the history
  • Loading branch information
XuShaohua committed Apr 29, 2024
1 parent b41738b commit 32668b4
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 15 deletions.

This file was deleted.

This file was deleted.

4 changes: 2 additions & 2 deletions src/leetcode/0219.contains-duplicate-ii/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

这个方法比较直接, 就是遍历数组, 并遍历后面的每个元素, 判断它们是否重复.

![brute-force](assets/brute-force.svg)
![brute-force](../0001.two-sum/assets/brute-force.svg)

因为有两层遍历, 这个方法的时间复杂度是 `O(n^2)`.

Expand All @@ -22,7 +22,7 @@
同样是需要遍历整个数组, 我们可以使用哈稀表缓存一下访问过的元素, 以加快查找元素的时间.
这个哈稀表用于记录元素值到它在数组中的索引值之间的关系.

![hash-table](assets/hash-table.svg)
![hash-table](../0001.two-sum/assets/hash-table.svg)

这个方法的时间复杂度是 `O(nlogn)`.

Expand Down
2 changes: 1 addition & 1 deletion src/leetcode/0349.intersection-of-two-arrays/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

这是一个搜索问题, 这个问题的解法就比较多了.

## 并行双指针
## 并行双指针 Parallel Two Pointers

这个也比较符合[并行双指针](../../two-pointers/parallel.md)的使用场景, 遍历两个数组或链表,
用它能很快地计算集合的交集和并集.
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion src/leetcode/0350.intersection-of-two-arrays-ii/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
[0349. 两个数组的交集 Intersection of Two Arrays](../0349.intersection-of-two-arrays/index.md) 有提到过,
`HashSet` 可以用来处理不包含重复元素的集合, 而 `HashMap` 可以用来处理包含有重复元素的集合.

![hash-table](assets/hash-table.svg)
![hash-table](../0001.two-sum/assets/hash-table.svg)

```rust
{{#include src/main.rs:41:70 }}
Expand Down
50 changes: 50 additions & 0 deletions src/leetcode/0532.k-diff-pairs-in-an-array/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
# 0532.数组中的数对 K-diff Pairs in an Array

[问题描述](../problems/0532.k-diff-pairs-in-an-array/content.html)

这是一个查找问题, 先思考一下处理查找问题的常用手段:

- 哈稀表或者 HashSet
- BitSet
- 排序后二分查找
- 排序后快慢型双指针遍历

## 哈稀表 Hash Table

使用哈稀表 HashMap 来统计整数值及其次数; 用集合 HashSet 来存放的有序数对, 并去掉重复的.

![hash-table](../0001.two-sum/assets/hash-table.svg)

这种方法可以支持无序数组.

```rust
{{#include src/main.rs:8:42 }}
```

## 二分查找法 Binary Search

基本的思路是:

- 先给数组排序
- 开始遍历数组
- 根据题目条件, 确定目标的元素的值; 使用二分查找法搜索目标元素
- 再根据要求, 判断目标元素是否合适, 比如两者索引值不能相同

```rust
{{#include src/main.rs:133:181 }}
```

## 快慢型双指针 Fast-Slow Two Pointers

[这个方法](../../two-pointers/fast-slow.md)的效率是最高的, 也最节省内存.

解决问题之前依然要先给数组排序.

![fast-slow two-pointers](../../two-pointers/assets/fast-slow.svg)

这个题目中, 双指针的命中条件是 `nums[fast] - nums[slow] = k;`, 只需要围绕这个核心条件做判断即可.

```rust
{{#include src/main.rs:183:233 }}
```

## 相关问题

- [0349. 两个数组的交集 Intersection of Two Arrays](../0349.intersection-of-two-arrays/index.md)
53 changes: 45 additions & 8 deletions src/leetcode/0532.k-diff-pairs-in-an-array/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};

// 哈稀表
// 哈稀表来计数
pub fn find_pairs1(nums: Vec<i32>, k: i32) -> i32 {
assert!(!nums.is_empty());

Expand All @@ -14,6 +14,7 @@ pub fn find_pairs1(nums: Vec<i32>, k: i32) -> i32 {
map.entry(num).and_modify(|count| *count += 1).or_insert(1);
}

// 使用集合来去重.
let mut set = HashSet::new();
for &num in &nums {
// k = diff - num;
Expand All @@ -40,9 +41,34 @@ pub fn find_pairs1(nums: Vec<i32>, k: i32) -> i32 {
set.len() as i32
}

// 给数组排序后二分查找, 使用集合来去掉重复的 pair.
// 哈稀表来计数, 对数组排序
pub fn find_pairs2(nums: Vec<i32>, k: i32) -> i32 {
assert!(!nums.is_empty());
let mut nums = nums;
nums.sort();

let mut map = HashMap::new();
for num in &nums {
map.entry(num).and_modify(|count| *count += 1).or_insert(1);
}

// 使用集合来去重.
let mut set = HashSet::new();
for &num in &nums {
let expected = num + k;
if let Some(count) = map.get(&expected) {
if (expected > num) || ((expected == num) && (*count > 1)) {
set.insert(vec![num, expected]);
}
}
}

set.len() as i32
}

// 给数组排序后二分查找, 使用集合来去掉重复的 pair.
pub fn find_pairs3(nums: Vec<i32>, k: i32) -> i32 {
assert!(!nums.is_empty());

// 先排序
let mut nums = nums;
Expand All @@ -60,7 +86,7 @@ pub fn find_pairs2(nums: Vec<i32>, k: i32) -> i32 {
}

// 排序后二分查找, 不使用额外内存.
pub fn find_pairs3(nums: Vec<i32>, k: i32) -> i32 {
pub fn find_pairs4(nums: Vec<i32>, k: i32) -> i32 {
assert!(!nums.is_empty());

// 先排序
Expand Down Expand Up @@ -105,7 +131,7 @@ pub fn find_pairs3(nums: Vec<i32>, k: i32) -> i32 {
}

// 排序后二分查找, 不使用额外内存. 根据 k == 0 做优化
pub fn find_pairs4(nums: Vec<i32>, k: i32) -> i32 {
pub fn find_pairs5(nums: Vec<i32>, k: i32) -> i32 {
assert!(!nums.is_empty());

// 先排序
Expand Down Expand Up @@ -154,8 +180,8 @@ pub fn find_pairs4(nums: Vec<i32>, k: i32) -> i32 {
count
}

// 快慢型二分查找
pub fn find_pairs5(nums: Vec<i32>, k: i32) -> i32 {
// 快慢型双指针
pub fn find_pairs6(nums: Vec<i32>, k: i32) -> i32 {
let len = nums.len();
if len <= 1 {
return 0;
Expand All @@ -171,7 +197,7 @@ pub fn find_pairs5(nums: Vec<i32>, k: i32) -> i32 {
let mut count = 0;

// 遍历整个数组.
while slow < len && fast < len {
while fast < len {
// 两个指针不能重复, 因为题目要求: `i != j`.
if fast == slow {
fast += 1;
Expand All @@ -193,9 +219,11 @@ pub fn find_pairs5(nums: Vec<i32>, k: i32) -> i32 {
}
}
Ordering::Less => {
// 两个元素间的差值太小了, 移动 fast 指针
fast += 1;
}
Ordering::Greater => {
// 两个元素间的差值太大了, 移动 slow 指针
slow += 1;
}
}
Expand Down Expand Up @@ -226,11 +254,15 @@ fn main() {
check_solution(find_pairs3);
check_solution(find_pairs4);
check_solution(find_pairs5);
check_solution(find_pairs6);
}

#[cfg(test)]
mod tests {
use super::{check_solution, find_pairs1, find_pairs2, find_pairs3, find_pairs4, find_pairs5};
use super::{
check_solution, find_pairs1, find_pairs2, find_pairs3, find_pairs4, find_pairs5,
find_pairs6,
};

#[test]
fn test_find_pairs1() {
Expand All @@ -256,4 +288,9 @@ mod tests {
fn test_find_pairs5() {
check_solution(find_pairs5);
}

#[test]
fn test_find_pairs6() {
check_solution(find_pairs6);
}
}

0 comments on commit 32668b4

Please sign in to comment.