Find repeated element in array - arrays

Consider array of INT of positive numbers:
{1,3,6,4,7,6,9,2,6,6,6,6,8}
Given: only one number is repeated, return number and positions with efficient algorithm.
Any ideas for efficient algorithms?

One possible solution is to maintain an external hash map. Iterate the array, and place the indices of values found into the hash map. When done, you now know which number was duplicated and the indices of the locations it was found at.

In an interview situation, I guess its your chance to ask around the question, for example, how many numbers? what range of numbers? you could state that an optimum algorithm could change depending.
That gives you a chance to show how you solve problems.
If the range of ints in the array is small enough then you could create another array to keep count of the number of times each integer is found then go linearly through the array accumulating occurrence counts, stopping when you get to an occurance count of two.

Hash will do just fine in here. Add numbers to it one by one, each time checking if number's already in there.

Well, there probably is some trick (usually is). But just off the cuff, you should be able to sort the list (O(nlogn)). Then its just a matter of finding a number that is the same as the next one (linear search - O(n)). You'd have to sort it as tuples of values and original indices of course, so you could return that index you are looking for. But the point is that the upper bound on an algorithim that will do the job should be O(nlogn).
If you just go through the list linerally, you could take each index, then search through the rest of the list after it for a matching index. I think that's roughly equivalent to the work done in a bubble sort, so it would probably be O(n^2), but a simple one.
I really hate trick questions as interview questions. They are kind of like optical illusions: Either you see it or you don't, but it doesn't really say anything bad about you if you don't see the trick.

I'd try this:
all elms of list have to be looked at (=> loop over the list)
before the repeated elm is known, store elm => location/index in a hash/dictionary
as soon as the second occurence of the repeated element is found, store its first postion (from the hash) and the current position in the result array
compare further elms of list against the repeated elm, append found locations to the result array
in code:
Function locRep( aSrc )
' to find repeated elm quickly
Dim dicElms : Set dicElms = CreateObject( "Scripting.Dictionary" )
' to store the locations
Dim aLocs : aLocs = Array()
' once found, simple comparison is enough
Dim vRepElm : vRepElm = Empty
Dim nIdx
For nIdx = 0 To UBound( aSrc )
If vRepElm = aSrc( nIdx ) Then ' repeated elm known, just store location
ReDim Preserve aLocs( UBound( aLocs ) + 1 )
aLocs( UBound( aLocs ) ) = nIdx
Else ' repeated elm not known
If dicElms.Exists( aSrc( nIdx ) ) Then ' found it
vRepElm = aSrc( nIdx )
ReDim aLocs( UBound( aLocs ) + 2 )
' location of first occurrence
aLocs( UBound( aLocs ) - 1 ) = dicElms( aSrc( nIdx ) )
' location of this occurrence
aLocs( UBound( aLocs ) ) = nIdx
Else
' location of first occurrence
dicElms( aSrc( nIdx ) ) = nIdx
End If
End If
Next
locRep = aLocs
End Function
Test run:
-------------------------------------------------
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
Src: 1 3 6 4 7 6 9 2 6 6 6 6 8
Res: 2 5 8 9 10 11
ok
Src:
Res:
ok
Src: 1 2 3
Res:
ok
Src: 1 1 2 3 4 5 6
Res: 0 1
ok
Src: 1 2 3 4 5 6 6
Res: 5 6
ok
=================================================

using namespace std;
list<int> find_duplicate_idx(const vector<int>& A)
{
hash_map<int, int> X;
list<int> idx;
for ( int i = 0; i < A.size(); ++ i ) {
hash_map<int, int>::iterator it = X.find(A[i]);
if ( it != X.end() ) {
idx.push_back(it->second);
idx.push_back(i);
for ( int j = i + 1; j < A.size(); ++j )
if ( A[j] == A[i] )
idx.push_back(j);
return idx;
}
X[A[i]] = i;
}
return idx;
}
This is a solution my friend provided. Thank you SETI from mitbbs.com

Use the hash-map to solve it :
private int getRepeatedElementIndex(int[] arr) {
Map<Integer, Integer> map = new HashMap();
// find the duplicate element in an array
for (int i = 0; i < arr.length; i++) {
if(map.containsKey(arr[i])) {
return i;
} else {
map.put(arr[i], i);
}
}
throw new RuntimeException("No repeated element found");
}
Time complexity : O(n)
Space complexity : O(n)

Related

How can I find the nonzero values in a MATLAB cells array?

