Python: Finding Lowest Unique Integer from List - python-2.7

I am trying to find out lowest unique element from list. I have been able to generate O(n^2) and O(n) solutions. But I don't find them optimized. Kindly help me understand,if there is a possible O(n) solution for it. No one liner solutions please. Below are my codes:
Main function:
if __name__ =="__main__":
print uniqueMinimum([6, 2, 6, -6, 45, -6, 6])
print lowestUnique([5, 10, 6, -6, 3, -6, 16])
O(n^2) Solution:
def lowestUnique(arr):
num = max(arr)
for i in range(len(arr)):
check = False
for j in range(len(arr)):
if arr[i]==arr[j] and i!=j:
check =True
if check==False:
if num > arr[i]:
num = arr[i]
return num
I would like to avoid using max(array) in above solution.
O(n) Solution:
def uniqueMinimum(array):
d ={}
a =[]
num = max(array)
for i in range(len(array)):
k =d.get(array[i])
if k is None:
d[array[i]] = 1
a.append(array[i])
else:
d[array[i]] = k+1
if array[i] in a:
a.remove(array[i])
a.sort()
return a[0]

I can't really comment on the big-O since it depends on the implementation of the built-in python functions which I've never looked into. Here's a more reasonable implementation though:
def lowestUnique(array):
for element in sorted(list(set(array))):
if array.count(element) == 1:
return element
raise Exception('No unique elements found.')

Related

heaps and priority queue with pseudocode

I have a question at school that i need to find the kth minimum elements in a min heap. the run time that was required is o(k^2) and i understood how to do that. but if i can get it down to o(k*logk) that i get a bonus. i thought about doing a priority queue from the min heap and then inserting the node of the heap to the queue and then taking it out then doing the same thing with the children of the root of the minimum heap and so on k times. i know that the time complexity of insert and pop operations is o(logk) since The initial size of the priority queue is one, and it increases by at most one at each of the k steps. Therefore, there are maximum k+1 elements in the priority queue.
i understand what i need to do but find it complex to implement it in pseudo code any ideas or guidelines would be great.
Thank you
Yes, your idea sounds good. I will show how to do this in Python.
Build heap from array
So, first build a min heap on top of your input array:
def create_min_heap(array):
min_heap = []
for value in array:
heappush(min_heap, value)
return min_heap
Count k min elements off the heap
Create a helper min-heap that will be used to retrieve all k minimum elements in O(klogk). At each step, a minimum element will be popped from it, and its 2 children nodes will be added (children can be found in the original min-heap). Please note, that it doesn't make sense to add children of other nodes to the helper min-heap because they cannot be smaller than their parents (per heap property).
def k_min_elements(min_heap, k):
result = list()
helper_min_heap = []
heappush(helper_min_heap, (min_heap[0],0))
while len(result) < k:
min_node = heappop(helper_min_heap)
value = min_node[0]
index = min_node[1]
left_index = index*2 + 1
right_index = left_index + 1
if left_index < len(min_heap):
heappush(helper_min_heap, (min_heap[left_index], left_index))
if right_index < len(min_heap):
heappush(helper_min_heap, (min_heap[right_index], right_index))
result.append(value)
return result
Full Code
Now, the full code and sample output.
from heapq import heappop
from heapq import heappush
def create_min_heap(array):
min_heap = []
for value in array:
heappush(min_heap, value)
return min_heap
def k_min_elements(min_heap, k):
if k > len(min_heap) or k < 0:
raise Exception("k is invalid")
result = list()
helper_min_heap = []
heappush(helper_min_heap, (min_heap[0],0))
while len(result) < k:
min_node = heappop(helper_min_heap)
value = min_node[0]
index = min_node[1]
left_index = index*2 + 1
right_index = left_index + 1
if left_index < len(min_heap):
heappush(helper_min_heap, (min_heap[left_index], left_index))
if right_index < len(min_heap):
heappush(helper_min_heap, (min_heap[right_index], right_index))
result.append(value)
return result
min_heap = create_min_heap([1, 3, 5, 7, 9, 2, 4, 6, 8, 0])
print (k_min_elements(min_heap, 3))
[0, 1, 2]

