Related
Given an integer n and array a, I need to find for each i, 1≤ i ≤ n, how many elements on the left are less than or equal to ai
Example:
5
1 2 1 1 2
Output
0 1 1 2 4
I can do it in O(N2) but I want to ask if there is any way to do it faster, since N is very large (N ≤ 106)?
You can use a segment tree, you just need to use a modified version called a range tree.
Range trees allow rectangle queries, so you can make the dimensions be index and value, and ask "What has value more than x, and index between 1 and n?"
Queries can be accomplished in O(log n) assuming certain common optimizations.
Either way O(N^2) is completely fine with N < 10^6.
I like to consider a bigger array to explain, so let's consider following array,
2, 1, 3, 4, 7, 6, 5, 8, 9, 10, 12, 0, 11, 13, 8, 9, 12, 20, 30, 60
The naïve way is to compare an element with all elements at left of it. Naïve approach has complexity of O(n^2) which make it not useful for big array.
If you look this problem closely you will find a pattern in it, and the pattern is Rather than comparing with each left element of an element we can compare first and last value of a range!. Wait a minute what is the range here?
These numbers can be viewed as ranges and there ranges can be created from traversing left to right in array. Ranges are as follows,
[2], [1, 3, 4, 7], [6], [5, 8, 9, 10, 12], [0, 11, 13], [8, 9, 12, 20, 30, 60]
Let’s start traversing array from left to right and see how we can create these ranges and how these ranges shall reduce the effort to find all small or equal elements at left of an element.
Index 0 have no element at its left to compare thus why we start form index 1, at this point we don’t have any range. Now we compare value of index 1 and index 0. Value 1 is not less than or equals to 2, so this is very import comparison, due to this comparison we know the previous range should end here because now numbers are not in acceding order and at this point we get first range [2], which contains only single element and number of elements less than or equals to left of element at index 1 is zero.
As continue with traversing left to right at index 2 we compare it with previous element which is at index 1 now value 1 <= 3 it means a new range is not staring here and we are still in same range which started at index 1. So to find how many elements less than or equals, we have to calculate first how many elements in current range [1, 3), in this case only one element and we have only one know range [2] at this point and it has one element which is less than 3 so total number of less than or equals elements at the left of element at index 2 is = 1 + 1 = 2. This can be done in similar way for rest of elements and I would like to jump directly at index 6 which is number 5,
At index 6, we have all ready discovered three ranges [2], [1, 3, 4, 7], [6] but only two ranges [2] and [1, 3, 4, 7] shall be considered. How I know in advance that range [6] is not useful without comparing will be explained at the end of this explanation. To find number of less than or equals elements at left, we can see first range [2] have only one element and it is less than 5, second range have first element 1 which is less than 5 but last element is 7 and it is greater than 5, so we cannot consider all elements of range rather we have to find upper bound in this range to find how many elements we can consider and upper bound can be found by binary search because range is sorted , so this range contains three elements 1, 3, 4 which are less then or equals to 5. Total number of elements less than or equals to 5 from two ranges is 4 and index 6 is first element of current range and there is no element at left of it in current range so total count = 1 + 3 + 0 = 4.
Last point on this explanation is, we have to store ranges in tree structure with their first value as key and value of the node should be array of pair of first and last index of range. I will use here std::map. This tree structure is required so that we can find all the range having first element less than or equals to our current element in logarithmic time by finding upper bound. That is the reason, I knew in advance when I was comparing element at index 6 that all three ranges known that time are not considerable and only two of them are considerable .
Complexity of solution is,
O(n) to travels from left to right in array, plus
O(n (m + log m)) for finding upper bound in std::map for each element and comparing last value of m ranges, here m is number of ranges know at particular time, plus
O(log q) for finding upper bound in a range if rage last element is greater than number, here q is number of element in particular range (It may or may not requires)
#include <iostream>
#include <map>
#include <vector>
#include <iterator>
#include <algorithm>
unsigned lessThanOrEqualCountFromRage(int num, const std::vector<int>& numList,
const std::map<int,
std::vector<std::pair<int, int>>>& rangeMap){
using const_iter = std::map<int, std::vector<std::pair<int, int>>>::const_iterator;
unsigned count = 0;
const_iter upperBoundIt = rangeMap.upper_bound(num);
for(const_iter it = rangeMap.cbegin(); upperBoundIt != it; ++it){
for(const std::pair<int, int>& range : it->second){
if(numList[range.second] <= num){
count += (range.second - range.first) + 1;
}
else{
auto rangeIt = numList.cbegin() + range.first;
count += std::upper_bound(rangeIt, numList.cbegin() +
range.second, num) - rangeIt;
}
}
}
return count;
}
std::vector<unsigned> lessThanOrEqualCount(const std::vector<int>& numList){
std::vector<unsigned> leftCountList;
leftCountList.reserve(numList.size());
leftCountList.push_back(0);
std::map<int, std::vector<std::pair<int, int>>> rangeMap;
std::vector<int>::const_iterator rangeFirstIt = numList.cbegin();
for(std::vector<int>::const_iterator it = rangeFirstIt + 1, endIt = numList.cend();
endIt != it;){
std::vector<int>::const_iterator preIt = rangeFirstIt;
while(endIt != it && *preIt <= *it){
leftCountList.push_back((it - rangeFirstIt) +
lessThanOrEqualCountFromRage(*it,
numList, rangeMap));
++preIt;
++it;
}
if(endIt != it){
int rangeFirstIndex = rangeFirstIt - numList.cbegin();
int rangeLastIndex = preIt - numList.cbegin();
std::map<int, std::vector<std::pair<int, int>>>::iterator rangeEntryIt =
rangeMap.find(*rangeFirstIt);
if(rangeMap.end() != rangeEntryIt){
rangeEntryIt->second.emplace_back(rangeFirstIndex, rangeLastIndex);
}
else{
rangeMap.emplace(*rangeFirstIt, std::vector<std::pair<int, int>>{
{rangeFirstIndex,rangeLastIndex}});
}
leftCountList.push_back(lessThanOrEqualCountFromRage(*it, numList,
rangeMap));
rangeFirstIt = it;
++it;
}
}
return leftCountList;
}
int main(int , char *[]){
std::vector<int> numList{2, 1, 3, 4, 7, 6, 5, 8, 9, 10, 12,
0, 11, 13, 8, 9, 12, 20, 30, 60};
std::vector<unsigned> countList = lessThanOrEqualCount(numList);
std::copy(countList.cbegin(), countList.cend(),
std::ostream_iterator<unsigned>(std::cout, ", "));
std::cout<< '\n';
}
Output:
0, 0, 2, 3, 4, 4, 4, 7, 8, 9, 10, 0, 11, 13, 9, 11, 15, 17, 18, 19,
Yes, It can be done in better time complexity compared to O(N^2) i.e O(NlogN). We can use the Divide and Conquer Algorithm and Tree concept.
want to see the source code of above mentioned two algorithms???
Visit Here .
I think O(N^2) should be the worst case. In this situation, we will have to traverse the array at least two times.
I have tried in O(N^2):
import java.io.*;
import java.lang.*;
public class GFG {
public static void main (String[] args) {
int a[]={1,2,1,1,2};
int i=0;
int count=0;
int b[]=new int[a.length];
for(i=0;i<a.length;i++)
{
for(int c=0;c<i;c++)
{
if(a[i]>=a[c])
{
count++;
}
}
b[i]=count;
count=0;
}
for(int j=0;j<b.length;j++)
System.out.print(b[j]+" ");
}`
I have the following array:
{7, 1, 3, 9, 5, 4, 7, 8, 2}
and a empty n-size array. Now I want to find the index of the n-least values in that given array without sorting and write them to the empty array. For example n = 3:
{1, 8, 2}
Is there an easy way to do that?
If you are not restricted in sorting other arrays, then create an array of indices and sort the array of indices in accordance with the original array.
#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric>
int main()
{
int n = 3;
// test data
std::vector<int> test = { 7, 1, 3, 9, 5, 4, 7, 8, 2 };
// index array
std::vector<int> index(test.size());
// set the index array to 0, 1, 2, … n-1
std::iota(index.begin(), index.end(), 0);
// sort the index array
std::sort(index.begin(), index.end(), [&](int n1, int n2) { return test[n1] < test[n2]; });
// output results -- note we are printing the index array
for (int i = 0; i < n; ++i)
std::cout << index[i] << "\n";
}
Output:
1
8
2
Start with first value in array.
Compare the values from the array and the value of the index in the n-least array. (If empty then just add it).
If the value is less, then shift the array from that position and add the index to that position in the n-least array.
If it's not less then compare the next value from the n-least array and so forth.
This is probably not optimal but atleast it's not of O(n^2) complexity that a naive solution would yield.
I'll write this in pseudo code:
n = 3
arr = [7, 1, 3, 9, 5, 4, 7, 8, 2]
narr = []
for i as 0 to sizeof(arr) - 1
for j as 0 to n - 1
if narr[j] is undefined or arr[i] < arr[narr[j]]
narr.shiftRight(j, 1)
narr[j] = i;
break
endif
endfor
endfor
I have an vector<int> number_vector that contains {1, 0, 0, 0, 0, 0 ,0}. I need to iterate over this number_vector, e.g 4 times, and remove the first smallest number at each iteration, i.e at the first iteration I will remove the value 0 at the index 1, at the next iteration I will remove the 0 that is at the index 1, etc. I'm doing this right now the following way:
int n = 7;
int d = 4;
vector<int> number_vector{1, 0, 0, 0, 0, 0 ,0};
for (int counter = 0; counter < n - d; counter++)
{
int index = distance(number_vector.begin(), min_element(number_vector.begin(), number_vector.end()));
if (index != number_vector.size() - 1)
{
number_vector[index] = move(number_vector.back());
}
number_vector.pop_back();
// number_vector.erase(number_vector.begin() + index);
}
The problem it's that if I run the code above, at the end number_vector has {1, 0, 0, 0} while it should have {1, 0, 0}, and for other cases like n = 4, d = 2 and number_vector{3, 7, 5, 9}, the final number_vector has the right value, that is 79. Some tips?
First of all you're iterating three times, not four. Secondly, if the vector isn't required, you can just use a map and pop the front iterator since it will always be the lowest value. Finally, there is no need for a swap or distance, just erase the result of min_element if it's not invalid.
When you iterate from 0 to n-d, with n=7 and d=4. you will iterate from counter=0 to counter < 7-4, i.e., 3. So your loop will iterate 3 times with values 0, 1 and 2. This will remove three zeros from number_vector. So your code is behaving as expected.
I think what you want is to iterate from 0 to d. Also you are unnecessarily complicating the code by using index. You can use the iterator directly like below.
for (int counter = 0; counter < d; counter++)
{
*min_element(number_vector.begin(), number_vector.end()) = *number_vector.rbegin();
number_vector.pop_back();
}
Is your d represents the times of pop minimum number from vector?
Then modify counter < n - d to counter < d, it will have {1, 0, 0}
11.04
if you want to keep the order,you can modify
for (int counter = 0; counter < d; ++counter)
{
auto iter = min_element(number_vector.begin(), number_vector.end());
number_vector.erase(iter);
}
PS:std::list maybe a better choice?
Consider an array. What is a good way to permute its elements according to another array that gives the new positions of elements (without making a copy of the array first)?
For example
int a[]={37,43,5,10}; //array to permute
int b[]={3,1,4,2}; //new position of each element
so a should become
{43,10,37,5}
I naturally thought about making a copy of a and then re allocate its element in the new positions. But is there a way to do it without making a copy of the array a (i.e. a more simple way)?
Note: If possible the way to do it should not use particular C++ headers but only <iostream>
It can be done in O(n) time with O(1) extra memory, by handling the cycles of the permutation array one at a time.
Note: this approach is more complicated than needed for this particular setting (a and b are both int arrays), but it has some benefits:
it can handle arbitrary datatypes (e.g. the permuted array a can be an array of strings).
it can retain the original values in b, the permutation array.
Consider the initial example:
int a[] = {37, 43, 5, 10}; // array to permute
int b[] = { 3, 1, 4, 2}; // new position of each element
The array b indicates that we want to make the following chain of assignments:
a[1] <-- a[3] <-- a[4] <-- a[2] <-- a[1].
The problem is that at the last assignment, we don't anymore have access to a[1] (it has already been replaced to a[3]).
However, the original value of the starting element can be saved in an auxiliary variable, so that we use it when we close the cycle (it is guaranteed that when we close the cycle we will reach precisely the element that we have started from - otherwise some element would be reachable in multiple ways, i.e. we would have b[i] = b[j]), for some i != j).
In general, the permutation may contain multiple cycles. After a cycle is processed, we need to start with an element that had not yet been updated (i.e. it was not part of a cycle processed so far).
Thus, we need to know which elements were not processed so far.
A possible approach is to temporarily modify the permutation vector b in order to keep track of which elements were updated, e.g. negating the value at the corresponding position in b when updating an element in a. This has the advantage that at the end, we can iterate through all elements of b and restore the initial values (by negating all of them again).
Below is an implementation of the previous ideas.
int main() {
int a[] = {11, 22, 33, 44};
int b[] = { 2, 1, 4, 3};
int aux, crtIdx, nxtIdx;
int n = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < n; i++) {
// check whether the i'th element
// was already processed
if (b[i] < 0) {
continue;
}
// start processing of a new cycle;
// backup the first value to aux
aux = a[i];
crtIdx = i;
nxtIdx = b[i] - 1;
// advance along the cycle until we reach
// again the first element
while (nxtIdx != i) {
a[crtIdx] = a[nxtIdx];
// use the b array to mark that the
// element at crtIdx was updated
b[crtIdx] = -b[crtIdx];
crtIdx = nxtIdx;
nxtIdx = b[nxtIdx] - 1;
}
// finalize the cycle using the aux variable
a[crtIdx] = aux;
b[crtIdx] = -b[crtIdx];
}
// restore the original values of b[i]
for (int i = 0; i < n; i++) {
b[i] = -b[i];
}
}
Note: although the code contains two nested loops, the time complexity is O(n). This can be seen by considering the fact that each element is updated exactly once (the outer loop is immediately continued if we reach an element that was already processed).
I'll show here the main steps performed by the algorithm, using this example:
a = {11, 22, 33, 44}
b = { 2, 1, 4, 3}
Step 1.
We look at the first element (please see the outer for loop over i from the code). The first element is not part of an already processed cycle, thus we start the processing of a new cycle. We do so by storing in aux the initial value of this element.
a = {11, 22, 33, 44}
b = { 2, 1, 4, 3}
aux = 11
Step 2.
We go along this cycle, update elements, mark them as updated (by negating the corresponding element in the b array), until we reach again the first element.
a = {22, 22, 33, 44}
b = {-2, 1, 4, 3}
aux = 11
Step 3.
We reached again the first element of the cycle, and need its initial value in order to update the last element of the cycle. This is where we use the auxiliary variable. In this way, the first cycle is completely processed.
a = {22, 11, 33, 44}
b = {-2, -1, 4, 3}
aux = 11
Step 4.
We continue the outer loop (the for over i). We see that the second element was already processed (because b[1] is negative), thus we don't start a new cycle here. We continue, and start a new cycle at the third element (which was not yet processed).
Now we can reuse the same aux variable to backup the first element of this cycle (we no longer need to hold the value from the first cycle, because that cycle was completely resolved).
a = {22, 11, 33, 44}
b = {-2, -1, 4, 3}
aux = 33
Step 5.
The processing of the second cycle is performed in a similar manner described in the previous steps, resulting in the end in this:
a = {22, 11, 44, 33}
b = {-2, -1, -4, -3}
aux = 33
Step 6.
The loop over i continues, and no un-processed element is found.
Now, that we know that all elements were processed, we can negate each element in b in order to restore the original values.
a = {22, 11, 44, 33}
b = { 2, 1, 4, 3}
The simplest answer is to copy a into b, destroying b as you go:
for (i = 0; i < B_SIZE; ++i):
b[i] = a[b[i] - 1];
Then, if you must, just copy b back to a:
for (i = 0; i < B_SIZE; ++i):
a[i] = b[i];
Since a and b are both int arrays, you're not using up any excess memory in doing so. You end with the correct values in a, without using any more memory than what was given to you. This isn't maximally efficient (though it is O(n)), but it is simplest to understand.
When you want to avoid copying an array, it generally means limiting yourself to swaps.
If we use swaps to sort b[], and use the same swaps for a[], then a[] will end up permuted according to the values of b[].
I'm going to step through the algorithm below. For simplicity, I start array counting at 1, although in C arrays count starting at 0. You'll have to adjust for that in your code.
a[]={37, 43, 5, 10} //array to permute
b[]={3, 1, 4, 2} //new position of each element
i = 1; b[i] = 3
swap(a[1], a[3]); a[] = {5, 43, 37, 10}
swap(b[1], b[3]); b[] = {4, 1, 3, 2}
i = 1; b[i] = 4
swap(a[1], a[4]); a[] = {10, 43, 37, 5}
swap(b[1], b[4]); b[] = {2, 1, 3, 4}
i = 1; b[i] = 2
swap(a[1], a[2]); a[] = {43, 10, 37, 5}
swap(b[1], b[2]); b[] = {1, 2, 3, 4}
i = 1; b[i] = 1
++i
i = 2; b[i] = 2
++i
i = 3; b[i] = 3
++i
i = 4; b[i] = 4
++i
i = 5; i > 4
DONE
Note how we step through b[] at the end there. Consider the case that b[]={2, 1, 4, 3}
a[] = {37, 43, 5, 10}
b[] = {2, 1, 4, 3}
i = 1; b[i] = 2
swap(a[1], a[2]); a[] = {43, 37, 5, 10}
swap(b[1], b[2]); b[] = {1, 2, 4, 3}
i = 1; b[i] = 1
++i
i = 2; b[i] = 2
++i
i = 3; b[i] = 4
swap(a[3], a[4]); a[] = {43, 37, 10, 5}
swap(b[3], b[4]); b[] = {1, 2, 3, 4}
i = 3; b[i] = 3
++i
i = 4; b[i] = 4
++i
i = 5; i > 4
DONE
With every swap, one element of the array ends up in the correct position, meaning we perform at most N swaps.
I want to fill a vector with random integers but there can't be duplicates in it.
First off, I have this code to put numberOfSlots random integers between 0 and 7 in the vector (numberOfSlots can be 2 to 20):
srand((unsigned int)time(NULL));
unsigned int min = 0;
unsigned int max = 7;
std::vector<unsigned int> v;
for (int i = 0; i < numberOfSlots; i++) {
unsigned int rdm = std::rand() % (max - min + 1) + min;
v.push_back(rdm);
}
This is the code for when duplicate integers are allowed. This is working fine!
Now I want to the change that code so that from the same random pool of possible integers (min to max) the generated random integer is only added if it's not already in the vector.
So if for example numberOfSlots is 5, then the vector will have 5 entries that were randomly chosen from the pool but are not the same, e.g. 7, 1, 3, 5, 0. If numberOfSlots is 8, the vector will be for example 3, 1, 2, 7, 6, 0, 4, 5.
I know how to shuffle the vector and stuff but I am not able to get this working. I think I have to use a while loop and check all already existing integers in the vector against the new random to be added number and if it's already in there generate a new random number and check again, etc. but I don't know
I am a beginner and this is really hard. Can someone maybe give me a hint? I would appreciate it... thank you so much
You can populate your vector with values 0..N-1 (or your pool values), and thereafter shuffle it. See example:
// Initialize
for(i = 0; i < N; i++)
arr[i] = i;
// shuffle
for(i = N - 1; i > 0; i--) {
j = rand() % i;
swap(arr[i], arr[j]);
}
I think your best bet is to create a vector to store the unrandomized integers, then another vector to store a randomized subset.
randomly chooose a number from your unrandomized integer vector, add that number to the randomized subset vector, then remove it from your unrandomized integer vector.
Now your unrandomized integer vector is one smaller, so randomly choose a number on the new smaller vector, add it to the randomized subset vector, and remove it from the unrandomized vector. Repeat.
Here's what it might look like
Unrandomized
{0, 1, 2, 3, 4, 5, 6, 7}
Randomized
{}
Choose random index: 5
Yields =>
Unrandomized
{0, 1, 2, 3, 5, 6, 7} //Removed 4 because it was at index #5
Randomized
{5}
Choose Random Index: 0
Yields =>
Unrandomized
{1, 2, 3, 5, 6, 7}
Randomized
{5, 0}
Choose Random Index: 6
Yields=>
Unrandommized
{1, 2, 3, 5, 6} // 7 removed at index #6
Randomized
{5, 0, 7}
And say you only have to pick do 3 random values here so you end up with 5, 0, 7. This method ensures no duplicates. I think there is an easier way using an inline function but I don't know it and the above should suffice.