I have a task which requires me to find the smallest of all bigger elements in an array for all array entries and store the respective indexes in an array and I can't quite figure out the last part of the solution.
This is kind of similar to the problem explained here: https://www.geeksforgeeks.org/smallest-greater-elements-in-whole-array/
The only difference is that only the values right of the array entry are accounted for (j>i), e.g.:
input: [80; 19; 49; 45; 65; 71; 76; 28; 68; 66]
output: [-1; 7; 4; 4; 9; 6; -1; 9; -1; -1]
The solution with a self balancing tree makes sense to me. However, I still need to account for the indexing because only the solutions right of the array entry are valid.
Is there a way to map the indexing of the inserted values to the tree entries or to create a second tree with an identical structure but the index of the old array entries instead of the actual values as nodes? I am not sure because the structure of the self-balancing tree of course depends on the values inserted (bigger values right subtree, smaller values left subtree).
EDIT: Actually a second AVL tree propably won't help as I have to check that indexing is bigger AND array entry is bigger while traversing the tree...
The simplest solution is to iterate over the input from right to left, and for each element look up the first greater element in a tree (or any data structure with O(LogN) look-up and insertion), and then add the element to the tree. That way the greater element always comes after the element in the input.
For a C++ version, you can use a std::map
where the element's value is the key and the element's index in the input is the value, and use upper_bound
to get the next greater value:
#include <iostream>
#include <vector>
#include <map>
void nextValues(std::vector<int> &in, std::vector<int> &out) {
std::map<int, int> tree;
for (int i = in.size() - 1; i >= 0; i--) {
out.insert(out.begin(), tree.upper_bound(in[i])->second - 1);
tree.insert(std::pair<int, int>(in[i], i + 1));
}
}
int main() {
std::vector<int> a = {80,19,49,45,65,71,76,28,68,66};
std::vector<int> b;
nextValues(a, b);
for (int i : b) std::cout << (int) i << ","; // -1,7,4,4,9,6,-1,9,-1,-1
return 0;
}