Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
### 📊 Repository Stats

[![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)
[![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)
[![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)
[![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)
[![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)

</div>

Expand Down Expand Up @@ -104,6 +104,7 @@ make lint-python # Lint Python files with ruff
| # | Title | Solution | Time | Space | Difficulty | Tag | Note |
|---|-------|----------|------|-------|------------|-----|------|
| 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 | | |
| 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 | | |

## Two Pointers

Expand Down
17 changes: 17 additions & 0 deletions problems/contains_duplicate/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
problem:
number: 217
title: "Contains Duplicate"
leetcode_url: "https://leetcode.com/problems/contains-duplicate/description/"
difficulty: "easy"
tags: ["Arrays & Hashing"]

solutions:
python: "problems/contains_duplicate/contains_duplicate.py"
cpp: "problems/contains_duplicate/contains_duplicate.cc"

complexity:
time: "O(n)"
space: "O(n)"

notes: ""
readme_link: ""
16 changes: 16 additions & 0 deletions problems/contains_duplicate/contains_duplicate.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "contains_duplicate.h"

#include <unordered_set>
#include <vector>

bool containsDuplicate(std::vector<int>& nums) {
std::unordered_set<int> seen;
seen.reserve(nums.size());
for (const int& num : nums) {
if (auto iter = seen.find(num); iter != seen.end()) {
return true;
}
seen.insert(num);
}
return false;
}
3 changes: 3 additions & 0 deletions problems/contains_duplicate/contains_duplicate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include <vector>

bool containsDuplicate(std::vector<int>& nums);
10 changes: 10 additions & 0 deletions problems/contains_duplicate/contains_duplicate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import List


def containsDuplicate(nums: List[int]) -> bool:
seen = set()
for num in nums:
if num in seen:
return True
seen.add(num)
return False
84 changes: 84 additions & 0 deletions problems/contains_duplicate/contains_duplicate_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "contains_duplicate.h"

#include <gtest/gtest.h>
#include <climits>
#include <string>
#include <vector>

struct ContainsDuplicateCase {
std::string test_name;
std::vector<int> nums;
bool expected;
};

using ContainsDuplicateTest = ::testing::TestWithParam<ContainsDuplicateCase>;

TEST_P(ContainsDuplicateTest, TestCases) {
const ContainsDuplicateCase &testCase = GetParam();
std::vector<int> nums = testCase.nums; // Copy since function takes non-const reference
const bool result = containsDuplicate(nums);
EXPECT_EQ(result, testCase.expected);
}

INSTANTIATE_TEST_SUITE_P(
ContainsDuplicateTestCases, ContainsDuplicateTest,
::testing::Values(
// Boundary conditions
ContainsDuplicateCase{.test_name = "EmptyArray", .nums = {}, .expected = false},
ContainsDuplicateCase{.test_name = "SingleElement", .nums = {42}, .expected = false},

// Basic cases
ContainsDuplicateCase{.test_name = "TwoUnique", .nums = {1, 2}, .expected = false},
ContainsDuplicateCase{.test_name = "TwoDuplicate", .nums = {1, 1}, .expected = true},
ContainsDuplicateCase{.test_name = "ThreeUnique", .nums = {1, 2, 3}, .expected = false},
ContainsDuplicateCase{
.test_name = "ThreeWithDuplicate", .nums = {1, 2, 1}, .expected = true},

// Edge cases with special values
ContainsDuplicateCase{.test_name = "ZeroDuplicate", .nums = {0, 1, 0}, .expected = true},
ContainsDuplicateCase{
.test_name = "NegativeDuplicate", .nums = {-1, -2, -1}, .expected = true},
ContainsDuplicateCase{
.test_name = "MinMaxValues", .nums = {INT_MIN, INT_MAX, INT_MIN}, .expected = true},

// Position sensitivity
ContainsDuplicateCase{
.test_name = "DuplicateAtEnd", .nums = {1, 2, 3, 4, 5, 1}, .expected = true},
ContainsDuplicateCase{
.test_name = "DuplicateAtBoundaries", .nums = {5, 1, 2, 3, 4, 5}, .expected = true},

// Performance edge cases
ContainsDuplicateCase{.test_name = "LargeUniqueArray",
.nums =
[]() {
std::vector<int> v;
v.reserve(100);
for (int i = 0; i < 100; ++i) {
v.push_back(i);
}
return v;
}(),
.expected = false},
ContainsDuplicateCase{.test_name = "ManyDuplicates",
.nums =
[]() {
std::vector<int> v(50, 1);
v.push_back(2);
return v;
}(),
.expected = true},
ContainsDuplicateCase{.test_name = "LargeArrayOneDuplicate",
.nums =
[]() {
std::vector<int> v;
v.reserve(5001);
for (int i = 0; i < 5000; ++i) {
v.push_back(i);
}
v.push_back(2500); // Introduce a single duplicate
return v;
}(),
.expected = true}),
[](const ::testing::TestParamInfo<ContainsDuplicateCase> &info) {
return info.param.test_name;
});
50 changes: 50 additions & 0 deletions problems/contains_duplicate/contains_duplicate_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Test cases for the contains_duplicate function."""

import pytest

from contains_duplicate import containsDuplicate


@pytest.mark.parametrize(
"nums, expected",
[
# Boundary conditions
([], False),
([42], False),
# Basic cases
([1, 2], False),
([1, 1], True),
([1, 2, 3], False),
([1, 2, 1], True),
# Edge cases with special values
([0, 1, 0], True),
([-1, -2, -1], True),
([0, -0], True), # 0 and -0 are equal
# Position sensitivity
([1, 2, 3, 4, 5, 1], True), # duplicate at end
([5, 1, 2, 3, 4, 5], True), # duplicate at start/end
# Performance edge cases
(list(range(100)), False), # no duplicates, larger array
([1] * 50 + [2], True), # many duplicates
(list(range(5000)) + [2500], True), # large array with one duplicate
],
ids=[
"empty_array",
"single_element",
"two_unique",
"two_duplicate",
"three_unique",
"three_with_duplicate",
"zero_duplicate",
"negative_duplicate",
"zero_negative_zero",
"duplicate_at_end",
"duplicate_at_boundaries",
"large_unique_array",
"many_duplicates",
"large_array_one_duplicate",
],
)
def test_contains_duplicate(nums, expected):
"""Test containsDuplicate with various input scenarios."""
assert containsDuplicate(nums) == expected