Python's faster alternative to lists for prime numbers?

I need to find the first pair of primes within specified range, these primes must be a certain difference from each other and have no other primes within that difference.
My code seems to be working, but it is painfully slow - I presume because of my use of lists to handle primes. What would be a better approach?
g=difference;
n=first number in range
m= second number in range
def gap(g,n,m):
prime_list = []
for num in range(n,m+1):
if all(num%i!=0 for i in range(2,int(num**0.5)+1)):
prime_list.append(num)
if len(prime_list)<1:
return None
for pnum in prime_list:
for index in range(len(prime_list)):
pnum2 = prime_list[index]
diff = abs(pnum - pnum2)
if diff == g:
checker = abs(prime_list.index(pnum2) - prime_list.index(pnum))
if checker <=1:
return [pnum, pnum2]
Some tests:
Test.assert_equals(gap(2,100,110), [101, 103])
Test.assert_equals(gap(4,100,110), [103, 107])
Test.assert_equals(gap(2, 10000000, 11000000), [10000139, 10000141])
Why store the primes in a list at all? You only need to remember one at a time. You'll be working through them in ascending order and, as jasonharper points out, all you need to do is stop when you encounter the first delta equal to g between successive primes:
def gap(g, n, m):
previous_prime = None
for candidate in range(n, m + 1):
if all(candidate % factor for factor in range(2, int(candidate ** 0.5) + 1)):
if previous_prime is not None and candidate - previous_prime == g:
return [previous_prime, candidate]
previous_prime = candidate

Counter for a list adding up to 10

I'm currently stuck on a question regarding lists and formulating codes. I have to
For example, if list = [4,6] I would have to return 2. (4+6) and (6+4). This code has to work for any length of list and no two numbers will be the same within the list. I'm new to lists and and stuck on how to begin coding.
def countsum(list):
Would appreciate the help
def count_list_aux(num_possibilities, a_list, i, j):
if i == j: # Only 1 item to check now.
if a_list[i] == 10: # The item itself is 10 so that can be a combo.
return num_possibilities + 1
else: # Otherwise we are done.
return num_possibilities
else:
combo = a_list[i] + a_list[j]
if combo == 10: # (4,6) for instance.
return count_list_aux(num_possibilities+2, a_list, i+1, j-1)
elif combo > 10: # (4,8) for instance. Clearly 8 needs to go when we have a sorted list.
return count_list_aux(num_possibilities, a_list, i, j-1)
else: # (4,7) for instance. Clearly 4 needs to go when we have a sorted list.
return count_list_aux(num_possibilities, a_list, i+1, j)
def countsum(a_list):
a_list = sorted(a_list)
return count_list_aux(0, a_list, 0, len(a_list)-1)
print(countsum([4,6,3,7,5,2,8]))
I have made a recursive solution where I simply sort the list (ascending order) and then recursively add up left most (i) and right most (j) and check if they add up to 10. If they do, then I increment num_possibiltiies by 2 (eg. 6,4 and 4,6 are 2 combos). If the sum is greater than 10, then I decrement j by 1 because clearly, the current index j cannot work with any other values in the list (list is sorted). Similarly, if the sum is smaller than 10, I increment i by 1 as the current index i cannot work with any other values to get a sum of 10 (it failed with the largest value at index j).
The function can also be implemented using:
from itertools import combinations
from math import factorial
def countsum(L):
x = 10
n = 2
return sum(factorial(n) for c in combinations(L, n) if sum(c) == x)
The factorial is because combinations produces tuples that are sets of items, rather than counting each of the permutations, simply compute their count. As the factorial depends on a constant it can be hoisted:
def countsum(L):
x = 10
n = 2
return factorial(n) * sum(1 for c in combinations(L, n) if sum(c) == x)

