In C++ is there any way to apply a function 'simultaneously' to all the elements of a vector ? - c++

I have a vector of length 6, with elements either 1 or zero. I want to apply 'XOR' on 2 elements on both sides of every ith element. e.g. for i = 1, I'll apply xor on 0th and 2nd element. the ith element is then replaced by this xor output. I want to apply xor for all such 'i's simultaneously on the original vector. Is there any way I can achieve this without using another vector?

When you say "simultaneously", you mean that one XOR operation should not use the intermediate data from the previous XOR operation but the data from the original vector, right? In that case, since each step obliterates information (the previous state of element i is overwritten with the result), you can not do that without at least some intermediate storage. However, you only obliterate one bit of information and that information is only required in the next step, so you don't need a complete additional vector.

use a temporary variable to store previous item:
bool prev = vec[0];
for(int i = 1; i < vec.size() - 1; i++){
bool result = vec[i + 1] ^ prev;
prev = vec[i];
vec[i] = result;
}

Related

Intuition behind incrementing the iteration variable?

I am solving a question on LeetCode.com:
Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue. Here, they use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. [The trivial counting sort cannot be used].
For the input: [2,0,2,1,1,0]; the output expected is: [0,0,1,1,2,2].
One of the highly upvoted solutions goes like this:
public void sortColors(vector<int>& A) {
if(A.empty() || A.size()<2) return;
int low = 0;
int high = A.size()-1;
for(int i = low; i<=high;) {
if(A[i]==0) {
// swap A[i] and A[low] and i,low both ++
int temp = A[i];
A[i] = A[low];
A[low]=temp;
i++;low++;
}else if(A[i]==2) {
//swap A[i] and A[high] and high--;
int temp = A[i];
A[i] = A[high];
A[high]=temp;
high--;
}else {
i++;
}
}
}
My question is, why is i incremented when A[i]==0 and A[i]==1 and not when A[i]==2? Using pen and paper, the algorithm just works to give me the answer; but could you please provide some intuition?
Thanks!
This steps through the array and maintains the constraint that the elements 0..i are sorted, and all either 0 or 1. (The 2's that were there get swapped to the end of the array.)
When A[i]==0, you're swapping the element at i (which we just said was 0) with the element at low, which is the first 1-element (if any) in the range 0..i. Hence, after the swap, A[i]==1 which is OK (the constraint is still valid). We can safely move forward in the array now. The same is true if A[i]==1 originally, in which case no swap is performed.
When A[i]==2, you're essentially moving element i (which we just said was 2) to the end of the array. But you're also moving something from the end of the array into element i's place, and we don't know what that element is (because we haven't processed it before, unlike the A[i]==0 case). Hence, we cannot safely move i forward, because the new element at A[i] might not be in the right place yet. We need another iteration to process the new A[i].
That is, because for 0s and 1s, only items left of the current item are handled and those have already been reviewed / sorted. Only for 2s items from the right end of the array are handled, which haven't been looked at yet.
To be more specific: In this specific example only three different states are handled:
the current item being reviewed equals 0: in this case this sorting algorithm just puts this item at the end of all zeros, which have already been sorted (aka A[low]). Also the item which was at A[low] before can only be a 0 or 1 (since they have already sorted) which means you can just swap with the current item and not break the sequence. Now the interesting part: up until now, every item from A[0] over A[low] to A[i] has been already sorted, so the next item which has to be reviewed will be A[i + 1], hence the i++
the current item equals 1: in this case, no swapping has to be done, since all 0s and 1s has already been put in A[0] to A[i - 1] and all 2s have already been put at the end of the array. That means, the next item to be reviewed is A[i + 1], hence the i++
the current item equals 2: in this case, the current item will be put at the end of the array, next to (i.e., to the left of) all the other already sorted 2s (A[high]). The item, which will be swapped from A[high] to A[i] has not been sorted yet and therefor has to be reviewed in the next step, hence th i = i;

Algorithm that sorts a permutation

I am stuck at this problem:
Given a permutation P of {0,1,2,...,n-1}
(Here n = P . length)
Explain why the following algorithm sorts the permutation in increasing order and give a worst case scenario (pseudo-code)
PermutationSort(P)
for i = 0 to P.length - 1
while(P[i] != i)
t = P[i]
exchange P[i] with P[t]
(C++ code)
void PermutationSort(int P[], int len)
{
for(int i = 0; i < len; i++)
while(P[i] != i)
{
int tmp;
tmp = P[i];
P[i] = P[tmp];
P[tmp] = tmp;
}
}
I am totally don't know why it sorts the permutation P.
I've sat on this problem all day and I'm still don't get why it sorts the permutation.
what "exchange P[i] with P[P[i]]" does and why we will ultimately get P[i] = i which will then terminate the inner loop?
Thanks for any hint or help.
First, note that, if you start at any arbitrary element k, and repeatedly apply the permutation P to obtain a chain like (k → P(k) → P(P(k)) → P(P(P(k))) → ...), you will (since the total number of elements in the permutation P is finite, and a permutation never maps two inputs to the same output) eventually end up back at k. The cycle of elements (k →P(k) → P(P(k)) → ... → k) is called the orbit of k under P, and every element of the permutation belongs to exactly one such cycle.
Now, let's see what the inner loop of your algorithm does to the cycle containing the element i.
If P(i ) = i, i.e. if this element is already where it belongs, then the inner loop just does nothing and the outer loop moves on to the next element. If P(i ) ≠ i, however, the inner loop sets t = P(i ), and then modifies the permutation P to swap P(i ) and P(t ).
After the swap, the new value of P(t ) is the old value of P(i ), i.e. t. Thus, the element t is now correctly sorted, while P(i ) now contains the old value of P(t ) = P(P(i )), i.e. the (former) next element in the cycle. If this is i, then there are no more elements left in the cycle, and the inner loop ends; otherwise, the cycle containing i has shrunk by one element, and the inner loop repeats.
Thus, at the end of the inner loop, all the elements that used to be part of the same cycle as i (including i itself) have been moved to their correct locations, and thus removed from the cycle, while the rest of the permutation has not been changed.
Since the outer loop iterates over every element in the permutation, it is also guaranteed to visit every cycle at least once. Of course, we're modifying the permutation in the inner loop, but that's all right, since the inner loop can never create new cycles (of more than one element); it can only break up existing ones.
Thus, the first time each cycle in the original permutation gets visited by the outer loop, the inner loop sorts and breaks up that cycle; on subsequent visits to the same original cycle, that cycle has already been sorted, and so the inner loop simply does nothing.
This observation should also allow you to bound the number of times the inner loop can be executed, and thus to determine the time complexity of the algorithm.

why removing the first element in ArrayList is slow?

some where I've read that removing the first elementarrayList.remove(0); is slower than removing the last one arrayList.remove(arrayList.size()-1); please some one provide the detailed explanation. Thanks in advance
In ArrayList the elements reside in contiguous memory locations.
So when you remove the first element, all elements from 2 to n have to be shifted.
E.g. If you remove 1 from [1,2,3,4], 2, 3 and 4 have to be shifted to left to maintain contiguous memory allocation.
This makes it a little slower.
On the other hand, if you remove the last element, there is no shifting required since all the remaining elements are in the proper place.
Implementation of remove:
public E More ...remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
The values are stored in an array, so if the last one is removed it only set the value in the array to null (elementData[--size] = null). But if it is somewhere else it needs to use arraycopy to move all the elements after it. So in the code above you can see clearly: index = size - 1 implies the arraycopy call (the extra time used).

Find the element with the longest distance in a given array where each element appears twice?

Given an array of int, each int appears exactly TWICE in the
array. find and return the int such that this pair of int has the max
distance between each other in this array.
e.g. [2, 1, 1, 3, 2, 3]
2: d = 5-1 = 4;
1: d = 3-2 = 1;
3: d = 6-4 = 2;
return 2
My ideas:
Use hashmap, key is the a[i], and value is the index. Scan the a[], put each number into hash. If a number is hit twice, use its index minus the old numbers index and use the result to update the element value in hash.
After that, scan hash and return the key with largest element (distance).
it is O(n) in time and space.
How to do it in O(n) time and O(1) space ?
You would like to have the maximal distance, so I assume the number you search a more likely to be at the start and the end. This is why I would loop over the array from start and end at the same time.
[2, 1, 1, 3, 2, 3]
Check if 2 == 3?
Store a map of numbers and position: [2 => 1, 3 => 6]
Check if 1 or 2 is in [2 => 1, 3 => 6] ?
I know, that is not even pseudo code and not complete but just to give out the idea.
Set iLeft index to the first element, iRight index to the second element.
Increment iRight index until you find a copy of the left item or meet the end of the array. In the first case - remember distance.
Increment iLeft. Start searching from new iRight.
Start value of iRight will never be decreased.
Delphi code:
iLeft := 0;
iRight := 1;
while iRight < Len do begin //Len = array size
while (iRight < Len) and (A[iRight] <> A[iLeft]) do
Inc(iRight); //iRight++
if iRight < Len then begin
BestNumber := A[iLeft];
MaxDistance := iRight - iLeft;
end;
Inc(iLeft); //iLeft++
iRight := iLeft + MaxDistance;
end;
This algorithm is O(1) space (with some cheating), O(n) time (average), needs the source array to be non-const and destroys it at the end. Also it limits possible values in the array (three bits of each value should be reserved for the algorithm).
Half of the answer is already in the question. Use hashmap. If a number is hit twice, use index difference, update the best so far result and remove this number from the hashmap to free space . To make it O(1) space, just reuse the source array. Convert the array to hashmap in-place.
Before turning an array element to the hashmap cell, remember its value and position. After this it may be safely overwritten. Then use this value to calculate a new position in the hashmap and overwrite it. Elements are shuffled this way until an empty cell is found. To continue, select any element, that is not already reordered. When everything is reordered, every int pair is definitely hit twice, here we have an empty hashmap and an updated best result value.
One reserved bit is used while converting array elements to the hashmap cells. At the beginning it is cleared. When a value is reordered to the hashmap cell, this bit is set. If this bit is not set for overwritten element, this element is just taken to be processed next. If this bit is set for element to be overwritten, there is a conflict here, pick first unused element (with this bit not set) and overwrite it instead.
2 more reserved bits are used to chain conflicting values. They encode positions where the chain is started/ended/continued. (It may be possible to optimize this algorithm so that only 2 reserved bits are needed...)
A hashmap cell should contain these 3 reserved bits, original value index, and some information to uniquely identify this element. To make this possible, a hash function should be reversible so that part of the value may be restored given its position in the table. In simplest case, hash function is just ceil(log(n)) least significant bits. Value in the table consists of 3 fields:
3 reserved bits
32 - 3 - (ceil(log(n))) high-order bits from the original value
ceil(log(n)) bits for element's position in the original array
Time complexity is O(n) only on average; worst case complexity is O(n^2).
Other variant of this algorithm is to transform the array to hashmap sequentially: on each step m having 2^m first elements of the array converted to hashmap. Some constant-sized array may be interleaved with the hashmap to improve performance when m is low. When m is high, there should be enough int pairs, which are already processed, and do not need space anymore.
There is no way to do this in O(n) time and O(1) space.

Traversing an array to find the second largest element in linear time

Is there a way in linear time by which we can find which is the second largest element of an array ?
Array elements can be positive, negative or zero.
Elements can be repetitive.
No STLs allowed.
Python can be used.
Solution : Sort the array and take the second element but Sorting not allowed
Modification : By definition second largest element will be the one which is numerically smaller. Like if we have
Arr = {5,5,4,3,1}
Then second largest is 4
Addition
Lets say if i want to generalize the question to kth largest and complexity less than linear like nlogn, what can be the solution.
Go through the array, keeping 2 memory slots to record the 2 largest elements seen so far. Return the smaller of the two.
.... is there anything tricky about this question that I can't see?
You can, this is the pseudo algorithm:
max = 2max = SMALLEST_INT_VALUE;
for element in v:
if element > max:
2max = max;
max = element;
else if element > 2max:
2max = element;
2max is the value you are looking for.
The algorithm won't return a correct value for particular cases, such as an array where its elements are equal.
If you want a true O(n) algorithm, and want to find nth largest element in array then you should use quickselect (it's basically quicksort where you throw out the partition that you're not interested in), and the below is a great writeup, with the runtime analysis:
http://pine.cs.yale.edu/pinewiki/QuickSelect
Pseudo code:
int max[2] = { array[0], array[1] }
if(max[1] < max[0]) swap them
for (int i = 2; i < array.length(); i++) {
if(array[i] >= max[0]) max[1] = max[0]; max[0] = array[i]
else if(array[i] >= max[1]) max[1] = array[i];
}
Now, max array contains the max 2 elements.
create a temporary array of size 3,
copy first 3 elements there,
sort the temporary array,
replace the last one in the temporary array with the 4th element from the source array,
sort the temporary array,
replace the last one in the temporary array with the 5th element from the source array,
sort the temporary array,
etc.
Sorting array of size 3 is constant time and you do that once for each element of the source array, hence linear overall time.
Yep. You tagged this as C/C++ but you mentioned you could do it in Python. Anyway, here is the algorithm:
Create the array (obviously).
If the first item is greater than the second item, set first variable to the first item and second variable to second item. Otherwise, do vise-versa.
Loop through all the items (except the first two).
If the item from the array is greater than first variable, set second variable to first variable and first variable to the item. Else if the item is greater than second variable set second variable to the item.
The second variable is your answer.
list = [-1,6,9,2,0,2,8,10,8,-10]
if list[0] > list[1]:
first = list[0]
second = list[1]
else:
first = list[1]
second = list[0]
for i in range(2, len(list)):
if list[i] > first:
first, second = list[i], first
elif list[i] > second:
second = list[i]
print("First:", first)
print("Second:", second)
// assuming that v is the array and length is its length
int m1 = max(v[0], v[1]), m2 = min(v[0], v[1]);
for (int i=2; i<length; i++) {
if (likely(m2 >= v[i]))
continue;
if (unlikely(m1 < v[i]))
m2 = m1, m1 = v[i];
else
m2 = v[i];
}
The result you need is in m2 (likely and unlikely are macros defined as here for performance purposes, you can simply remove them if you don't need them).
I think the other answers have not accounted for the fact that in an array like [0, 1, 1], the second largest is 0 (according to the updated problem definition). Furthermore, all mentions of quickselect are not O(n) but rather O(n^2) and are doing much more work than necessary (on top of which that is a sorting algorithm which the problem statement disallowed). Here is a very similar algorithm to Simone's but updated to return the second largest unique element:
def find_second(numbers):
top = numbers[0]
second = None
for num in numbers[1:]:
if second is None:
if num < top: second = num
elif num > top:
second = top
top = num
else:
if num > second:
if num > top:
second = top
top = num
elif num < top: second = num
if second is not None: return second
return top
if __name__ == '__main__':
print "The second largest is %d" % find_second([1,2,3,4,4,5,5])
// Second larger element and its position(s)
int[] tab = { 12, 1, 21, 12, 8, 8, 1 };
int[] tmp = Arrays.copyOf(tab, tab.length);
int secMax = 0;
Arrays.sort(tmp);
secMax = tmp[tmp.length - 2];
System.out.println(secMax);
List<Integer> positions = new ArrayList<>();
for (int i = 0; i < tab.length; i++) {
if (tab[i] == secMax) {
positions.add(i);
}
}
System.out.println(positions);