The following code generates an cell array Index [1x29], where each cell is an array [29x6]:
for i = 1 : size(P1_cell,1)
for j = 1 : size(P1_cell,2)
[Lia,Lib] = ismember(P1_cell{i,j},PATTERNS_FOR_ERANOS_cell{1},'rows');
Index1(i,j) = Lib % 29x6
end
Index{i} = Index1; % 1x29
end
How can I find the nonzero values in Index array?, i.e. generate an array with the number of non-zero values in each row of the Index1 array. I tried the following loop, but it doesn't work, it creates conflict with the previous one:
for i = 1 : length(Index)
for j = 1 : length(Index)
Non_ceros = length(find(Index{:,i}(j,:))); %% I just need the length of the find function output
end
end
I need help, Thanks in advance.
The nnz() (number of non-zeros) function can be used to evaluate the number of non-zero elements. To obtain the specific positive values you can index the array by using the indices returned by the find() function. I used some random test data but it should work for 29 by 6 sized arrays as well.
%Random test data%
Index{1} = [5 2 3 0 zeros(1,25)];
Index{2} = [9 2 3 1 zeros(1,25)];
Index{3} = [5 5 5 5 zeros(1,25)];
%Initializing and array to count the number of zeroes%
Non_Zero_Counts = zeros(length(Index),1);
for Row_Index = 1: length(Index)
%Evaluating the number of positive values%
Array = Index{Row_Index};
Non_Zero_Counts(Row_Index) = nnz(Array);
%Retrieving the positive values%
Positive_Indices = find(Array);
PositiveElements{Row_Index} = Array(Positive_Indices);
disp(Non_Zero_Counts(Row_Index) + " Non-Zero Elements ");
disp(PositiveElements{Row_Index});
end
Ran using MATLAB R2019b
for i = 1 : length(Index)
for j = 1 : length(Index)
Non_ceros(i,j) = nnz(Index{:,i}(j,:));
end
end

Trouble understanding one line in Insertion Sort (Python 3)

I was looking through the other threads concerning the Insertion Sort but didn't find the answer that relates to the specific part of it which I do not understand.
My full Insertion Sort algorithm can be seen below. It works as intended, but I cannot figure out the purpose of that last line.
array[position] = value
Let me explain through an example:
When the 'for' loop starts, index = 1.
=> value = array[1] = 3
=> position = 1
=> Since 4 > 3, the item at index 1, is swapped with the item at index 0.
=> position -= 1
=> position = 0
We now get to the line which confuses me:
array[0] = value
=> value = array[index] = array[0] = 3
However, when the 'for' loop goes through its second iteration, index = 2.
And so immediately value = array[2] and position = 2 ?
Even though I know that this last line of code is necessary I just cannot see what purpose it serves.
Could someone please explain to me this final logical step?
Thank you in advance for your time and help.
array = [4,3,5,6,12,9,8,6]
for index in range (1, len(array)):
value = array[index]
position = index
while position > 0 and array[position - 1] > value:
array[position] = array[position - 1]
position -= 1
array[position] = value
The position variable represents (at the end) where you will eventually insert the number. Without the last line, you are not inserting the number at 'position' at the correct place (it will result in the 1 index after). Below is my code for insertion sort.
def insertionSort(arr):
length = len(arr)
for i in range(1, length):
currNum = arr[i]
j = i - 1
while j >= 0 and currNum < arr[j]:
arr[j + 1] = arr[j]
j -= 1
arr[j+1] = currNum
return arr
You wouldn't have really swapped the numbers without that line, would you?
index 1:
-> [4,3,5,6,12,9,8,6] (enters while loop)
-> [4,4,5,6,12,9,8,6] ("pushes" 4 to position 1)
-> <waits for while loop to finish>
-> [3,4,5,6,12,9,8,6] (assigns 3 to position 0 since there are no other elements > 3)
index 2:
...
I think is not really needed at start in for loop, because it was used to index inside the loop. Looks the picture

Delete every other item in the array until only one is left

My problem is asking to iterate over an array of items and delete every other item until I reach the end of the array when I should start iterating backwards and keep deleting every other item and so on back and forth until only one item is left in the array.
for example: 1,2,3,4,5, would become 1,3,5 and then 3
I understand that I shouldn't be deleting from the original array so I created another array that just keeps every other item while decreasing its size but I can't get it to work and end up with an infinite loop.
arr=*(1..10)
s_arr=[]
until s_arr.length==1
i=0
while i<arr.length
s_arr.push(arr[i])
i+=2
end
arr=s_arr.reverse
s_arr=arr
end
Thank you.
Each iteration, replace the array with a version with every other element dropped
arr = *(1..10)
while arr.length > 1
arr = arr.select.with_index { |_, i| i % 2 == 0 }.reverse
end
This doesn't match your example, but your example seems inconsistent in the first place. If [1,2,3,4,5] goes to [1,3,5], then the next step should be [1,5] instead of [3].
This is similar to #Max's answer, but implemented recursively.
def last_one_standing(arr)
return arr.first if arr.size == 1
last_one_standing arr.select.with_index { |_,i| i.even? }.reverse
end
(1..16).each { |i| puts "1..%d: %d" % [i, last_one_standing((1..i).to_a)] }
1..1: 1
1..2: 1
1..3: 3
1..4: 3
1..5: 1
1..6: 1
1..7: 3
1..8: 3
1..9: 9
1..10: 9
1..11: 11
1..12: 11
1..13: 9
1..14: 9
1..15: 11
1..16: 11
try something like this so you can take advantage of Ruby's power
result = []
array.each_with_index {|val,idx| result << val if ( idx % 2 == 0)}
Try this on your ruby console:
arr=*(1..10)
x = (Math::log(arr.length) / Math::log(3)).to_i
3**x
arr=*(1..10)
s_arr=[]
until s_arr.length == 1
i=0
while i < arr.length
s_arr.push(arr[i])
i+=2
end
arr=s_arr.reverse
if s_arr.length != 1
s_arr=[]
end
end
Your problem was setting the s_arr array the same as the arr. Then you must add a conditional to tell it to stop when it does reach 1 otherwise it'll become 0 instead.
EDIT:
arr=*(1..10)
s_arr=[]
until s_arr.length == 1
s_arr = []
i=0
while i < arr.length
s_arr.push(arr[i])
i+=2
end
arr=s_arr.reverse
end
even better solution.

