Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
You are given an array of n integers. You want to modify the array so that it is increasing, i.e., every element is at least as large as the previous element.
On each turn, you may increase the value of any element by one. What is the minimum number of turns required?
Example:
Input = 3 2 5 1 7
Output = 5
steps:
1 => 3 2+1 5 1 7
2 => 3 3 5 1+1 7
3 => 3 3 5 2+1 7
4 => 3 3 5 3+1 7
5 => 3 3 5 4+1 7
So it will take 5 turns to make this array increasing.
My approch in Python:
def makeIncreasingArray(arr, count=1):
temp = []
for i in range(1, len(arr)):
if arr[i] >= arr[i - 1]:
temp.append(True)
else:
arr[i] += 1
temp.append(False)
if sum(temp) == len(arr) - 1:
return count
else:
count += 1
return makeIncreasingArray(arr, count)
It's working but I think this one is more like bruteforce solution.
How can I make this code better?
Your approach is to keep adding 1 to each element that’s smaller than the one preceding it until the array is increasing.
Think about the first element that’s too small. You’ll keep adding 1 to it until it’s equal to the number before it. Because nothing is changing before this element (it’s the first element that’s wrong), once it’s equal to the number before it, it’ll never need to change again. So you can do all the steps at once (let’s say that i is the index of this first wrong element):
while arr[i] < arr[i - 1]:
arr[i] += 1
count += 1
Maybe with this smaller example, it’ll be clearer that this can be done without a loop (i.e. much faster):
if arr[i] < arr[i - 1]:
count += arr[i - 1] - arr[i]
arr[i] = arr[i - 1]
And since this does nothing on elements that are not wrong, all you need to do now is apply it to every element in order:
def make_increasing_array(arr):
count = 0
for i in range(1, len(arr)):
if arr[i] < arr[i - 1]:
count += arr[i - 1] - arr[i]
arr[i] = arr[i - 1]
return count
Finally, there’s no need to alter the input if you keep track of arr[i - 1] separately:
def make_increasing_array(arr):
if not arr:
return 0
count = 0
last = arr[0]
for i in range(1, len(arr)):
if arr[i] < last:
count += last - arr[i]
else:
last = arr[i]
return count
If you don't mind using NumPy, you can implement this as (np.maximum.accumulate(arr) - arr).sum().
E.g.
import numpy as np
def count_turns(x):
return (np.maximum.accumulate(x) - x).sum()
In action,
In [18]: x = [3, 2, 5, 1, 7]
In [19]: count_turns(x)
Out[19]: 5
If you want to stick with "pure" Python, you can do the same thing, with a little help from itertools.accumulate to replace np.maximum.accumulate. For example,
In [22]: from itertools import accumulate
In [23]: x = [3, 2, 5, 1, 7]
In [24]: list(accumulate(x, max))
Out[24]: [3, 3, 5, 5, 7]
Then the element-wise subtraction can be implemented using zip and a list comprehension:
In [25]: [cmax - t for cmax, t in zip(accumulate(x, max), x)]
Out[25]: [0, 1, 0, 4, 0]
Finally, the number of turns is the sum of those differences:
In [26]: sum(cmax - t for cmax, t in zip(accumulate(x, max), x))
Out[26]: 5
Putting that into a function gives
from itertools import accumulate
def count_turns(x):
return sum(cmax - t for cmax, t in zip(accumulate(x, max), x))
Related
Description:
Input a list of numbers “num_list”.
All numbers in the list occur even times expect one number which occurs odd number of times. Find the number that occurs odd number of time in O(1) space complexity and O(n) time complexity.
Note: Use Bitwise operator.
Sample Input:
1 2 2 5 5 1 3 9 3 9 6 4 4
What I tried:
def getOddOccurrence(arr, arr_size):
for i in range(0, arr_size):
count = 0
for j in range(0, arr_size):
if arr[i] == arr[j]:
count += 1
if (count % 2 != 0):
return arr[i]
return -1# driver code
arr = [1, 2, 2, 5, 5, 1, 3, 9, 3, 9, 6, 4, 4]
n = len(arr)
print(getOddOccurrence(arr, n))
Bitwise operations consists of multiple operations like AND, OR, XOR... and so on. The one you are looking for is called XOR.
XOR of number with same number is 0. So if you XOR all elements in your array, all elements occurring even number of times cancel each other out. And you are left with with the number that occurred odd number of times.
Time Complexity: O(N)
Space Complexity: O(1)
def getOddOccurrence(arr, arr_size):
if len(arr) == 0:
return -1
xor = arr[0]
for i in range(1, arr_size):
xor = xor ^ arr[i]
return xor
arr = [1,2,2,5,5,1,3,9,3,9,6,4,4 ]
n = len(arr)
print(getOddOccurrence(arr, n))
I want to square even index values in numpy array and assign same in that array. I followed 2 approaches.
1 -
for i in range(len(arr)):
if i %2 == 0:
arr[i] = arr[i]**2
That is working.
2 -
arr[i] = arr[i]**2 for i in range(len(arr)) if i % 2 == 0
File "<ipython-input-149-30fc7ed25f1f>", line 1
arr[i] = arr[i]**2 for i in range(len(arr)) if i % 2 == 0
^
SyntaxError: invalid syntax
not working.
Is some syntax error?
This works with list compreension:
arr = [arr[i]**2 if i % 2 == 0 else arr[i] for i in range(len(arr))]
But you could also use the shorter:
arr[::2] = arr[::2]**2
I assume you are trying to do list comprehension, for which your syntax is slightly off, read up on the syntax of list comprehension.
It's syntax is similar to [exp1(item) if condition1 else exp2(item) for item in arr] .
The correct way to do it is as follows.
arr = [1,2,3,4,5,6]
arr = [arr[i]**2 if i % 2 == 0 else arr[i] for i in range(len(arr))]
print(arr)
#[1, 2, 9, 4, 25, 6]
What this is doing is running the for loop, checking the condition, and then picking either arr[i] or arr[i]**2, and then assigning the result to the list
Dont loop over numpy arrays you lose all the power of numpy.
Use these numpy functions to achieve the required result instead:
import numpy as np
arr = np.random.randint(0,10, size=(10,))
print(arr)
ans = np.where(np.arange(10) % 2 == 0, arr, arr**2)
print(ans)
output:
[ 1 9 1 1 0 6 5 2 1 5 ]
[ 1 81 1 1 0 36 5 4 1 25]
np.where selects the elements where the condition is true. Then outputs either the original array or the squared array.
Docs for np.where.
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 5 years ago.
s = [[0]*3]*3
i = 0
while i < 3:
j = 0
while j < 3:
print(s[i][j])
s[i][j] += 1
j += 1
i += 1
The printed result of the above code really confused me, Why the second and third column of the array become [1,1,1] and [2,2,2] but not [0,0,0]?
Because when you create a list of lists using [[0]*3]*3, you're creating one list [0,0,0] three times, so you'll have [[0,0,0],[0,0,0],[0,0,0]], but all of the sub lists ([0,0,0]) are really refrencing the same list, since you just created one and multiplied it by 3 to create the others, so changing one list will make changes to the other lists.
To prevent this, create independent zero-ed lists using a list comprehension:
s = [[0]*3 for i in range(3)]
i = 0
while i < 3:
j = 0
while j < 3:
print(s[i][j])
s[i][j] += 1
j += 1
i += 1
print(s) # just to see the final result
Which outputs:
0
0
0
0
0
0
0
0
0
[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
because the way you create array is
s = [[0]*3]*3
which means all elements of s is the same list and once you change one of them, the rest of them will be changed too
so if you want to get [[0,0,0],[1,1,1],[2,2,2]] as you said,try this:
import numpy as np
s = np.zeros((3,3)) #in this way you can get a 3*3 array
i = 0
while i < 3:
j = 0
while j < 3
s[i][j] += i #not plus 1,otherwise you will get [[1,1,1],[1,1,1],[1,1,1]]
j += 1
i += 1
I want to write a program which would calculate the difference between all the values of an array and find whether the difference is also present in the array or not.
For eg,
a = [1,2,4,5]
for i in range(len(a)):
j = i+1
for j in range(len(a)):
dif = a[i] - a[j]
if dif in a:
print a[i], a[j], dif
The output here would be,
2 1 1
4 2 2
5 1 4
5 4 1
I want to know if there is a more efficient way of doing this? I don't want to use any python in built functions here. Without that is it possible to improve the algorithm?
Any help would be helpful
Thanks
You may use itertools.combinations to achieve this:
from itertools import combinations
a = [1,2,4,5]
for i, j in combinations(a, 2):
dif = j - i # OR, dif = abs(j - i) for checking against absolute value
if dif in a:
print j, i, dif
Above code will print:
2 1 1
5 1 4
4 2 2
5 4 1
I am analyzing counting example in python presented by Codility
I don't understand the logic used in the last loop (5 last rows) of this algorithm.
Can anybody help please?
The problem:
You are given an integer m (1 < m < 1000000) and two non-empty,
zero-indexed arrays A and B of n integers, a0, a1, ... ,
an−1 and b0, b1, ... , bn−1 respectively (0 < ai, bi < m).
The goal is to check whether there is a swap operation which can be
performed on these arrays in such a way that the sum of elements in
array A equals the sum of elements in array B after the swap. By
swap operation we mean picking one element from array A and one
element from array B and exchanging them.
The solution:
def counting(A, m):
n = len(A)
count = [0] * (m + 1)
for k in xrange(n):
count[A[k]] += 1
return count
def fast_solution(A, B, m):
n = len(A)
sum_a = sum(A)
sum_b = sum(B)
d = sum_b - sum_a
if d % 2 == 1:
return False
d //= 2
count = counting(A, m)
for i in xrange(n):
if 0 <= B[i] - d and B[i] - d <= m and count[B[i] - d] > 0:
return True
return False
What I would recommend you is read again the explanations given in the exercise. It already explains what how the algorithm works. However, if you still have problems with it, then take a piece of paper, and some very simple example arrays and go through the solution step by step.
For example, let A = [6, 6, 1, 2, 3] and B = [1, 5, 3, 2, 1].
Now let's go through the algorithm.
I assume you understand how this method works:
def counting(A, m):
n = len(A)
count = [0] * (m + 1)
for k in xrange(n):
count[A[k]] += 1
return count
It just returns a list with counts as explained in the exercise. For list A and m = 10 it will return:
[0, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0]
Then we go through the main method fast_solution(A, B, m):
n = 11 (this will be used in the loop)
The sum of A equals 18 and the sum of B equals 12.
The difference d is -6 (sum_b - sum_a), it is even. Note that if difference is odd, then no swap is available and the result is False.
Then d is divided by 2. It becomes -3.
For A we get count [0, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0] (as already mentioned before).
Then we just iterate though the list B using xrange and check the conditions (The loop goes from 0 and up to but not including 11). Let's check it step by step:
i = 0, B[0] - (-3) is 1 + 3 = 4. 4 is greater than or equal to 0 and less than or equal to 10 (remember, we have chosen m to be 10). However, count[4] is 0 and it's not greater than 0 (Note the list count starts from index 0). The condition fails, we go further.
i = 1, B[1] - (-3) is 5 + 3 = 8. 8 is greater than or equal to 0 and less than or equal to 10. However, count[8] is 0 and the condition fails.
i = 2, B[2] - (-3) is 3 + 3 = 6. 6 is greater than 0 and less than 10. Also count[6] is 2 and it is greater than 0. So we found the number. The loop stops, True is returned. It means that there is such a number in B which can be swapped with a number in A, so that sum of A becomes equal to the sum of B. Indeed, if we swap 6 in A with 3 in B, then their sum become equal to 15.
Hope this helps.
I'm not sure I get your idea correctly. Here's my understanding:
def counting(A, m):
n = len(A)
count = [0] * (m + 1)
for k in xrange(n):
count[A[k]] += 1
return count # this essentially build a counter
def fast_solution(A, B, m):
n = len(A)
sum_a = sum(A)
sum_b = sum(B)
d = sum_b - sum_a
if d % 2 == 1:
return False
d //= 2
count = counting(A, m) # get the dict
for i in xrange(n):
if 0 <= B[i] - d and B[i] - d <= m and count[B[i] - d] > 0:
# the first two conditions are to verify that B[i]-d exists as a key (index) in counter.
# then check if there actually exists the value.
# if count > 0, then you can swap the two to get same sum
return True
return False
Or rewriting to get:
def counting(A, m):
count = collections.Counter()
for i in A:
count[i] += 1
return count
def fast_solution(A, B, m):
n = len(A)
sum_a = sum(A)
sum_b = sum(B)
d = sum_b - sum_a
if d % 2 == 1:
return False
d //= 2
count = counting(A, m) # get the dict
for i in B:
if count[i-d]:
return True
return False
But in any case, this piece of code just check the solution existence with only single swap, be sure to check if that's what you wanted.