Skip to content

Commit

Permalink
leetcode: Add two-pointer method to 0532
Browse files Browse the repository at this point in the history
  • Loading branch information
XuShaohua committed Apr 29, 2024
1 parent 4c7ba05 commit b41738b
Showing 1 changed file with 73 additions and 22 deletions.
95 changes: 73 additions & 22 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 @@ -2,6 +2,7 @@
// Use of this source is governed by General Public License that can be found
// in the LICENSE file.

use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};

// 哈稀表
Expand All @@ -19,12 +20,8 @@ pub fn find_pairs1(nums: Vec<i32>, k: i32) -> i32 {
// diff1 >= num
let diff1 = num + k;
if let Some(count) = map.get(&diff1) {
if diff1 > num {
if (diff1 > num) || ((diff1 == num) && (*count > 1)) {
set.insert(vec![num, diff1]);
} else if diff1 == num {
if *count > 1 {
set.insert(vec![num, diff1]);
}
}
}

Expand All @@ -34,18 +31,16 @@ pub fn find_pairs1(nums: Vec<i32>, k: i32) -> i32 {
if let Some(count) = map.get(&diff2) {
if diff2 < num {
set.insert(vec![diff2, num]);
} else if diff2 == num {
if *count > 1 {
set.insert(vec![num, diff2]);
}
} else if (diff2 == num) && (*count > 1) {
set.insert(vec![num, diff2]);
}
}
}

set.len() as i32
}

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

Expand All @@ -64,52 +59,52 @@ pub fn find_pairs2(nums: Vec<i32>, k: i32) -> i32 {
set.len() as i32
}

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

// 先排序
let mut nums = nums;
nums.sort();

let mut fast = 0;
let mut index = 0;
let len = nums.len();
let mut count = 0;

// 遍历数组
while fast < len {
let curr_val = nums[fast];
while index < len {
let curr_val = nums[index];
let expected_val = curr_val + k;
// 当前值和期待值是否相等, 即 k 是否为0.
if expected_val == curr_val {
// 只保留两个重复元素, 跳过其它的.
let mut added = false;
while fast + 1 < len && curr_val == nums[fast + 1] {
while index + 1 < len && curr_val == nums[index + 1] {
if !added {
count += 1;
added = true;
}
fast += 1;
index += 1;
}
} else {
// 跳过所有重复元素
while fast + 1 < len && curr_val == nums[fast + 1] {
fast += 1;
while index + 1 < len && curr_val == nums[index + 1] {
index += 1;
}
// 使用二分查找法在后面的元素里搜索 `expected_val`.
if fast + 1 < len && nums[fast + 1..].binary_search(&expected_val).is_ok() {
if index + 1 < len && nums[index + 1..].binary_search(&expected_val).is_ok() {
count += 1;
}
}

// 指针向前走一步
fast += 1;
index += 1;
}

count
}

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

Expand Down Expand Up @@ -159,6 +154,56 @@ pub fn find_pairs4(nums: Vec<i32>, k: i32) -> i32 {
count
}

// 快慢型二分查找
pub fn find_pairs5(nums: Vec<i32>, k: i32) -> i32 {
let len = nums.len();
if len <= 1 {
return 0;
}

let mut nums = nums;
// 先排序
nums.sort();

// 初始化两个指针, 两个指针不能重复.
let mut fast = 1;
let mut slow = 0;
let mut count = 0;

// 遍历整个数组.
while slow < len && fast < len {
// 两个指针不能重复, 因为题目要求: `i != j`.
if fast == slow {
fast += 1;
continue;
}

match (nums[fast] - nums[slow]).cmp(&k) {
Ordering::Equal => {
count += 1;
let curr_slow = nums[slow];
let curr_fast = nums[fast];

// 跳过重复元素
while slow < len && curr_slow == nums[slow] {
slow += 1;
}
while fast < len && curr_fast == nums[fast] {
fast += 1;
}
}
Ordering::Less => {
fast += 1;
}
Ordering::Greater => {
slow += 1;
}
}
}

count
}

pub type SolutionFn = fn(Vec<i32>, i32) -> i32;

fn check_solution(func: SolutionFn) {
Expand All @@ -180,11 +225,12 @@ fn main() {
check_solution(find_pairs2);
check_solution(find_pairs3);
check_solution(find_pairs4);
check_solution(find_pairs5);
}

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

#[test]
fn test_find_pairs1() {
Expand All @@ -205,4 +251,9 @@ mod tests {
fn test_find_pairs4() {
check_solution(find_pairs4);
}

#[test]
fn test_find_pairs5() {
check_solution(find_pairs5);
}
}

0 comments on commit b41738b

Please sign in to comment.