Skip to content

Commit fb752c4

Browse files
mathusanm6Copilot
andauthored
feat: add problem (217. Contains Duplicate) with unit testing (#70)
closes #69 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 927077f commit fb752c4

File tree

7 files changed

+183
-2
lines changed

7 files changed

+183
-2
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
### 📊 Repository Stats
1616

1717
[![Last Commit](https://img.shields.io/github/last-commit/mathusanm6/LeetCode?style=for-the-badge&logo=git&logoColor=white)](https://github.com/mathusanm6/LeetCode/commits/main)
18-
[![C++ Solutions](https://img.shields.io/badge/C%2B%2B%20Solutions-2-blue?style=for-the-badge&logo=cplusplus&logoColor=white)](https://github.com/mathusanm6/LeetCode/tree/main/problems)
19-
[![Python Solutions](https://img.shields.io/badge/Python%20Solutions-2-green?style=for-the-badge&logo=python&logoColor=white)](https://github.com/mathusanm6/LeetCode/tree/main/problems)
18+
[![C++ Solutions](https://img.shields.io/badge/C%2B%2B%20Solutions-3-blue?style=for-the-badge&logo=cplusplus&logoColor=white)](https://github.com/mathusanm6/LeetCode/tree/main/problems)
19+
[![Python Solutions](https://img.shields.io/badge/Python%20Solutions-3-green?style=for-the-badge&logo=python&logoColor=white)](https://github.com/mathusanm6/LeetCode/tree/main/problems)
2020

2121
</div>
2222

@@ -104,6 +104,7 @@ make lint-python # Lint Python files with ruff
104104
| # | Title | Solution | Time | Space | Difficulty | Tag | Note |
105105
|---|-------|----------|------|-------|------------|-----|------|
106106
| 1 | [Two Sum](https://leetcode.com/problems/two-sum/) | [Python](./problems/two_sum/two_sum.py), [C++](./problems/two_sum/two_sum.cc) | _O(n)_ | _O(n)_ | Easy | | |
107+
| 217 | [Contains Duplicate](https://leetcode.com/problems/contains-duplicate/description/) | [Python](./problems/contains_duplicate/contains_duplicate.py), [C++](./problems/contains_duplicate/contains_duplicate.cc) | _O(n)_ | _O(n)_ | Easy | | |
107108

108109
## Two Pointers
109110

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
problem:
2+
number: 217
3+
title: "Contains Duplicate"
4+
leetcode_url: "https://leetcode.com/problems/contains-duplicate/description/"
5+
difficulty: "easy"
6+
tags: ["Arrays & Hashing"]
7+
8+
solutions:
9+
python: "problems/contains_duplicate/contains_duplicate.py"
10+
cpp: "problems/contains_duplicate/contains_duplicate.cc"
11+
12+
complexity:
13+
time: "O(n)"
14+
space: "O(n)"
15+
16+
notes: ""
17+
readme_link: ""
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "contains_duplicate.h"
2+
3+
#include <unordered_set>
4+
#include <vector>
5+
6+
bool containsDuplicate(std::vector<int>& nums) {
7+
std::unordered_set<int> seen;
8+
seen.reserve(nums.size());
9+
for (const int& num : nums) {
10+
if (auto iter = seen.find(num); iter != seen.end()) {
11+
return true;
12+
}
13+
seen.insert(num);
14+
}
15+
return false;
16+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include <vector>
2+
3+
bool containsDuplicate(std::vector<int>& nums);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from typing import List
2+
3+
4+
def containsDuplicate(nums: List[int]) -> bool:
5+
seen = set()
6+
for num in nums:
7+
if num in seen:
8+
return True
9+
seen.add(num)
10+
return False
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include "contains_duplicate.h"
2+
3+
#include <gtest/gtest.h>
4+
#include <climits>
5+
#include <string>
6+
#include <vector>
7+
8+
struct ContainsDuplicateCase {
9+
std::string test_name;
10+
std::vector<int> nums;
11+
bool expected;
12+
};
13+
14+
using ContainsDuplicateTest = ::testing::TestWithParam<ContainsDuplicateCase>;
15+
16+
TEST_P(ContainsDuplicateTest, TestCases) {
17+
const ContainsDuplicateCase &testCase = GetParam();
18+
std::vector<int> nums = testCase.nums; // Copy since function takes non-const reference
19+
const bool result = containsDuplicate(nums);
20+
EXPECT_EQ(result, testCase.expected);
21+
}
22+
23+
INSTANTIATE_TEST_SUITE_P(
24+
ContainsDuplicateTestCases, ContainsDuplicateTest,
25+
::testing::Values(
26+
// Boundary conditions
27+
ContainsDuplicateCase{.test_name = "EmptyArray", .nums = {}, .expected = false},
28+
ContainsDuplicateCase{.test_name = "SingleElement", .nums = {42}, .expected = false},
29+
30+
// Basic cases
31+
ContainsDuplicateCase{.test_name = "TwoUnique", .nums = {1, 2}, .expected = false},
32+
ContainsDuplicateCase{.test_name = "TwoDuplicate", .nums = {1, 1}, .expected = true},
33+
ContainsDuplicateCase{.test_name = "ThreeUnique", .nums = {1, 2, 3}, .expected = false},
34+
ContainsDuplicateCase{
35+
.test_name = "ThreeWithDuplicate", .nums = {1, 2, 1}, .expected = true},
36+
37+
// Edge cases with special values
38+
ContainsDuplicateCase{.test_name = "ZeroDuplicate", .nums = {0, 1, 0}, .expected = true},
39+
ContainsDuplicateCase{
40+
.test_name = "NegativeDuplicate", .nums = {-1, -2, -1}, .expected = true},
41+
ContainsDuplicateCase{
42+
.test_name = "MinMaxValues", .nums = {INT_MIN, INT_MAX, INT_MIN}, .expected = true},
43+
44+
// Position sensitivity
45+
ContainsDuplicateCase{
46+
.test_name = "DuplicateAtEnd", .nums = {1, 2, 3, 4, 5, 1}, .expected = true},
47+
ContainsDuplicateCase{
48+
.test_name = "DuplicateAtBoundaries", .nums = {5, 1, 2, 3, 4, 5}, .expected = true},
49+
50+
// Performance edge cases
51+
ContainsDuplicateCase{.test_name = "LargeUniqueArray",
52+
.nums =
53+
[]() {
54+
std::vector<int> v;
55+
v.reserve(100);
56+
for (int i = 0; i < 100; ++i) {
57+
v.push_back(i);
58+
}
59+
return v;
60+
}(),
61+
.expected = false},
62+
ContainsDuplicateCase{.test_name = "ManyDuplicates",
63+
.nums =
64+
[]() {
65+
std::vector<int> v(50, 1);
66+
v.push_back(2);
67+
return v;
68+
}(),
69+
.expected = true},
70+
ContainsDuplicateCase{.test_name = "LargeArrayOneDuplicate",
71+
.nums =
72+
[]() {
73+
std::vector<int> v;
74+
v.reserve(5001);
75+
for (int i = 0; i < 5000; ++i) {
76+
v.push_back(i);
77+
}
78+
v.push_back(2500); // Introduce a single duplicate
79+
return v;
80+
}(),
81+
.expected = true}),
82+
[](const ::testing::TestParamInfo<ContainsDuplicateCase> &info) {
83+
return info.param.test_name;
84+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Test cases for the contains_duplicate function."""
2+
3+
import pytest
4+
5+
from contains_duplicate import containsDuplicate
6+
7+
8+
@pytest.mark.parametrize(
9+
"nums, expected",
10+
[
11+
# Boundary conditions
12+
([], False),
13+
([42], False),
14+
# Basic cases
15+
([1, 2], False),
16+
([1, 1], True),
17+
([1, 2, 3], False),
18+
([1, 2, 1], True),
19+
# Edge cases with special values
20+
([0, 1, 0], True),
21+
([-1, -2, -1], True),
22+
([0, -0], True), # 0 and -0 are equal
23+
# Position sensitivity
24+
([1, 2, 3, 4, 5, 1], True), # duplicate at end
25+
([5, 1, 2, 3, 4, 5], True), # duplicate at start/end
26+
# Performance edge cases
27+
(list(range(100)), False), # no duplicates, larger array
28+
([1] * 50 + [2], True), # many duplicates
29+
(list(range(5000)) + [2500], True), # large array with one duplicate
30+
],
31+
ids=[
32+
"empty_array",
33+
"single_element",
34+
"two_unique",
35+
"two_duplicate",
36+
"three_unique",
37+
"three_with_duplicate",
38+
"zero_duplicate",
39+
"negative_duplicate",
40+
"zero_negative_zero",
41+
"duplicate_at_end",
42+
"duplicate_at_boundaries",
43+
"large_unique_array",
44+
"many_duplicates",
45+
"large_array_one_duplicate",
46+
],
47+
)
48+
def test_contains_duplicate(nums, expected):
49+
"""Test containsDuplicate with various input scenarios."""
50+
assert containsDuplicate(nums) == expected

0 commit comments

Comments
 (0)