Search code examples
c#dictionarycontainskey

Dictionary.ContainsKey() doesn't work as expected


I'm currently trying to solve the first Leetcode problem (Two Sum):

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

You can return the answer in any order.

Example 1:

Input: nums = [2,7,11,15], target = 9

Output: [0,1]

Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].

Example 2:

Input: nums = [3,2,4], target = 6

Output: [1,2]

Example 3:

Input: nums = [3,3], target = 6

Output: [0,1]

Here's my code:

public class Solution {
    public int[] TwoSum(int[] nums, int target) {
        Dictionary<int, int> hash = new Dictionary<int, int>();
        int n = nums.Count();

        for (int i=0; i < n; i++) {
            int complement = target - nums[i];
            if (hash.ContainsKey(complement)) {
                int[] solution = new int[]{(int)i, (int)hash[complement]};
                return solution;
            }
            else {
                hash.Add(nums[i], i);
            }
        }

        return new int[]{};
    }

This code works fine until I get a list containing the same element several times.

For example:

Inputs : nums = [2,7,11,15], target = 9

Returns : [1,0]

Inputs : nums = [1,1,1,1,1,4,1,1,1,1,1,7,1,1,1,1,1] target = 11

Returns : "Unhandled exception. System.ArgumentException: An item with the same key has already been added. Key: 1"

So the program is trying to add another '1' key in my dictionary. I think it's because even if the value is the same, the object is different, but i can't find how to solve this.

Any help ? Thanks!

I just want to point out that this algorithm works perfectly. See this code in Python (works):

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hash = {}
        for i in range(len(nums)):
            complement = target - nums[i]
            if complement in hash:
                return [i, hash[complement]]
            else:
                hash[nums[i]] = i

        return []

Solution

  • Please note, that Add throws exception when you try to add the same key; you can use TryAdd instead

    public int[] TwoSum(int[] nums, int target) {
         ...
         else {
             // Add a new key if and only if it doesn't exist
             hash.TryAdd(nums[i], i);
         }
         ...
    }
    

    Your code simplified (.Length instead of Count(), TryGetValue instead of Contains etc.):

    public class Solution {
        public int[] TwoSum(int[] nums, int target) {
            var hash = new Dictionary<int, int>();
    
            for (int i = 0; i < nums.Length; ++i) 
                if (hash.TryGetValue(target - nums[i], out int index)) 
                    return new int[]{index, i};
                else 
                    hash.TryAdd(nums[i], i);
    
            return Array.Empty<int>();
        }
    }
    

    Please, fiddle yourself

    Edit: Note, that you check different keys, e.g. for nums = {1, 1, ...} and target = 11 you have for the second item

    1. hash contains single 1 key
    2. complement = 11 - 1 = 10
    3. you check hash.ContainsKey(complement) get false (hash doesn't contain 10)
    4. you try to add 1 (note, 1 not 10) and get the exception