Cost constant of pseudocode - algorithm

I understand where the cost comes from for lines 1-4, 6, and 9-10. But why is the cost of line 5 10 and the cost of line 7 6?
Max-Heap-Increase-Key(A[1...n]: array of number, i: 1<= i <= n, key)
1 if key < A[i]
2 then print " "
3 A[i] = key
4 parent = floor(i/2)
5 while i > 1 and A[parent] < A[i]
6 temp = A[i]
7 A[i] = A[parent]
8 A[parent] = temp
9 i = parent
10 parent = floor(i/2)
The constant cost for a single execution of each line are as follows:
1) 5,
2) 1,
3) 4,
4) 4,
5) 10,
6) 4,
7) 6,
8) 4,
9) 2,
10) 4
Count cost 1 for: reading a variable, writing to variable, using an array index to locate memory location, reading or writing to array index, arithmetic op, comparison (where <= or >= counts twice) and a boolean operation.

Let's look at line 5:
while i > 1 and A[parent] < A[i]
According to the rules for what we should count:
Reading a variable: i is read twice, A twice, and parent once, so there are five read operations.
Reading from an array: Twice from the array A.
Comparison: One > and one <, so there are two comparisons.
Boolean operation: One and.
Total cost is 10.
And line 7:
A[i] = A[parent]
According to the rules:
Reading a variable: A is read twice, i once, and parent once.
Reading from an array: Once, on the right-hand side.
Writing to an array: Once, on the left-hand side.
So the total cost is 6.
It remains uncertain what "using an array index to locate memory location" is supposed to mean if this is different to "reading or writing to array index". Perhaps this should be counted instead of loading the variable A? That would be strange, but it is also strange to describe it as a separate cost from reading/writing to an array.
Generally speaking, a variable like A holds a pointer to an array, so accessing an array like A[i] requires loading that pointer, then loading the index variable, and then doing the read or the write. The read or write operation consumes the pointer and index loaded in the previous two operations.

Related

Increase efficiency for following algorithm

Problem:-
input = n
output :-
1 2 3.......n [first row]
2n+1 2n+2 2n+3....3n [second row]
3n+1 3n+2 3n+3...4n [second last row]
n+1 n+2 n+3....2n [last row]
In the problem we have to print a square such that we have 'n' numbers of rows in our square and in every row we have 'n' numbers. We prepare rows from numbers from 1 to square(n) in such way we fill numbers for first row, then last row, second row, second last row and so on.....
for e.g. if n = 4
We start from 1 print upto 4 then print a newline, so our first row is:-
1 2 3 4
Then our last row comes in continuation
5 6 7 8
then our second row will be
9 10 11 12
few examples:
input = 1
output = 1
input = 2
output = 1 2
3 4
input = 3
output = 1 2 3
7 8 9
4 5 6
My Code:
n = int(input().strip())
lines = [i for i in range (1, n + 1)]
line_order1 = []
line_order2 = []
#Reordering lines so we know the staring element of our method
for i in lines:
if(i % 2 == 1):
line_order1.append(i)
else:
line_order2.append(i)
print(line_order1)
print(line_order2)
// Getting the desired order of lines
line_order2.reverse()
line_order1.extend(line_order2)
print(line_order1)
// Now printing the desired square
for l in line_order1:
for i in range (1, n+1):
k = n * (l - 1)
print(k + i, end = " ")
print("\n")
Is there a better way to do this in terms of execution time?
While I see a few minor places you can improve your code, the performance is unlikely to be much better (my suggestions below might not make any performance difference at all). Your code will take O(n**2) time, which is the best you can do, since you need to print out that many numbers to form your square. Even if you combine some of your longer, more verbose steps into more compact versions, they'll can only possibly be better by a constant factor.
My first suggestion is to number the lines from 0 to n-1 instead of from 1 to n. This will save you some effort when you have to calculate how what multiple of n to include in the values for the row. Currently you've got an awkward l - 1 in your calculation that you could skip if you just used zero-indexed numbers for the rows. (Also l is a terrible variable name, since it looks like the digit 1 (one) in some fonts.)
My next suggestion is to simplify your code that builds the order. You don't need three lists, you can do the whole thing with one list that you feed two range objects, each counting up or down by two.
line_order = list(range(0, n, 2)) # count up by twos
line_order.extend(range(n - 1 - n%2, 0, -2)) # count down starting at either n-1 or n-2
Or, if you're willing to use a standard library module, you could import itertools and then use:
line_order = itertools.chain(range(0, n, 2), range(n - 1 - n%2, 0, -2))
The itertools.chain function returns an iterator that yields values from each of its iterable arguments as if they were concatenated together, without making any copies of the data or using significant extra memory. The difference is not likely to be a much here (since the maximum n you can usefully print out is fairly small), but if you were doing something different with the result of this algorithm and n was in the billions it would be very nice to avoid filling a list with that many values.
My last suggestion is to use a range again to generate all the numbers in each row directly, rather than explicitly looping from 1 to n and adding k each time.
for row_num in line_order:
print(*range(n * row_num + 1, n * (rownum + 1) + 1))
You can compute the start and end points with the multiples of n already included, rather than needing to do that in a separate step for each one. You certainly didn't need to be recomputing k as often as you were before. You can pass all the values from the range to print in one go using iterable unpacking syntax (*args).
Note though that unpacking the range that way is sort of the reverse of the previous suggestion regarding itertools.chain. If n is large, using a loop over the range would be more memory efficient, since you won't need all n values to exist in memory at a the same time. Here's what that would look like:
for line_num in line_order:
for value in range(n * row_num + 1, n * (rownum + 1) + 1):
print(value, end=" ")
print()

