If I have a list of numbers where the numbers increase to a point and then decrease after that point, is there a finite number of guesses independent of the size of the set that I would have to make in order to find that maximum value?
The distance between the values is arbitrary and the number of values on the increasing side can be different than the number of values on the decreasing side.
What would be the best method? Check element 1, then the last element, then the half between? And repeat? Or something more sophisticated?
What would the processing time be for such an algorithm?
You could use a Binary Search comparing two neighboring elements instead of one element to a fixed value. Start at a := 0, b := n, i := (a+b)/2 and compare element(i) to element(i+1). If you notice e(i+1) > e(i), you know the breakpoint is somewhere after i, so set a := i. If e(i) < e(i-1), the opposite is true and you set b := i.
The Complexity would then be O(log n). It would be slightly slower than a regular binary search because you need more comparisons.
You could try a rcursive algorithm simmilar to ordered search, based on the number of elements in your list.
Pseudo code:
List search(int index, List listpart){
if(listpart.length()==1){ // already found
return listpart
}
else if(listpart(index+1)>listpart(i) && listpart(index-1)<listpart(i)){ //search right part
List listpart_tmp = getlistpart(listpart, index, listpart.length())
return search(index+(listpart.length()/4), listpart_tmp
}
else if(listpart(index+1)<listpart(i) && listpart(index-1)>listpart(i)){ //search left part
List listpart_tmp = getlistpart(listpart, 0, index)
return search(index-(listpart.length()/4), listpart_tmp
}
else if(listpart(index+1)<listpart(i) && listpart(index-1)<listpart(i)){ //found
return getlistpart(listpart, index, index)
}
}
The function
getlistpart
is a function that returns a list consisting of the elements in the original list between the given indices.
Related
I want to make my algorithm more efficient via deleting the items it already sorted, but i don't know how I can do it efficiently. The only way I found was to rewrite the whole list.
l = [] #Here you put your list
sl = [] # this is to store the list when it is sorted
a = 0 # variable to store which numbers he already looked for
while True: # loop
if len(sl) == len(l): #if their size is matching it will stop
print(sl) # print the sorted list
break
a = a + 1
if a in l: # check if it is in list
sl.append(a) # add to sorted list
#here i want it to be deleted from the list.
The variable a is a little awkward. It starts at 0 and increments 1 by 1 until it matches elements from the list l
Imagine if l = [1000000, 1200000, -34]. Then your algorithm will first run for 1000000 iterations without doing anything, just incrementing a from 0 to 1000000. Then it will append 1000000 to sl. Then it will run again 200000 iterations without doing anything, just incrementing a from 1000000 to 1200000.
And then it will keep incrementing a looking for the number -34, which is below zero...
I understand the idea behind your variable a is to select the elements from l in order, starting from the smallest element. There is a function that does that: it's called min(). Try using that function to select the smallest element from l, and append that element to sl. Then delete this element from l; otherwise, the next call to min() will select the same element again instead of selecting the next smallest element.
Note that min() has a disadvantage: it returns the value of the smallest element, but not its position in the list. So it's not completely obvious how to delete the element from l after you've found it with min(). An alternative is to write your own function that returns both the element, and its position. You can do that with one loop: in the following piece of code, i refers to a position in the list (0 is the position of the first element, 1 the position of the second, etc) and a refers to the value of that element. I left blanks and you have to figure out how to select the position and value of the smallest element in the list.
....
for i, a in enumerate(l):
if ...:
...
...
If you managed to do all this, congratulations! You have implemented "selection sort". It's a well-known sorting algorithm. It is one of the simplest. There exist many other sorting algorithms.
I apologize if this is a duplicate, I tried my best to find an existing question but was unsuccessful.
Recently, I've run into a couple of problems where I've needed to find the element in a list that produces the max/min value when a calculation is performed. For example, a list of real numbers where you want to find out which element produces the highest value when squared. The actual value of the squared number is unimportant, I just need the element(s) from the list that produces it.
I know I can solve the problem by finding the max, then making a pass through the list to find out which values' square matches the max I found:
l = [-0.25, 21.4, -7, 0.99, -21.4]
max_squared = max(i**2 for i in l)
result = [i for i in l if i**2 == max_squared]
but I feel like there should be a better way to do it. Is there a more concise/one-step solution to this?
This will return you just the element which gives the max when squared.
result = max(l, key = lambda k: k**2)
It does not get much better if you need the value in a list f.e. to see how often it occures. You can remeber the source element as well if you do not need that:
l = [-0.25, 21.4, -7, 0.99, -21.4]
max_squared = max( (i**2, i) for i in l) # remeber a tuple, with the result coming first
print(max_squared[1]) # print the source number (2nd element of the tuple)
Output:
21.4
Your calculation does only return the first occurence of abs(24.1) because max only returns one value, not two - if you need both, you still need to do:
print( [k for k in l if abs(k) == max_squared[1]])
to get
[21.4,-21.4]
I have the following pieces of code doing the sorting of a list by swapping pairs of elements:
# Complete the minimumSwaps function below.
def minimumSwaps(arr):
counter = 0
val_2_indx = {val: arr.index(val) for val in arr}
for indx, x in enumerate(arr):
if x != indx+1:
arr[indx] = indx+1
s_indx = val_2_indx[indx+1]
arr[s_indx] = x
val_2_indx[indx+1] = indx
val_2_indx[x] = s_indx
counter += 1
return counter
def minimumSwaps(arr):
temp = [0] * (len(arr) + 1)
for pos, val in enumerate(arr):
temp[val] = pos
swaps = 0
for i in range(len(arr)):
if arr[i] != i+1:
swaps += 1
t = arr[i]
arr[i] = i+1
arr[temp[i+1]] = t
temp[t] = temp[i+1]
temp[i+1] = i
return swaps
The second function works much faster than the first one. However, I was told that dictionary is faster than list.
What's the reason here?
A list is a data structure, and a dictionary is a data structure. It doesn't make sense to say one is "faster" than the other, any more than you can say that an apple is faster than an orange. One might grow faster, you might be able to eat the other one faster, and they might both fall to the ground at the same speed when you drop them. It's not the fruit that's faster, it's what you do with it.
If your problem is that you have a sequence of strings and you want to know the position of a given string in the sequence, then consider these options:
You can store the sequence as a list. Finding the position of a given string using the .index method requires a linear search, iterating through the list in O(n) time.
You can store a dictionary mapping strings to their positions. Finding the position of a given string requires looking it up in the dictionary, in O(1) time.
So it is faster to solve that problem using a dictionary.
But note also that in your first function, you are building the dictionary using the list's .index method - which means doing n linear searches each in O(n) time, building the dictionary in O(n^2) time because you are using a list for something lists are slow at. If you build the dictionary without doing linear searches, then it will take O(n) time instead:
val_2_indx = { val: i for i, val in enumerate(arr) }
But now consider a different problem. You have a sequence of numbers, and they happen to be the numbers from 1 to n in some order. You want to be able to look up the position of a number in the sequence:
You can store the sequence as a list. Finding the position of a given number requires linear search again, in O(n) time.
You can store them in a dictionary like before, and do lookups in O(1) time.
You can store the inverse sequence in a list, so that lst[i] holds the position of the value i in the original sequence. This works because every permutation is invertible. Now getting the position of i is a simple list access, in O(1) time.
This is a different problem, so it can take a different amount of time to solve. In this case, both the list and the dictionary allow a solution in O(1) time, but it turns out it's more efficient to use a list. Getting by key in a dictionary has a higher constant time than getting by index in a list, because getting by key in a dictionary requires computing a hash, and then probing an array to find the right index. (Getting from a list just requires accessing an array at an already-known index.)
This second problem is the one in your second function. See this part:
temp = [0] * (len(arr) + 1)
for pos, val in enumerate(arr):
temp[val] = pos
This creates a list temp, where temp[val] = pos whenever arr[pos] == val. This means the list temp is the inverse permutation of arr. Later in the code, temp is used only to get these positions by index, which is an O(1) operation and happens to be faster than looking up a key in a dictionary.
I have two lists. I have to choose one. I have to choose the one with the smallest nth element. So I can choose the smallest element easy with min, but how do I back track it to the list itself. Have literally no idea how to solve this presumably easy problem.
a = [2,45,1,56]
b= [0,23,3,87]
Which list has the smallest element at position 2? The answer here is list a.
In case I wasnt clear, the program sould be able to solve this task for any pair of lists.
Here is a very simple snippet that does what you want, but you might want to check for the size of the arrays, in case the index is out of range.
def choose_smallest(a, b, i):
if len(a) >= i or len(b) >= i:
return 0 # do whatever you want here
if a[i] < b[i]:
return a
else:
return b
Also notice that both nth elements in your array can have the exact same value... In this example array b will be returned, but you can change that behaviour if needed.
EDIT
Added array length check
According to your example, here is a sample code you can try. You can change the code as per your requirement.
a = [2,45,1,56]
b = [0,23,3,87]
n= int(input('Enter element number: ')) # n starts from zero to length of list - 1
if a[n] > b[n]:
print('List b has smaller nth element')
elif a[n] < b[n]:
print('List a has smaller nth element')
else:
print('Both lists have equal nth element')
I'm trying to find the sublist of a list (with at least one positive integer) with the following 2 properties
1. the sum of it's elements is positive
2. it has the maximum length of all the other sub lists with positive sum
I'm only interesting in the length of that list. Kadane's algorithm finds the sublist with maximum sum in O(n) time. Is there an algorithm that can do the same here in O(n)? I've found a solution but it really computes all the sublists and is of course very very slow....
thank you for your time
Calculate the sum of all the numbers say it is n.
If n > 0 then return the full list as the answer.
else
keep trimming the smaller element from both ends and subtract from the sum till the sum turns positive.
Return this as the result.
It is an O(n) algorithm.
Hope it helps
A possible solution is here. You can use Counting sort to sort the array.
After that staring form the maximum element make a sum and check that if adding this element
will retain positive sum of not, if it remain positive add that and increment count move ahead. This might have some bugs for some input,i mean it may not work for all test cases.
but, this is just an idea which may help you as some improvement to this will give you your desired output.
at the end of one traversal count variable will give u result.
example:
array=[12,10,8,5,4,-2,-3,-20,-30] //considered already sorted now
i=0 sum=12 count=1
i=1 sum=22 count=2
i=2 sum=30 count=3
i=3 sum=35 count=4
i=4 sum=39 count=5
i=5 sum=37 count=6
i=6 sum=34 count=7
i=7 sum=14 count=8
i=8 sum=14 count=8 //as now 30 cant be added
so, here count=8 says maximum length sub array of 8 can give you positive sum.
OK, you have almost answered it already. Just modify Kadane's to use length of subsequence rather than the sum of the subsequence. That solves your problem. Here is Kadane's from Wikipedia:
int sequence(int numbers[])
{
// These variables can be added in to track the position of the subarray
size_t begin = 0;
size_t begin_temp = 0;
size_t len_temp = 0;
size_t end = 0;
// Find sequence by looping through
for(size_t i = 1; i < numbers.size(); i++)
{
// calculate max_ending_here
if(max_ending_here < 0)
{
max_ending_here = numbers[i];
begin_temp = i;
}
else
{
max_ending_here += numbers[i];
len_temp += (i - begin_temp);
}
// calculate max_so_far_len
if(len_temp >= max_so_far_len )
{
max_so_far_len = len_temp;
begin = begin_temp;
end = i;
}
}
return max_so_far_len ;
}
Since in your answer u consider sub-lists as consequetive elements , I guess a slight modification in Kadane's Algo will work for you.
Just introduce a variable named max_length_till_now . And update it whenever you found a sub list with length greater than it's present value.