Assuming an array where every element is also a positive integer number, without duplicates and without any missing elements, like the following:
{15, 1, 2, 6, 7, 8, 3, 4, 9, 5, 10, 13, 11, 12, 14}
Considering the removal and insertion (and not swaping) of each element, how can I find the most efficient move (remove/insert) operations to sort the list with the minimum number of insertions.
I think identifying individual groups is helpful since I can more easily find what needs to be moved together:
{{15}, {1, 2}, {6, 7, 8}, {3, 4}, {9}, {5}, {10}, {13}, {11, 12}, {14}}
For that I can create another array with the difference between the value and the correct position to let me easily identify the groups and which ones are furthest from being correct.
{{14}, {-1, -1}, {2, 2, 2}, {-4, -4}, {0}, {-5}, {-1}, {1}, {-2, -2}, {-1}}
Then I choosed the group furthest from being in the correct position (largest difference) and with smaller number of elements. So based on that I can see that {15} is 14 away from being correct and should be the first to be moved. I THINK (I'm guessing here) that I need to move AT least the difference in value, because I can land in the middle of group. Repeating the procedure I move the {5} to before {6,7,8}, which is moved 6 spaces, more difference between value and correct position because there is a group in its correct spot. Then {3,4}, and finally {13} and the list is sorted.
I can already create a iterative method that does just that. But I think it would be highly inefficient, since I will be dealing with about 200k values and recalculating it after every set of insertions is a terrible idea.
PS: I NEED to follow this procedure (remove and insertion of elements, and thinking in groups) instead of other more time efficient methods, since this would be applied in the real world to sort items in shelves, and something with a smaller number of operations of less items is prefered rather than computational or memory requirements.
Minimizing the number of elements that are moved is the same as maximizing the number of elements that are not moved.
Since any elements you don't move will be left in their original order, those elements must be a subsequence of the desired sorted array. You can use the common algorithm to find the longest such subsequence:
https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/
Then remove all the elements that are not part of this subsequence, and reinsert them wherever they belong.
Note that there are optimizations you can use for this specific case of the longest monotonically increasing subsequence:
https://en.wikipedia.org/wiki/Longest_increasing_subsequence
https://www.geeksforgeeks.org/longest-increasing-subsequence-dp-3/
Create an integer array of size 16. Call it fred.
Init all of the values to 0
Iterate your unsorted array.
use each value as a subscript into fred, setting the value to 1.
Pretend your unsorted array is empty.
Iterate fred.
when you encounter a value of 1, that subscript needs to be inserted
back into your unsorted array.
Your unsorted array of size N is now sorted at a cost of N insertions
Related
I have an array that contains N elements, which values are in 0 <= value < N range and can be discontinuous. For this array I need to find a slice which will contain all unique values and at the same time it will be the shortest slice that will meet the above criterion.
An example, for array {1, 2, 1, 2, 1, 4, 3, 4, 8, 1, 8} with 5 unique values {1, 2, 3, 4, 8} we are talking about slice {2, 1, 4, 3, 4, 8} with length 6.
Is there an optimal way to do this? As for now I've naive implementation that has far too high complexity (nested loops). I've tried to come up with an idea for an algorithm to do this in an optimal way but sadly to no avail. As for now I've tried to come up with something that will make use of occurrences for each unique value when looping through array, but still my mind is not clear enough. Any ideas are welcome, this problem is troubling me for a long time. :) Thank you in advance.
Best regards
The first run collects possible values and creates a map with pairs (value; counter = 0). Let Nis map size
For the second run prepare two indexes - left and right, and ActiveCnt.
Move right, updating map counters. When you update zero counter, increment ActiveCnt. When ActiveCnt becomes equal to N, stop.
Now move left, decrementing map counters. When some counter becomes zero, get difference between right and left, compare it with current MinLength, then decrement ActiveCnt. Continue with right index and so on.
In the work I'm doing, I declare an array with some length N.
At some point during my code, the data between certain elements needs to be removed.
If my initial array is [1,2,3,4,5], I want to change it to [1,2,4,5]. But I don't just do it once. The process will involved removing each element until there are no elements left and I may take out more than one element at once. The reason why I do this is related a complicated process I'm trying to reproduce and I don't think its necessary to go into this right now.
What I want to be able to do is define an array
a = (/ 1, 2, 3, 4, 5 /)
and if I decided to remove elements 3 and 4 I could set up a pointer (call it p) such that it would point to a as:
p = (/ 1, 2, 5 /)
Specifically, p will have length that is equal to a minus the number of elements removed. I'd want to do this morn than once. Redefine a
a = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /)
First I remove elements 4 and 5 and point to it such that
p = (/ 1, 2, 3, 6, 7, 8, 9, 10 /)
And then later removed 7,8,9 I could point to a
p = (/ 1, 2, 3, 6, 10 /)
Meanwhile keeping a intact. The p above would in my head be created by pointing to the first three elements of a and then the 6th and then the 10th all at once in one compact pointer.
I know I can probably achieve the same results with allocatable arrays, but I see pointers as being extremely useful.
No. An array pointer can be associated any array section, but not arbitrary elements.
Depending on what you later want to do, you can have a second array that lists the current indices in a, and then use vector subscripting for certain operations. But there are limitations for where a vector subscripted array can be used (e.g. if associated with a dummy argument it cannot be redefined), and in some cases the underlying implementation of a vector subscripted array may simply be to create a temporary contiguous copy of the relevant elements anyway.
I usually approach it using an allocatable (data) array, and also another logical array that is a mask for the data array. Then use the mask to keep track of what elements of the array are 'in use' or 'not in use'. When the need arises the active or 'in use' elements can be packed into either a final or intermediate array and if it is intermediate then the logical array reset to the size of the new data array.
And I generally avoid pointers.
PACK https://gcc.gnu.org/onlinedocs/gfortran/PACK.html and SUM(logical array) may be useful here.
It depends on whether the access speed to an arbitrary position in the array is more important than the speed of erasing elements.
If erasing elements is your priority, you should definitely make a linked list structure in which you are able to erase n elements at once.
If, on the other hand, what you need is access speed to the data you should use an array.
I have an array of n pairwise different elements and a number k with 1<=k<=n.
Now I am looking for an algorithm calculating the k numbers with the minimal absolute difference to the median of the number array. I need linear complexity (O(n)).
My approach:
I find the median:
I sort the number
I get the middle element or if the number of elements id even then the average of the two elements in the middle and round.
After that:
I take every number and find the absolute distance from the median. These results I save in a different array
I sort the newly obtained array.
I take the first k elements of the result array and I'm done.
I don't know if my solution is in O(n), also whether I'm right with this idea. Can someone verify that? Can someone show me how to solve it in O(n)?
You can solve your problem like that:
You can find the median in O(n), w.g. using the O(n) nth_element algorithm.
You loop through all elements substutiting each with a pair: <the absolute difference to the median>, <element's value>. Once more you do nth_element with n = k. after applying this algorithm you are guaranteed to have the k smallest elements in absolute difference first in the new array. You take their indices and DONE!
Your algorithm, on the other hand uses sorting, and this makes it O(nlogn).
EDIT: The requested example:
Let the array be [14, 6, 7, 8, 10, 13, 21, 16, 23].
After the step for finding the median it will be reordered to, say: [8, 7, 9, 10, 13, 16, 23, 14, 21], notice that the array is not sorted, but still the median (13) is exactly in the middle.
Now let's do the pair substitution that got you confused: we create a new array of pairs: [<abs(14-13), 14>, <abs(6-13), 6>, <abs(7-13), 7>, <abs(8-13), 8>, <abs(10-13), 10>, <abs(13-13), 13>, <abs(21-13), 21>, <abs(16-13), 16>, <abs(23-13), 23>. Thus we obtain the array: [<1, 14>, <7, 6>, <6, 7>, <5, 8>, <3, 10>, <0, 13>, <8, 21>, <3, 16>, <10, 23>
If e.g. k is 4 we make once more nth_element(using the first element of each pair for comparisons) and obtain: [<1, 14>, <3, 16>, <0, 13>, <3, 10>, <8, 21>, <7, 6>, <10, 23>, <6, 7>, <5, 8>] so the numbers you search for are the second elements of the first 4 pairs: 14, 16, 13 and 10
I am trying to create a "prefix reversal game" which generates only the permutations from n=2 (ie: {1,2}, {2,1}) to n=100, that require the highest number of prefix reversals in order to replace one at the beginning of the permutation.
For example,
{2, 4, 1, 3} (the first two elements reverse) -->
{4, 2, 1, 3} (the first four elements reverse) -->
{2, 1, 3, 4} (the first two elements reverse) -->
{1, 2, 3, 4} (end).
Therefore this permutation has a score of "4".
The part that I am having problems with is creating and implementing my own algorithm in order to find the highest scoring permutations without having to test every single one (because it is very inefficient). I was wondering if anybody could offer assistance in creating this algorithm.
I have been looking at algorithms such as the "pancake sorting" algorithm, but this seems to be the opposite of what I want.
Thank you so much for your time!
I jave a 2D array like this, just like a matrix:
{{1, 2, 4, 5, 3, 6},
{8, 3, 4, 4, 5, 2},
{8, 3, 4, 2, 6, 2},
//code skips... ...
}
(The Array is not sorted)
I want to get all the "4" position, instead of searching the array one by one, and return the position, how can I search it faster / more efficient? thz in advance.
You can't. There is no magic way. Your algorithm will always need to check each cell in your matrix, so it will always be O(n*m) for a matrix of size n * m.
If you can sort your matrix first, then you can get away with O(log(n) * m), as you can use a binary search inside each row.
The only way to do this is less than m * n is to have it presorted in some way. It is not clear from your question if that is possible.
There is no obvious algorithmic optimisation (unless you have some a priori knowledge of the data, e.g. that it's sorted, or you know how many 4s there are). However there are micro-optimisations that you can use, e.g. if your array is 32 bit int and you can use SSE then you can load and compare 4 elements at a time.
You can choose speed or memory consumption. If Memory is not important you could create a List of positions where values are stored. So you have still your m*n array, but additionaly an array of "position-lists". You would have to create "setter"-methods which write down a position in the lists each time a value is added or changed. So the idea is not to improve the search but avoid it.
Example:
You have a 2*2 Array.
{{0,0}
{0,0}}
And you want to add a 4 in the . So you have to call your method write which is called with the parameters X, Y, and Value. This method would change your array to
{{4,0},
{0,0}}
but also create a list
List4=>{(0,0)}
with the position of fours. If you add a second 4 it would look like
{{4,0}
{4,0}}
List4=>{(0,0),(1,0)}
So if you want to find all 4 in your matrix you just have to go to all positions in your List4. Of course you would have to create a list for each value in your array. So you could have a maximum of m*n lists with positions if the matrix contains each value only once.