Vector search Algorithm

I have the following problem. Say I have a vector:
v = [1,2,3,4,5,1,2,3,4,...]
I want to sequentially sample points from the vector, that have an absolute maginute difference higher than a threshold from a previously sampled point. So say my threshold is 2.
I start at the index 1, and sample the first point 1. Then my condition is met at v[3], and I sample 3 (since 3-1 >= 2). Then 3, the new sampled point becomes the reference, that I check against. The next sampled point is 5 which is v[5] (5-3 >= 2). Then the next point is 1 which is v[6] (abs(1-5) >= 2).
Unfortunately my code in R, is taking too long. Basically I am scanning the array repeatedly and looking for matches. I think that this approach is naive though. I have a feeling that I can accomplish this task in a single pass through the array. I dont know how though. Any help appreciated. I guess the problem I am running into is that the location of the next sample point can be anywhere in the array, and I need to scan the array from the current point to the end to find it.
Thanks.
I don't see a way this can be done without a loop, so here is one:
my.sample <- function(x, thresh) {
out <- x
i <- 1
for (j in seq_along(x)[-1]) {
if (abs(x[i]-x[j]) >= thresh) {
i <- j
} else {
out[j] <- NA
}
}
out[!is.na(out)]
}
my.sample(x = c(1:5,1:4), thresh = 2)
# [1] 1 3 5 1 3
You can do this without a loop using a bit of recursion:
vsearch = function(v, x, fun=NULL) {
# v: input vector
# x: threshold level
if (!length(v) > 0) return(NULL)
y = v-rep(v[1], times=length(v))
if (!is.null(fun)) y = fun(y)
i = which(y >= x)
if (!length(i) > 0) return(NULL)
i = i[1]
return(c(v[i], vsearch(v[-(1:(i-1))], x, fun=fun)))
}
With your vector above:
> vsearch(c(1,2,3,4,5,1,2,3,4), 2, abs)
[1] 3 5 1 3

How to specify starting value of index in Groovy's eachWithIndex method?

When using Groovy's eachWithIndex method the index value starts at 0, I need it to start at 1. How can I do that?
The index will always start from 0
Your options are:
1) Add an offset to the index:
int offs = 1
list.eachWithIndex { it, idx ->
println "$it # pos ${idx + offs}"
}
2) Use something other than eachWithIndex (ie: transpose a list of integers starting at 1 with your original list, and then loop through this)
3) You can also use default parameters to hack this sort of thing in... If we pass eachWithIndex a closure with 3 parameters (the two that eachWithIndex is expecting and a third with a default value of index + 1):
[ 'a', 'b', 'c' ].eachWithIndex { item, index, indexPlusOne = index + 1 ->
println "Element $item has position $indexPlusOne"
}
We will give the output:
Element a has position 1
Element b has position 2
Element c has position 3
I wouldn't use eachWithIndex at all, a for loop with .indexed(1) will be more elegant/readable:
for (item in ['a','b','c','d','e'].indexed(1)) {
println("element $item.key = $item.value")
}
outputs:
element 1 = a
element 2 = b
element 3 = c
element 4 = d
element 5 = e
caveat -- indexed(n) is only available in Groovy 2.4.0 onwards
What about just using a Range?
def offset = 1
def arr = [1,2,3,4,5]
def len = arr.size() - 1
arr[offset..len].eachWithIndex{n,i -> println "${i+offset}:$n"}
You could use some metaprogramming hackery as well:
def eachWithMyIndex = { init, clos ->
delegate.eachWithIndex { it, idx -> clos(it, idx + init) }
}
List.metaClass.eachWithMyIndex = eachWithMyIndex
[1,2,3].eachWithMyIndex(10) {n, idx -> println("element $idx = $n") }
gives output:
element 10 = 1
element 11 = 2
element 12 = 3

Resources