9
votes

I have to design and implement a TwoSum class. It should support the following operations:

  • add - Add the number to an internal data structure.
  • find - Find if there exists any pair of numbers which sum is equal to the value.

Here is my code:

class TwoSum(object):

    dict = {}

    def add(self,n):
        dict[n] = n #TypeError: 'type' object does not support item assignment

    def find(self,n):
        for i in range(0,len(dict)+1):
            if dict[i] == None:
                continue

            val = n - dict[i]
            if dict[val] != None and val != i+1:
                return True
        return False

test = TwoSum()
test.add(1)
test.add(3)
test.add(5)
print(test.find(4))  # True
print(test.find(7))  # False

I got error message

TypeError: 'type' object does not support item assignment for "dict[n] = n"

Any help or suggestion? Thank you so much!

4
What's this code supposed to do? - Keatinge
Python instance attributes should be created in __init__, not at class level, and you need to access them through self. - user2357112 supports Monica
Also you're overwriting the python's dict. Rename it so something like numbers_dict - Keatinge
Reading your requirements you are using the wrong data structure too. You should be using a list not a dict for this - Keatinge

4 Answers

6
votes

Lot of issues here, I'll try to go through them one by one

The data structure

dict = {}

Not only is this overwriting python's dict, (see mgilson's comment) but this is the wrong data structure for the project. You should use a list instead (or a set if you have unique unordered values)

Using the data structure

The data structure is an instance variable, it needs to be defined with self and inside the __init__ function. You should be using something like this:

class TwoSum(object):
    def __init__(self):
        self.numbers = []

def add

def add(self,n):
        dict[n] = n

Assigning items to a dictionairy is not the way to do it. You should instead append to your list. Additionally you need to append to the list for that instance using self.variableName = value

def find

That range is wrong, and you would need a nested range, or itertools.combinations since you have to check for any two numbers that sum to a certain value, pythons sum() is handy here.

To loop through the numbers you can use two ranges or itertools.combinations

The code

import itertools

class TwoSum(object):
    def __init__(self):
        self.numbers = []

    def add(self, num):
        self.numbers.append(num)

    def find(self, desiredSum):
        for nums in itertools.combinations(self.numbers, 2):
            if sum(nums) == desiredSum:
                return True
        return False


test = TwoSum()
test.add(1)
test.add(3)
test.add(5)
print(test.find(4))
print(test.find(7))
#True
#False

Def find without itertools

def find(self, desiredSum):
        for num1 in self.numbers:
            for num2 in self.numbers:
                if num1 + num2 == desiredSum and num1 != num2:
                    return True
        return False
2
votes

The dict at the class level and the dict in the method are different

In the method, dict is the builtin python type. If you want to modify the dict on the class, you could try something like type(self).dict[n] = n

Also, for what it's worth, if your dict is always going to have the value == key, you might want to consider using a set instead.

Finally, you'd probably be better off defining dict as an instance attribute rather than a class attribute:

class TwoSum(object):
    def __init__(self):
        self.added_items = set()  # Make the `dict` -> `set` swap here too...
    def add(self, n):
        self.added_items.add(n)
1
votes
class TwoSum(object):
    def __init__(self):
        self.__data = []

    def __repr__(self):
        return repr(self.__data)

    def add(self, n):
        self.__data.append(n)

    def find(self, n):
        for i, v in enumerate(self.__data):
            for x, v2 in enumerate(self.__data):
                if i!= x and v + v2 == n:
                    return True
        return False
1
votes

Here is my solution, just another reference for any potential people who may see this question. Basically, I combined all above answers to get this solution. Credits to @Keatinge, @mgilson, @TheLazyScripter. Thank you guys all.

class TwoSum(object):
    def __init__(self):
        self.added_items = set()  # Make the `dict` -> `set` swap here too...
    def add(self, n):
        self.added_items.add(n)
    def find(self, n):
        for nums in itertools.combinations(self.added_items, 2):
            if sum(nums) == n:
                return True
        return False

test = TwoSum()
test.add(1)
test.add(3)
test.add(5)
print(test.find(4))
print(test.find(7))