Common List Elements

Alright, so I have a small issue:
def common(a,b,c):
a.sort()
b.sort()
c.sort()
i = 0
j = 0
k = 0
common=False
while i<len(a) and j<len(b):
if a[i] == b[j]:
if b[j] == c[k]:
return True
else:
k = k+1
continue
else:
if i == len(a):
j = j+1
else:
i = i+1
return common
a=[3, 1, 5, 10]
b=[4, 2, 6, 1]
c=[5, 3, 1, 7]
print common(a,b,c)
Basically, it has to tell me if there are common elements in the lists. With 1 it works, but if I replace the 1's with 8's, it doesn't work anymore.
Your 'j' never increase, 1 is working because after sort it is the 1st element and doesn't need j to be increased.
My suggestion is convert your lists to sets and check the common elements using intersection(&)
def common(a,b,c):
common = set(a) & set(b) & set(c)
return True if common else False
a=[3, 8, 5, 10]
b=[4, 2, 6, 8]
c=[5, 3, 8, 7]
print common(a,b,c)
Your current algorithm only works if the smallest value in the b list is common to the other lists. If there's a different common value, you'll never find it, because you'll increment i until it is len(a), then quit.
I think you need to change your logic so that you increment the index of the list that points at the smallest value. If a[i] is less than b[j], you need to increment i. If c[k] is less still, you should increment it instead.
What you've programmed is not doing at all what you expect, so you need to rethink your logic. If you look at your loop, you first check if a[0] matches b[0]. Nope, so add to i. Then you compare a[1] to b[0], nope and so on. If nothing matches b[0], you exit the loop without ever checking the other elements of b. It works with 1's in your lists because after you sort, those happen to be in the first position in all three lists.
In any case, this is pretty clunky. There's a much easier way of doing this via set intersection. See this related question.

For a given integer a, find all unique combinations of positive integers that sum up to a