How to sort K sorted arrays, with MERGE SORT

I know that this question has been asked, and there is a very nice elegant solution using a min heap.
MY question is how would one do this using the merge function of merge sort.
You already have an array of sorted arrays. So you should be able to merge all of them into one array in O(nlog K) time, correct?
I just can't figure out how to do this!
Say I have
[ [5,6], [3,4], [1,2], [0] ]
Step 1: [ [3,4,5,6], [0,1,2] ]
Step2: [ [0,1,2,3,4,5,6] ]
Is there a simple way to do this? Is O(nlog K) theoretically achievable with mergesort?
As others have said, using the min heap to hold the next items is the optimal way. It's called an N-way merge. Its complexity is O(n log k).
You can use a 2-way merge algorithm to sort k arrays. Perhaps the easiest way is to modify the standard merge sort so that it uses non-constant partition sizes. For example, imagine that you have 4 arrays with lengths 10, 8, 12, and 33. Each array is sorted. If you concatenated the arrays into one, you would have these partitions (the numbers are indexes into the array, not values):
[0-9][10-17][18-29][30-62]
The first pass of your merge sort would have starting indexes of 0 and 10. You would merge that into a new array, just as you would with the standard merge sort. The next pass would start at positions 18 and 30 in the second array. When you're done with the second pass, your output array contains:
[0-17][18-62]
Now your partitions start at 0 and 18. You merge those two into a single array and you're done.
The only real difference is that rather than starting with a partition size of 2 and doubling, you have non-constant partition sizes. As you make each pass, the new partition size is the sum of the sizes of the two partitions you used in the previous pass. This really is just a slight modification of the standard merge sort.
It will take log(k) passes to do the sort, and at each pass you look at all n items. The algorithm is O(n log k), but with a much higher constant than the N-way merge.
For implementation, build an array of integers that contains the starting indexes of each of your sub arrays. So in the example above you would have:
int[] partitions = [0, 10, 18, 30];
int numPartitions = 4;
Now you do your standard merge sort. But you select your partitions from the partitions array. So your merge would start with:
merge (inputArray, outputArray, part1Index, part2Index, outputStart)
{
part1Start = partitions[part1Index];
part2Start = partitions[part2Index];
part1Length = part2Start - part1Start;
part2Length = partitions[part2Index-1] - part2Start;
// now merge part1 and part2 into the output array,
// starting at outputStart
}
And your main loop would look something like:
while (numPartitions > 1)
{
for (int p = 0; p < numPartitions; p += 2)
{
outputStart = partitions[p];
merge(inputArray, outputArray, p, p+1, outputStart);
// update partitions table
partitions[p/2] = partitions[p] + partitions[p+1];
}
numPartitions /= 2;
}
That's the basic idea. You'll have to do some work to handle the dangling partition when the number is odd, but in general that's how it's done.
You can also do it by maintaining an array of arrays, and merging each two arrays into a new array, adding that to an output array of arrays. Lather, rinse, repeat.
You should note that when we say complexity is O(n log k), we assume that n means TOTAL number of elements in ALL of k arrays, i.e. number of elements in a final merged array.
For example, if you want to merge k arrays that contain n elements each, total number of elements in final array will be nk. So complexity will be O(nk log k).
There different ways to merge arrays. To accoplish that task in N*Log(K) time you can use a structure called Heap (it is good structure to implement priority queue). I suppose that you already have it, if you don’t then pick up any available implementation: http://en.wikipedia.org/wiki/Heap_(data_structure)
Then you can do that like this:
1. We have A[1..K] array of arrays to sort, Head[1..K] - current pointer for every array and Count[1..K] - number of items for every array.
2. We have Heap of pairs (Value: int; NumberOfArray: int) - empty at start.
3. We put to the heap first item of every array - initialization phase.
4. Then we organize cycle:
5. Get pair (Value, NumberOfArray) from the heap.
6. Value is next value to output.
7. NumberOfArray – is number of array where we need to take next item (if any) and place to the heap.
8. If heap is not empty, then repeat from step 5
So for every item we operate only with heap built from K items as maximum. It mean that we will have N*Log(K) complexity as you asked.
I implemented it in python. The main idea is similar to mergesort. There are k arrays in lists. In function mainMerageK, just divide lists (k) into left (k/2) and right (k/2). Therefore, the total count of partition is log(k). Regarding function merge, it is easy to know the runtime is O(n). Finally, we get O(nlog k)
By the way, it also can be implemented in min heap, and there is a link: Merging K- Sorted Lists using Priority Queue
def mainMergeK(*lists):
# implemented by k-way partition
k = len(lists)
if k > 1:
mid = int(k / 2)
B = mainMergeK(*lists[0: mid])
C = mainMergeK(*lists[mid:])
A = merge(B, C)
print B, ' + ', C, ' = ', A
return A
return lists[0]
def merge(B, C):
A = []
p = len(B)
q = len(C)
i = 0
j = 0
while i < p and j < q:
if B[i] <= C[j]:
A.append(B[i])
i += 1
else:
A.append(C[j])
j += 1
if i == p:
for c in C[j:]:
A.append(c)
else:
for b in B[i:]:
A.append(b)
return A
if __name__ == '__main__':
x = mainMergeK([1, 3, 5], [2, 4, 6], [7, 8, 10], [9])
print x
The output likes below:
[1, 3, 5] + [2, 4, 6] = [1, 2, 3, 4, 5, 6]
[7, 8, 10] + [9] = [7, 8, 9, 10]
[1, 2, 3, 4, 5, 6] + [7, 8, 9, 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Just do it like a 2-way merge except with K items. Will result in O(NK). If you want O(N logK) you will need to use a min-heap to keep track of the K pointers(with source array as a metadata) in the algorithm below:
Keep an array of K elements - i.e K pointers showing position in each array.
Mark all K elements are valid.
loop:
Compare values in K pointers that are valid. if the value is minimum, select least index pointer and increment it into the next value in the array. If incremented value has crossed it's array, mark it invalid.
Add the least value into the result.
Repeat till all K elements are invalid.
For example,:
Positions Arrays
p1:0 Array 1: 0 5 10
p2:3 Array 2: 3 6 9
p3:2 Array 3: 2 4 6
Output (min of 0,3,2)=> 0. So output is {0}
Array
p1:5 0 5 10
p2:3 3 6 9
p3:2 2 4 6
Output (min of 5,3,2)=> 2. So {0,2}
Array
p1:5 0 5 10
p2:3 3 6 9
p3:4 2 4 6
Output (min of 5,3,4)=>3. So {0,2,3}
..and so on..until you come to a state where output is {0,2,3,4,5,6}
Array
p1:5 0 5 10
p2:9 3 6 9
p3:6 2 4 6
Output (min of 5,9,6)=>6. So {0,2,3,4,5,6}+{6} when you mark p3 as "invalid" as you have exhausted the array. (or if you are using a min-heap you will simply remove the min-item, get it's source array metadata: in this case array 3, see that it's done so you will not add anything new to the min-heap)

best way to rewind a variable at 1?

I have an array with 12 entries.
When doing 12+1, I want to get the entry 1 of the array
When doing 12+4, I want to get the entry 4 of the array
etc...
I'm done with
cases_to_increment.each do |k|
if k > 12
k = k-12
end
self.inc(:"case#{k}", 1)
end
I found a solution with modulo
k = 13%12 = 1
k = 16%12 = 4
I like the modulo way but 12%12 return 0 and I need only numbers between 1..12
There is a way to do that without condition ?
You almost had the solution there yourself. Instead of a simple modulo, try:
index = (number % 12) + 1
Edit: njzk2 is correct, modulo is a very expensive function if you are using it with a value that is not a power of two. If, however, your total number of elements (the number you are modulo-ing with) is a power of 2, the calculation is essentially free.

Given an array that contains all elements thrice except one. Find the element which occurs once. [duplicate]

There are many numbers in an array and each number appears three times excepting for one special number appearing once. Here is the question: how can I find the special number in the array?
Now I can only put forward some methods with radix sorting and rapid sorting which cannot takes advantage the property of the question. So I need some other algorithms.
Thanks for your help.
Add the numbers bitwise mod 3, e.g.
def special(lst):
ones = 0
twos = 0
for x in lst:
twos |= ones & x
ones ^= x
not_threes = ~(ones & twos)
ones &= not_threes
twos &= not_threes
return ones
Since nobody's saying it, I will: hashtable.
You can calculate how many times each element occurs in the array in O(n) with simple hashtable (or hashmap).
If the array is sorted, the problem is trivial, you just loop through the list, three items at a time, and check if the third item is the same as the current.
If the array is not sorted, you can use a Hash Table to count the number of occurences of each numbers.
A possible algorithm (very generic, not tested) :
function findMagicNumber(arr[0...n])
magic_n := NaN
if n = 1 then
magic_n := arr[0]
else if n > 1 then
quicksort(arr)
old_n := arr[0]
repeat := 0
for i := 1 to n
cur_n := arr[i]
repeat := repeat + 1
if cur_n ≠ old_n then
if repeat = 1 then
magic_n := old_n
old_n := cur_n
repeat := 0
return magic_n
Following is another O(n) time complexity and O(1) extra space method
suggested by aj. We can sum the bits in same positions for all the numbers and take modulo with 3.
The bits for which sum is not multiple of 3, are the bits of number with single occurrence.
Let us consider
the example array {5, 5, 5, 8}.
The 101, 101, 101, 1000
Sum of first bits%3 = (1 + 1 + 1 + 0)%3 = 0;
Sum of second bits%3 = (0 + 0 + 0 + 0)%0 = 0;
Sum of third bits%3 = (1 + 1 + 1 + 0)%3 = 0;
Sum of fourth bits%3 = (1)%3 = 1;
Hence number which appears once is 1000
#include <stdio.h>
#define INT_SIZE 32
int getSingle(int arr[], int n)
{
// Initialize result
int result = 0;
int x, sum;
// Iterate through every bit
for (int i = 0; i < INT_SIZE; i++)
{
// Find sum of set bits at ith position in all
// array elements
sum = 0;
x = (1 << i);
for (int j=0; j< n; j++ )
{
if (arr[j] & x)
sum++;
}
// The bits with sum not multiple of 3, are the
// bits of element with single occurrence.
if (sum % 3)
result |= x;
}
return result;
}
// Driver program to test above function
int main()
{
int arr[] = {12, 1, 12, 3, 12, 1, 1, 2, 3, 2, 2, 3, 7};
int n = sizeof(arr) / sizeof(arr[0]);
printf("The element with single occurrence is %d ",getSingle(arr, n));
return 0;
}
How about the following?
If we assume that you know the maximum and minimum values of all numbers in the array (or can at least limit them to some maximum range, say max - min + 1, then create an auxiliary array of that size, initialized to all zeros, say AuxArray[].
Now scan your original array, say MyArray[], and for each element MyArray[i], increment
AuxArray[MyArray[i]] by one. After your scan is complete, there will be exactly one element
in AuxArray[] that equals one, and the index of that element in AuxArray[] will be the value of the special number.
No complicated search here. Just a linear order of complexity.
Hope I've made sense.
John Doner
I didnt find the implementation of bitwise mod 3 very intuitive so I wrote a more intiuitive version of the code and tested it with various examples and it worked.
Here is the code inside the loop
threes=twos&x //=find all bits counting exactly thrice
x&=~threes //remove the bits countring thrice from x as well as twos
twos&=~threes
twos|=ones&x //find all bits counting exactly twice
x&=~twos //remove all bits counting twice from modified x as well as ones
ones&=~twos
ones|=x //find all the bits from previous ones and modified x
Hope you guys find it easy to understand this version of code.
I got a solution. It's O (n) time and O (1) space.
n=list(map(int,input().split()))
l=[0]*64
for x in n:
b=bin(x)[2:]
b='0'*(64-len(b))+b
i=0
while i<len(l):
l[i]+=int(b[i])
i+=1
i=0
while i<len(l):
l[i]%=3
i+=1
s=''
for x in l:
s+=str(x)
print(int(s,2))
int main()
{
int B[] = {1,1,1,3,3,3,20,4,4,4};
int ones = 0 ;
int twos = 0 ;
int not_threes;
int x ;
for( i=0; i< 10; i++ )
{
x = B[i];
twos |= ones & x ;
ones ^= x ;
not_threes = ~(ones & twos) ;
ones &= not_threes ;
twos &= not_threes ;
}
printf("\n unique element = %d \n", ones );
return 0;
}
The code works in similar line with the question of "finding the element which appears once in an array - containing other elements each appearing twice". Solution is to XOR all the elements and you get the answer.
Basically, it makes use of the fact that x^x = 0. So all paired elements get XOR'd and vanish leaving the lonely element.
Since XOR operation is associative, commutative.. it does not matter in what fashion elements appear in array, we still get the answer.
Now, in the current question - if we apply the above idea, it will not work because - we got to have every unique element appearing even number of times. So instead of getting the answer, we will end up getting XOR of all unique elements which is not what we want.
To rectify this mistake, the code makes use of 2 variables.
ones - At any point of time, this variable holds XOR of all the elements which have
appeared "only" once.
twos - At any point of time, this variable holds XOR of all the elements which have
appeared "only" twice.
So if at any point time,
1. A new number appears - It gets XOR'd to the variable "ones".
2. A number gets repeated(appears twice) - It is removed from "ones" and XOR'd to the
variable "twice".
3. A number appears for the third time - It gets removed from both "ones" and "twice".
The final answer we want is the value present in "ones" - coz, it holds the unique element.
So if we explain how steps 1 to 3 happens in the code, we are done.
Before explaining above 3 steps, lets look at last three lines of the code,
not_threes = ~(ones & twos)
ones & = not_threes
twos & = not_threes
All it does is, common 1's between "ones" and "twos" are converted to zero.
For simplicity, in all the below explanations - consider we have got only 4 elements in the array (one unique element and 3 repeated elements - in any order).
Explanation for step 1
------------------------
Lets say a new element(x) appears.
CURRENT SITUATION - Both variables - "ones" and "twos" has not recorded "x".
Observe the statement "twos| = ones & x".
Since bit representation of "x" is not present in "ones", AND condition yields nothing. So "twos" does not get bit representation of "x".
But, in next step "ones ^= x" - "ones" ends up adding bits of "x". Thus new element gets recorded in "ones" but not in "twos".
The last 3 lines of code as explained already, converts common 1's b/w "ones" and "twos" to zeros.
Since as of now, only "ones" has "x" and not "twos" - last 3 lines does nothing.
Explanation for step 2.
------------------------
Lets say an element(x) appears twice.
CURRENT SITUATION - "ones" has recorded "x" but not "twos".
Now due to the statement, "twos| = ones & x" - "twos" ends up getting bits of x.
But due to the statement, "ones ^ = x" - "ones" removes "x" from its binary representation.
Again, last 3 lines of code does nothing.
So ultimately, "twos" ends up getting bits of "x" and "ones" ends up losing bits of "x".
Explanation for step 3.
-------------------------
Lets say an element(x) appears for the third time.
CURRENT SITUATION - "ones" does not have bit representation of "x" but "twos" has.
Though "ones & x" does not yield nothing .. "twos" by itself has bit representation of "x". So after this statement, "two" has bit representation of "x".
Due to "ones^=x", after this step, "one" also ends up getting bit representation of "x".
Now last 3 lines of code removes common 1's of "ones" and "twos" - which is the bit representation of "x".
Thus both "ones" and "twos" ends up losing bit representation of "x".
1st example
------------
2, 2, 2, 4
After first iteration,
ones = 2, twos = 0
After second iteration,
ones = 0, twos = 2
After third iteration,
ones = 0, twos = 0
After fourth iteration,
ones = 4, twos = 0
2nd example
------------
4, 2, 2, 2
After first iteration,
ones = 4, twos = 0
After second iteration,
ones = 6, twos = 0
After third iteration,
ones = 4, twos = 2
After fourth iteration,
ones = 4, twos = 0
Explanation becomes much more complicated when there are more elements in the array in mixed up fashion. But again due to associativity of XOR operation - We actually end up getting answer.

puzzle using arrays

My first array M + N size and second array of size N.
let us say m=4,n=5
a[ ]= 1,3,5,7,0,0,0,0,0
b[ ]= 2,4,6,8,10
Now , how can i merge these two arrays without using external sorting algorithms and any other temporary array(inplace merge) but complexity should be o(n).Resultant array must be in sorted order.
Provided a is exactly the right size and arrays are already sorted (as seems to be the case), the following pseudo-code should help:
# 0 1 2 3 4 5 6 7 8
a = [1,3,5,7,0,0,0,0,0]
b = [2,4,6,8,10]
afrom = 3
bfrom = 4
ato = 8
while bfrom >= 0:
if afrom == -1:
a[ato] = b[bfrom]
ato = ato - 1
bfrom = bfrom - 1
else:
if b[bfrom] > a[afrom]:
a[ato] = b[bfrom]
ato = ato - 1
bfrom = bfrom - 1
else:
a[ato] = a[afrom]
ato = ato - 1
afrom = afrom - 1
print a
It's basically a merge of the two lists into one, starting at the ends. Once bfrom hits -1, there are no more elements in b so the remainder in a were less than the lowest in b. Therefore the rest of a can remain unchanged.
If a runs out first, then it's a matter of transferring the rest of b since all the a elements have been transferred above ato already.
This is O(n) as requested and would result in something like:
[1, 2, 3, 4, 5, 6, 7, 8, 10]
Understanding that pseudo-code and translating it to your specific language is a job for you, now that you've declared it homework :-)
for (i = 0; i < N; i++) {
a[m+i] = b[i];
}
This will do an in-place merge (concatenation).
If you're asking for an ordered merge, that's not possible in O(N). If it were to be possible, you could use it to sort in O(N). And of course O(N log N) is the best known general-case sorting algorithm...
I've got to ask, though, looking at your last few questions: are you just asking us for homework help? You do know that it's OK to say "this is homework", and nobody will laugh at you, right? We'll even still do our best to help you learn.
Do you want a sorted array ? If not this should do
for(int i=a.length-1,j=0;i >=0; i--)
{
a[i] = b[j++];
}
You can take a look at in-place counting sort that works provided you know the input range. Effectively O(n).

Resources