Home > Software design >  Can this algorithm be improved to linear time?
Can this algorithm be improved to linear time?

Time:03-18

I have a counter like below:

counter = Counter({'a': 2, 'b': 1, 'c': 1, 'd':1, 'e':1})

I want to update its count based on lookup from another dictionary, dict1, which stores compatibility information of keys in the counter. For example, in dict1,

'a': ['b','d']

'a' is compatible with 'b' and 'd', so I want to update a's count from 2 to 4, because it is both compatible with b and d.

I wrote this piece of code, but it uses two loops. Is it possible to use one loop to achieve the same effect?

counter = Counter({'a': 2, 'b': 1, 'c': 1, 'd':1, 'e':1})
dict1 = {'a': ['b','d'], 'b':['a','d'], 'd':['a','b'], 'c':['e'], 'e':['c']}

keys = list(counter.keys())
count = len(keys)
for i in range(count):
    current = keys[i]
    for j in range(i 1, count):
        next = keys[j]
        comps = dict1.get(current, None)
        if comps and next in comps:
            counter[current]  = 1

CodePudding user response:

No, you can't do better than quadratic.

Let n be the number of keys in the counter. Then, each key can be compatible with O(n) other keys, for which we must do linear work in order to enumerate. There are n keys, so we have an operation that must take at least O(n) time, repeated across n keys, meaning that the best we can do is O(n^2).

CodePudding user response:

I don't think it can be done in linear time since you need to sum over all compatible values for all keys in counter. You can do this much more cleanly though:

In [3]: {k: sum(map(counter.get, dict1[k]), v) for k, v in counter.items()}
Out[3]: {'a': 4, 'b': 4, 'c': 2, 'd': 4, 'e': 2}

BTW I don't think your result is correct, unless I'm misunderstanding your logic.

  • Related