Efficiently inserting an element into an array
Show older comments
I have a 1xn array A and need to insert a number x between the mth and (m+1)th element.
I know this can be done by
A = [A(1:m),x,A(m+1:end)]
but I am not sure how MATLAB processes this - it could possibly involve re-assigning the entire latter section of the array, taking O(n) time. I suspect this is the case as a program that applies this many times is running quite slowly.
Is there a more efficient way to do this?
13 Comments
Matt J
on 17 Aug 2021
No, there isn't. If you elaborate on what the code is doing, it might be possible to recommend alternative formulations.
Yazan
on 17 Aug 2021
I think the complexity is O(n) indeed.
Lorcan O'Connor
on 17 Aug 2021
Matt J
on 17 Aug 2021
The elaboration that I think we need is on what is being done with A and why it needs to remain sorted. You will not be able to do so with o(N) effort.
the cyclist
on 17 Aug 2021
I think it may be possible for the memory usage to be more efficient, if you are steadily growing A, element-by-element, to a large size. The reason is that MATLAB may need to repeatedly reallocate the memory for A.
If you know how large A will ultimately get, you can preallocate A to be that size (filling in with NaNs or zeros). You may need to do a bit more indexing to manipulate only the section of A that contains meaningful values, for your search/insertion. The devil is in the details.
Just to expand on @the cyclist's preallocation approach, here's a version of that which avoids the reallocation. Here I used find to keep that bit concise...which I'm guessing would be O(n)...but you'd replace this with the log(n) bit that depends on A being sorted.
A = nan(1,100);
for i = 1:100
b=rand;
m=find(A<b,1,'last');
if isempty(m)
A(1:i)=[b A(1:i-1)];
else
A(1:i)=[A(1:m) b A(m+1:i-1)];
end
end
isequal(A,sort(A))
Lorcan O'Connor
on 17 Aug 2021
Lorcan O'Connor
on 17 Aug 2021
Lorcan O'Connor
on 17 Aug 2021
dpb
on 17 Aug 2021
All @Dave B claimed is to save any memory reallocation, not the complexity of the MATLAB-generated code.
TMW never divulges details of the code optimizations, but it is possible the reassignment boils down to a call to the compiler RTL memcopy() routine which is about as fast as you're going to get if you use an algorithm that must actually do the insertion each iteration.
Alternatively, keep only the insertion points and only build the list at the end although then the complexity of the indexing may turn out to be the killer...
Lorcan O'Connor
on 17 Aug 2021
Dave B
on 17 Aug 2021
I probably was overly simplistic above, as I'm (probably) making a temporary array for the right hand side. The problem with appending to an array is that you reallocate it every time: insertion is inherently expensive.
Maybe you could do a little experiment to approximate O?
Dave B
on 17 Aug 2021
"Are there other data structures, in MATLAB or not, that can insert in sublinear time?"
I'd think the standard datatype for fast insertion is a linked list, there isn't a built-in linked list in MATLAB (to my knowledge), but you can implement your own. https://www.mathworks.com/help/matlab/matlab_oop/example-implementing-linked-lists.html The example is for doubly linked and you could probably simplify by making a singly linked.
Accepted Answer
More Answers (0)
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!