Suppose I have an array A of size N and want to perform Q queries and each query is the type -
"X L R" where X is an element that I want to add in array A from location L to R.
Mathematical format like-
N=5
A=[1 4 3 2 4]
Q=2
X L R=[[5 1 2],
[-5 1 3]]
my algorithm for this problem is like this-
#python code
N=int(input())
A=list(map(int,input().split()))
Q=int(input())
L=[list(map(int,input().split())) for i in range(Q)]
for i in range(Q):
for j in range(L[i][1]-1,L[i][2]):
A[j]=A[j]+L[i][0]
but my code takes a long time hence I want to reduce the time of this code.
How I can reduce the time of this code anyone has any idea please let me know.
Thank you.
What you basically need is a difference array. That would allow you to get Q update queries done in O(1) time each, plus O(N) complexity to recreate the original array.
n = 5
a = [1, 4, 3, 2, 4]
q = 2
xlr = [[5, 1, 2], [-5, 1, 3]]
for item in xlr:
# create the list to be inserted first
to_add = [item[0]]*(item[2]-item[1])
a[item[1]:item[1]] = to_add
print(a)
Inside the for loop, I first create the list that needs to be inserted at the desired location. After that, I set the list that needs to be inserted at the position identified by the element xlr[i][1].
Generated output - [1, -5, -5, 5, 4, 3, 2, 4]
Related
There is this question, 189 Rotate array on Leetcode. enter link description here Its statement is "Given an array, rotate the array to the right by k steps, where k is non-negative."
To understand it better, here's an example.
enter image description here
So, My code for this is
for _ in range(k):
j = nums[-1]
nums.remove(nums[-1])
nums.insert(0, j)
It cannot pass some of the test cases in it.
In the discussion panel, I found a code claiming it got submitted successfully that went like
for _ in range(k):
nums.insert(0, nums.pop(-1))
I would like to know, what is the difference between these two and why my code isn't able to pass some of the test cases.
If you do this on python shell [].remove.__doc__, you'll see the purpose of list.remove is to:
Remove first occurrence of value. Raises ValueError if the value is
not present.
In your code nums.remove(nums[-1]) does not remove the last item, but first occurrence of the value of your last item.
E.g.
If you have a list with values nums = [2, 4, 8, 3, 4] and if you do nums.remove(nums[-1]) the content of nums becomes [2, 8, 3, 4] not [2, 4, 8, 3] that you're expecting.
Just use slicing:
>>> def rotate(l, n):
... return l[-n:] + l[:-n]
...
>>> lst = [1, 2, 3, 4, 5, 6, 7]
>>> rotate(lst, 1)
[7, 1, 2, 3, 4, 5, 6]
>>> rotate(lst, 2)
[6, 7, 1, 2, 3, 4, 5]
>>> rotate(lst, 3)
[5, 6, 7, 1, 2, 3, 4]
In your code j = nums[-1] and you are trying to insert(0, nums[-1]).
In
for _ in range(k):
nums.insert(0, nums.pop(-1))
inserting other number - (0, nums.pop(-1))
Answer given by cesarv is good and simple, but on large arrays numpy will definitely perform better. Consider:
np.roll(lst, n)
The remove() method takes a single element as an argument and removes it's first occurence from the list.
The pop() method takes a single argument (index). The argument passed to the method is optional. If not passed, the default index -1 is passed as an argument (index of the last item).
If the test case has the same item before the last index then test case will fail.
Hence to correct your code replace remove with pop
for _ in range(k):
poppedElement = nums.pop()
nums.insert(0, poppedElement)
or to make it even concise -
for _ in range(k):
nums.insert(0, nums.pop())
I've been given a homework task that asks me to find in a list of data the greatest continuous increase. i.e [1,2,3,4,5,3,1,2,3] the greatest static increase here is 4.
I've written a function that takes a single list and spits out a list of sublists like this.
def group_data(lst):
sublist= [[lst[0]]]
for i in range(1, len(lst)):
if lst[i-1] < lst[i]:
sublist[-1].append(lst[i])
else:
sublist.append([lst[i]])
return(sublist)
Which does what it's supposed to
group_data([1,2,3,4,5,6,7,8,9,10,1,2,3,5,4,7,8])
Out[3]: [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 5], [4, 7, 8]]
And I now want to subtract the last element of each individual list from the first to find their differences. But I'm having difficulty figuring out how to map the function to each list rather than each element of the list. Any help would be greatly appreciated.
you can do it using map function where arr is your grouped list
list(map(lambda x: x[-1]-x[0], arr ))
For this problem I think itertools.groupby would be a good choice. Since your final goal is to find the difference of longest consecutive numbers:
from itertools import groupby
max_l = max([len(list(g)) - 1 for k, g in groupby(enumerate([1,2,3,4,5,6,7,8,9,10,1,2,3,5,4,7,8]), key=lambda x: x[0] - x[1])])
print(max_l)
#it will print 9
Explanation:
First groupby the numbers with the difference between index and number value. For example [0, 1, 2, 4] will create [0, 0, 0, 1] as the index of 0 is 0, so 0-0=0, for the second one 1-1=0. Then take the maximum length of the grouped list. Since you want difference, I used len(list(g)) - 1
I am trying to save the result of a nested for loop in a list in python. can someone tell me how to do it?
V is an array containing [1, 2, 3]
while n is the length = 3
and sq is the matrix containing swaps.
i have tried many approaches but whenever i return the result it only gives me one element of the list.
any help would be appreciated. Thankyou
def Permute1(sq,v,n):
for i in range(n):
for j in range(n):
if (sq[i,j]==1):
temp=v[i]
v[i]=v[j]
v[j]=temp
print(v)
results:
[1, 2, 3]
[2, 1, 3]
[3, 1, 2]
[3, 1, 2]
[3, 2, 1]
[3, 2, 1]
I'm not sure what is the utility of d = vhere.
To swap two elements in Python, I recommend:
v[i], v[j] = v[j], v[i]
Declaring an empty list before for loops and append the values (like AkshayNevrekar said) can also be useful, depending on what you need as a result.
def Permute1(sq,v,n):
result=[]
for i in range(n):
for j in range(n):
if (sq[i,j]==1):
temp=v[i]
v[i]=v[j]
v[j]=temp
result += [v]
print(result)
return result
No tested but may be it can help.
Check yield.
You can use this to generate all the permutations and process each one of them & store them in a list.
I have an array a = [1, 2, 3, 4, 5, 6] and b = [1, 3, 5] and I'd like to map a such that for every element in a that's between an element in b it will get mapped to the index of b that is the upper range that a is contained in. Not the best explanation in words but here's an example
a = 1 -> 0 because a <= first element of b
a = 2 -> 1 because b[0] < 2 <= b[1] and b[1] = 3
a = 3 -> 1
a = 4 -> 2 because b[1] < 4 <= b[2]
So the final product I want is f(a, b) = [0, 1, 1, 2, 2, 2]
I know I can just loop and solve for it but I was wondering if there is a clever, fast (vectorized) way to do this in pandas/numpy
Use python's bisect module:
from bisect import bisect_left
a = [1, 2, 3, 4, 5, 6]
b = [1, 3, 5]
def f(_a, _b):
return [bisect_left(_b, i) for i in _a]
print(f(a, b))
bisect — Array bisection algorithm
This module provides support for maintaining a list in sorted order without having to sort the list after each insertion. For long lists of items with expensive comparison operations, this can be an improvement over the more common approach. The module is called bisect because it uses a basic bisection algorithm to do its work. The source code may be most useful as a working example of the algorithm (the boundary conditions are already right!).
The following functions are provided:
bisect.bisect_left(a, x, lo=0, hi=len(a))
Locate the insertion point for x in a to maintain sorted order. The parameters lo and hi may be used to specify a subset of the list which should be considered; by default the entire list is used. If x is already present in a, the insertion point will be before (to the left of) any existing entries.
The return value is suitable for use as the first parameter to list.insert() assuming that a is already sorted.
The returned insertion point i partitions the array a into two halves so that all(val < x for val in a[lo:i]) for the left side and all(val >= x for val in a[i:hi]) for the right side.
Reference:
https://docs.python.org/3/library/bisect.html
bisect is faster: the solution assumes lists are sorted
a = [1, 2, 3, 4, 5, 6]
b = [1, 3, 5]
inds=[min(bisect_left(b,x),len(b)-1) for x in a]
returns
[0, 1, 1, 2, 2, 2]
I have a generator which tries to mimic realtime. This generator makes sure that the user has no access to the future but only to current time.
To simplify my case i use this generator
def generator(n):
for x in range(n):
yield [[x],[x+3]]
if run for n = 5 the generator returns:
[[0], [3]]
[[1], [4]]
[[2], [5]]
[[3], [6]]
[[4], [7]]
I want to be able to combine the elements of each generator iteration with the elements of previous generator iteration to compute sum() of inner lists
case 1:
sum([0]), sum([3])
case 2:
sum([0,1]), sum([3,4])
case 3:
sum([0,1,2]), sum([3,4,5])
...
case LAST
sum([0,1,2,3,4]), sum([3,4,5,6,7])
I don't see how this can be achieved by using:
for x in generator(5):
do sum operation
the values that I will use in the for loop will be gone for the next iteration.
Please do not focus on the numbers and the results, but mainly on the logic and algorithm behind a possible solution. In this case for me it is important to be able to preserve the situation where access to future data is not allowed, only data from the past can be used for calculations, however the data that I consider from the past is already gone when the for iteration is ended!
Any solution? Suggestions?
Thanks in advance!
l1, l2 = [], []
for x1, x2 in generator(5):
l1.extend(x1)
l2.extend(x2)
print sum(l1), sum(l2)
Seems pretty straightforward. It's not like the generator can force you to forget what it gave you. If the operation you want to do is something as simple as sum, you don't even need to keep all the old data, just its sum.
sum1 = sum2 = 0
for x1, x2 in generator(5)
sum1 += x1[0]
sum2 += x2[0]
If the number of lists you need is dynamic, that's easy to handle:
lists = [[] for _ in xrange(numberoflists)]
for subtuple in generator(5):
for element, sublist in zip(subtuple, lists):
sublist.extend(element)
do_whatever_with(map(sum, lists))
I hope I understood this correctly, but are you trying to do something like this?
>>> tmp = [[],[]]
>>> for x in generator(5):
tmp[0] += x[0]
tmp[1] += x[1]
print sum(tmp[0]),sum(tmp[1])
0, 3
1, 7
3, 12
6, 18
10, 25
>>> tmp
[[0, 1, 2, 3, 4], [3, 4, 5, 6, 7]]
Or if you don't want to save the entire list:
>>> tmp = [0,0]
>>> for x in generator(5):
tmp[0] += x[0][0]
tmp[1] += x[1][0]
print tmp[0],tmp[1]
0, 3
1, 7
3, 12
6, 18
10, 25