Not a homework question.
I was going through the questions here and I came across this question.
Someone has answered it. I have tried a lot to understand the recursion used but I am not able to get it. Could someone explain it to me?
Write a function, for a given number, print out all different ways to make this number, by using addition and any number equal to or smaller than this number and greater than zero.
For example, given a = 5, we have the following seven ways to make up 5:
1, 1, 1, 1, 1
1, 4
1, 1, 1, 2
1, 1, 3
2, 3
1, 2, 2
5
The solution from the site is in C++:
void printSeq( int num , int a[] , int len , int s )
{
if( num <= 0 )
{
for( int j = 0 ; j < len ; j++ )
cout << a[ j ] << "," ;
cout << endl;
return;
}
for(int i = s ; i <= num ; i++)
{
a[ len ] = i;
printSeq( num - i , a , len + 1 , i );
}
}
int main()
{
int a[5];
printSeq(5,a,0,1);
cin.get();
return 0;
}
When facing a problem like this it is often a good idea to take a step back from your editor/IDE and think about the problem by drawing out a simple case on a whiteboard. Don't even do pseudo-code yet, just draw out a flowchart of how a simple case (e.g. a = 3) for this problem would turtle all the way down. Also, don't worry about duplicate combinations at first. Try to find a solution which gives you all the desired combinations, then improve your solution to not give you duplicates. In this case, why not look at the manageable case of a = 3? Let me draw a little picture for you. A green checkmark means that we have arrived at a valid combination, a red cross means that a combination is invalid.
As you can see, we start with three empty subcombinations and then build three new subcombinations by appending a number to each of them. We want to examine all possible paths, so we choose 1, 2 and 3 and end up with [1], [2] and [3]. If the sum of the numbers in a combination equals 3, we have found a valid combination, so we can stop to examine this path. If the sum of the numbers in a combination exceeds 3, the combination is invalid and we can stop as well. If neither is the case, we simply continue to build combinations until we arrive at either a valid or invalid solution.
Since your question seems to be primarily about how to work out a recursive solution for this kind of problems and less about specific syntax and you just happened to find a C++ solution I am going to provide a solution in Python (it almost looks like pseudo code and it's what it know).
def getcombs(a, combo = None):
# initialize combo on first call of the function
if combo == None:
combo = []
combosum = sum(combo) # sum of numbers in the combo, note that sum([]) == 0
# simple case: we have a valid combination of numbers, i.e. combosum == a
if combosum == a:
yield combo # this simply gives us that combination, no recursion here!
# recursive case: the combination of numbers does not sum to a (yet)
else:
for number in range(1, a + 1): # try each number from 1 to a
if combosum + number <= a: # only proceed if we don't exceed a
extcombo = combo + [number] # append the number to the combo
# give me all valid combinations c that can be built from extcombo
for c in getcombs(a, extcombo):
yield c
Let's test the code!
>>> combos = getcombs(3)
>>> for combo in combos: print(combo)
...
[1, 1, 1]
[1, 2]
[2, 1]
[3]
This seems to work fine, another test for a = 5:
>>> combos = getcombs(5)
>>> for combo in combos: print(combo)
...
[1, 1, 1, 1, 1]
[1, 1, 1, 2]
[1, 1, 2, 1]
[1, 1, 3]
[1, 2, 1, 1]
[1, 2, 2]
[1, 3, 1]
[1, 4]
[2, 1, 1, 1]
[2, 1, 2]
[2, 2, 1]
[2, 3]
[3, 1, 1]
[3, 2]
[4, 1]
[5]
The solution includes all seven combinations we were looking for, but the code still produces duplicates. As you may have noticed, it is not necessary to take a number smaller than the previous chosen number to generate all combinations. So let's add some code that only starts to build an extcombo for numbers which are not smaller than the currently last number in a combination. If the combination is empty, we just set the previous number to 1.
def getcombs(a, combo = None):
# initialize combo on first call of the function
if combo == None:
combo = []
combosum = sum(combo) # sum of numbers in combo, note that sum([]) == 0
# simple case: we have a valid combination of numbers, i.e. combosum == a
if combosum == a:
yield combo # this simply gives us that combination, no recursion here!
# recursive case: the combination of numbers does not sum to a (yet)
else:
lastnumber = combo[-1] if combo else 1 # last number appended
for number in range(lastnumber, a + 1): # try each number between lastnumber and a
if combosum + number <= a:
extcombo = combo + [number] # append the number to the combo
# give me all valid combinations that can be built from extcombo
for c in getcombs(a, extcombo):
yield c
Once again, let's test the code!
>>> combo = getcombs(5)
>>> for combo in combos: print(combo)
...
[1, 1, 1, 1, 1]
[1, 1, 1, 2]
[1, 1, 3]
[1, 2, 2]
[1, 4]
[2, 3]
[5]
The presented solution may not be the most efficient one that exists, but hopefully it will encourage you to think recursively. Break a problem down step by step, draw out a simple case for small inputs and solve one problem at a time.
Leaving the solution aside for moment and looking at the problem itself:
Compare this problem to insertion sort for an array(or any recursive algorithm). In insertion sort at any point during the execution we have a part of the array that is sorted and another part that is unsorted. We pick an element from the unsorted part and find it's place in the sorted part, thereby extending the sorted part, making the problem smaller.
In case of this problem, we have a fixed number of elements we can choose from i.e integers 1 to the number in the problem(let's call it N), to be a part of the sequence that sums up to N.
At any point we have collected some numbers that sum up to less than N(say X), reducing the problem to N-X size, also reducing our choices from 1..N to 1..(N-X) for the next recursion.
The solution does the obvious, making each choice from 1 to (N-X) and proceeding recursively till X=N. Every time the algorithm reaches X=N, means a permutation is found.
Note: One problem I see with the solution is that it needs to know the number of permutations that will be found beforehand.
int a[5];
This could cause problems if that value is unknown.