How to find duplicate element in array and return duplicate index - ruby

I need to find duplicate latitude in an array and nudge it a bit to avoid marker display problem.
I searched and find a way to do it in ruby:
1.find duplicate element in ruby
(I consider sort array element and check adjacent element)
2.use array.indexof() to get its index(may have 3 or more duplicate element)
This works sure but I feel its not the best way. Is there a way to find duplicate and index of duplicate in one go?
Thanks in advance
EDIT:
I've find a way,check duplicate and change on spot.
But the problem is this function change all duplicate value to another duplicated value.
I think its because the main array is not updated during check and change procedure, attached is my code,anyway to improve it?
#ln=0
for #ln in 0..#checkLocation.length-1 do
if (!(#checkLocation.index(#existlat)==nil) && (#existlat!=nil))
#checkLocation[#ln]=#checkLocation[#ln]+0.00001
end
#existlat=#checkLocation[#ln]
end

a = [:a, :b, :c, :b, :d, :a, :e]
a.each_index.group_by{|i| a[i]}.values.select{|a| a.length > 1}.flatten
# => [0, 5, 1, 3]

Finding dupes is not very difficult if performance is not a real issue for you.
The most natural way would be to compare each element with all the other elements:
for (int i = 0; i < arraySize-1; ++i) {
for (int j = i+1; j < arraySize; ++j) {
if(array[i] == array[j]) changeDupe(array[j]);
}
}
The code above will allow you to change all the dupes.
Example in execution, changin dupes to 0:
Input: {1, 2, 3, 2, 1, 4, 5, 6, 8, 2}
Output: {1, 2, 3, 0, 0, 4, 5, 6, 8, 0}
Another way to achieve this is to use a second array. If you are using integer values, you can make it like this:
int input[10] = {1, 2, 3, 2, 1, 4, 5, 6, 8, 2};
bool output[10] = {false, false, false, false, false, false, false, false, false, false};
for (int i = 0; i < arraySize; ++i) {
if (output[input[i]] == false) changeDupe(input[i]));
else output[input[i]] = true;
}
However, if one of your elements is bigger than the size of your array you will have a boundary problem. Suppose you have the value 100, then you would be trying to access the 100th element of the boolean array.
If you want to use the second algorithm but you are not working with an integer array, you could use a map to map each value on your array to an int, and then use the map value to set the booleans.
A pseudocode would look like this:
Map<yourData, int> map;
map<someValue, 1>;
map[someValue] = 1; //work based on this return value;
Yeeeet another way is to sort the array before iterating over it, and stop once you hit a different number. This would diminish the number of times you iterate over the array, but you would be adding the sorting algorithm complexity (probably O(n log(n))).
The code would look something like this:
int i = 0;
while (i < arraySize-1) {
if(array[i] == array[i+1])
array[i] = 0;
i++;
}
Input: {1, 1, 2, 3, 3, 4, 5, 6, 7, 8};
Output: {0, 1, 2, 0, 3, 4, 5, 6, 7, 8}
Complexity:
for the first algorithm, you would have N*(N-1) which I would say is O(n²).
for the second is O(n), but restrictions apply.
for the third, it would be the sort + O(n) for the loop.

Related

Fast way of getting r-long combinations of set A that have at least one element from set B, which is a subset of A

For example, if A={0,1,2,3,4}, r=3 and B={1,4}, the result would be:
[0, 1, 2]
[0, 1, 3]
[0, 1, 4]
[0, 2, 4]
[0, 3, 4]
[1, 2, 3]
[1, 2, 4]
[1, 3, 4]
[2, 3, 4]
That's all the r-long combinations of A, excluding [0, 2, 3], because that one doesn't contain either 1 or 4.
The solution that I currently have is the following, using the fastest algorithm for getting normal combinations I know of, and just doing a simple check to see if combinations generated also contain an element of B (java):
int[] A = new int[]{0,1,2,3,4};
int[] B = new int[]{1,4};
int n = A.length;
int r = 3;
int[] picks = new int[r]; //Holds indexes of elements in A
for (int i = 0; i < picks.length; i++)
picks[i] = i;
int lastindex = picks.length - 1;
outer:
while (true) {
int at = lastindex;
while (true) {
picks[at] += 1;
if (picks[at] < n) {
int displacement = picks[at] - at; // at + displacement = picks[at], at + displacement + 1 = picks[at] + 1 ,...
// Make all picks elements after at y = picks[at] + x, so picks={0, 2, 4, 6, 18, 30} & at=3 --> picks={0, 2, 4, 5, 6, 7}
// (Note that this example will never take place in reality, because the 18 or the 30 would be increased instead, depending on what n is)
// Do the last one first, because that one is going to be the biggest,
picks[lastindex] = lastindex + displacement;
if (picks[lastindex] < n) { // and check if it doesn't overflow
for (int i = at + 1; i < lastindex; i++)
picks[i] = i + displacement;
int[] combination = new int[r];
for (int i = 0; i < r; i++)
combination[i] = A[picks[i]];
System.out.print(Arrays.toString(combination));
//^With this, all r-long combinations of A get printed
//Straightforward, bruteforce-ish way of checking if int[] combination
//contains any element from B
presence:
for (int p : combination) {
for (int b : B) {
if (p==b) {
System.out.print(" <-- Also contains an element from B");
break presence;
}
}
}
System.out.println();
break;
}
}
at--;
if (at < 0) {
//Moving this check to the start of the while loop will make this natively support pick 0 cases (5C0 for example),
//but reduce performance by I believe quite a bit. Probably better to special-case those (I haven't
// done that in this test tho)
break outer;
}
}
}
output:
[0, 1, 3] <-- Also contains an element from B
[0, 1, 4] <-- Also contains an element from B
[0, 2, 3]
[0, 2, 4] <-- Also contains an element from B
[0, 3, 4] <-- Also contains an element from B
[1, 2, 3] <-- Also contains an element from B
[1, 2, 4] <-- Also contains an element from B
[1, 3, 4] <-- Also contains an element from B
[2, 3, 4] <-- Also contains an element from B
As written in the comments, I believe this method to be very rudimentary. Can anyone think of a faster way to do this?
Assuming you have a int[][] FindCombinations(int[] set, int length) function that returns a list of all the length-long combinations of set, do the following (pseudo-code):
for i=1 to B.length
{
int bi = B[i];
A = A - bi; // remove bi from A
foreach C in FindCombinations(A, r-1)
{
output C+bi // output the union of C and {bi}
}
}
This way all combinations contain at least one element from B (and may also contain elements of B that have not yet been used) without much extra work. All other combinations are eliminated at no cost (the don't have to be found at all) and also the test that a combination contains an element from B for each combination is also eliminated.
Whether this algorithm is faster, greatly depends on how efficently you can add/remove elements from a set and the percentage of included vs excluded combinations (i.e. if you only end up excluding 1% of the total combinations it is probably not worth it)
Note that when getting the combinations to union with {b[i]} these may also contain an element B[j] where j>i. When you get to the point that you get the combinations to union with B[j] none of them will contain B[i], so all combinations are unique.

How do you check if one array is a subsequence of another?

I'm looking to explore different algorithms, both recursive and dynamic programming, that checks if one arrayA is a subsequence of arrayB. For example,
arrayA = [1, 2, 3]
arrayB = [5, 6, 1, 7, 2, 9, 3]
thus, arrayA is indeed a subsequence of arrayB.
I've tried a few different searches, but all I can seem to find is algorithms to compute the longest increasing subsequence.
Since you must match all elements of arrayA to some elements of arrayB, you never need to backtrack. In other words, if there are two candidates in arrayB to match an element of arrayA, you can pick the earliest one, and never retract the choice.
Therefore, you do not need DP, because a straightforward linear greedy strategy will work:
bool isSubsequence(int[] arrayA, int[] arrayB) {
int startIndexB = 0;
foreach (int n in arrayA) {
int next = indexOf(arrayB, startIndexB , n);
if (next == NOT_FOUND) {
return false;
}
startIndexB = next+1;
}
return true;
}
As dasblinkenlight has correctly said(and i could not have phrased it better than his answer!!) a greedy approach works absolutely fine. You could use the following pseudocode (with just a little more explanation but totally similar to what dasblinkenlight has written)which is similar to the merging of two sorted arrays.
A = {..}
B = {..}
j = 0, k = 0
/*j and k are variables we use to traverse the arrays A and B respectively*/
for(j=0;j<A.size();){
/*We know that not all elements of A are present in B as we
have reached end of B and not all elements of A have been covered*/
if(k==B.size() && j<A.size()){
return false;
}
/*we increment the counters j and k both because we have found a match*/
else if(A[j]==B[k]){
j++,k++;
}
/*we increment k in the hope that next element may prove to be an element match*/
else if(A[j]!=B[k]){
k++;
}
}
return true; /*cause if we have reached this point of the code
we know that all elements of A are in B*/
Time Complexity is O(|A|+|B|) in the worst case, where |A| & |B| are the number of elements present in Arrays A and B respectively. Thus you get a linear complexity.
As #sergey mentioned earlier, there is no need to do backtracking in this case.
Here just another Python version to the problem: [Time complexity: O(n) - worst]
>>> A = [1, 2, 3]
>>> B = [5, 6, 1, 7, 8, 2, 4, 3]
>>> def is_subsequence(A, B):
it = iter(B)
return all(x in it for x in A)
>>> is_subsequence(A, B)
True
>>> is_subsequence([1, 3, 4], B)
False
>>>
Here is an example in Ruby:
def sub_seq?(a_, b_)
arr_a = [a_,b_].max_by(&:length);
arr_b = [a_,b_].min_by(&:length);
arr_a.select.with_index do |a, index|
arr_a.index(a) &&
arr_b.index(a) &&
arr_b.index(a) <= arr_a.index(a)
end == arr_b
end
arrayA = [1, 2, 3]
arrayB = [5, 6, 1, 7, 2, 9, 3]
puts sub_seq?(arrayA, arrayB).inspect #=> true
Here is an example in GOLANG...
func subsequence(first, second []int) bool {
k := 0
for i := 0; i < len(first); i++ {
j := k
for ; j < len(second); j++ {
if first[i] == second[j] {
k = j + 1
break
}
}
if j == len(second) {
return false
}
}
return true
}
func main(){
fmt.Println(subsequence([]int{1, 2, 3}, []int{5, 1, 3, 2, 4}))
}

Difference between Lists

You are given 2 lists, the first with a elements and the second with b elements, with a < b.
For each element e in list a, you want to take a element f in list b, and replace e with e-f. You cannot use a element twice unless it appears in list b twice.
The problem is to find the minimum value of the largest element of list a.
For example, say list a is [1, 2, 3, 4], and list b is [5, 6, 7, 8, 9, 10, 11, 12]. We would take the e's to be 5, 6, 7, 8, so that list a becomes [5-1, 6-2, 7-3, 8-4], with the largest element being 4. So 4 is the answer.
Another example: if list a is [1, 4, 7] and list b is [-1, 3, 4, 5, 6, 7, 8], we would take the e's to be -1, 4, 7, so that list a becomes [2, 0, 0], and the answer is 2. So 2 is the answer.
I know this is poorly worded, if I could do anything to better word it, please let me know. I tried first sorting list a and list b, then did not know what to do.
If you could help, please do.
Thanks!
calculate the values of the list:
(java)
List listA = ...;
List listb = ...;
for(int i = 0; i < listA.size(); i++){
listA.set(i, listA.get(i) - listb.get(i));
}
find the highest value in listA:
iHighestValue = listA.get(0); //setting it to 0 would not work with lists containing only negative integers
for(int j = 1; j < listA.size(); j++){
if(listA.get(j) > iHighestValue)
iHighestValue = listA.get(i);
}
[Edit]: sorry, it doesn't show as code (don't know why)

Finding minimum element to the right of an index in an array for all indices

Given an array, I wish to find the minimum element to the right of the current element at i where 0=<i<n and store the index of the corresponding minimum element in another array.
For example, I have an array A ={1,3,6,7,8}
The result array would contain R={1,2,3,4} .(R array stores indices to min element).
I could only think of an O(N^2) approach.. where for each element in A, I would traverse the remaining elements to right of A and find the minimum.
Is it possible to do this in O(N)? I want to use the solution to solve another problem.
You should be able to do this in O(n) by filling the array from the right hand side and maintaining the index of the current minimum, as per the following pseudo-code:
def genNewArray (oldArray):
newArray = new array[oldArray.size]
saveIndex = -1
for i = newArray.size - 1 down to 0:
newArray[i] = saveIndex
if saveIndex == -1 or oldArray[i] < oldArray[saveIndex]:
saveIndex = i
return newArray
This passes through the array once, giving you the O(n) time complexity. It can do this because, once you've found a minimum beyond element N, it will only change for element N-1 if element N is less than the current minimum.
The following Python code shows this in action:
def genNewArray (oldArray):
newArray = []
saveIndex = -1
for i in range (len (oldArray) - 1, -1, -1):
newArray.insert (0, saveIndex)
if saveIndex == -1 or oldArray[i] < oldArray[saveIndex]:
saveIndex = i
return newArray
oldList = [1,3,6,7,8,2,7,4]
x = genNewArray (oldList)
print "idx", [0,1,2,3,4,5,6,7]
print "old", oldList
print "new", x
The output of this is:
idx [0, 1, 2, 3, 4, 5, 6, 7]
old [1, 3, 6, 7, 8, 2, 7, 4]
new [5, 5, 5, 5, 5, 7, 7, -1]
and you can see that the indexes at each element of the new array (the second one) correctly point to the minimum value to the right of each element in the original (first one).
Note that I've taken one specific definition of "to the right of", meaning it doesn't include the current element. If your definition of "to the right of" includes the current element, just change the order of the insert and if statement within the loop so that the index is updated first:
idx [0, 1, 2, 3, 4, 5, 6, 7]
old [1, 3, 6, 7, 8, 2, 7, 4]
new [0, 5, 5, 5, 5, 5, 7, 7]
The code for that removes the check on saveIndex since you know that the minimum index for the last element can be found at the last element:
def genNewArray (oldArray):
newArray = []
saveIndex = len (oldArray) - 1
for i in range (len (oldArray) - 1, -1, -1):
if oldArray[i] < oldArray[saveIndex]:
saveIndex = i
newArray.insert (0, saveIndex)
return newArray
Looks like HW. Let f(i) denote the index of the minimum element to the right of the element at i. Now consider walking backwards (filling in f(n-1), then f(n-2), f(n-3), ..., f(3), f(2), f(1)) and think about how information of f(i) can give you information of f(i-1).

How to sort an array in linear timer and in place?

question origin
Given an unsorted array of size n containing objects with ids of 0 … n-1, sort the array in place and in linear time. Assume that the objects contain large members such as binary data, so instantiating new copies of the objects is prohibitively expensive.
void linearSort(int* input, const int n) {
for (int i = 0; i < n; i++) {
while (input[i] != i) {
// swap
int swapPoint = input[i];
input[i] = input[swapPoint];
input[swapPoint] = swapPoint;
}
}
}
Is this linear? Does this sort work with any kind of array of ints? If so, why do we need quicksort anymore?
Despite the while loop inside the for, this sort is linear O(n). If the while loop occurs multiple times for a given i then for the i values that match swapPoint there will not execute the while loop at all.
This implementation will only work for arrays of ints where there are no duplicates and the values are sequential from 0 to n-1, which is why Quicksort still is relevant being O(n log n) because it works with non-sequential values.
This can be easily tested by making the worst case:
input = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
and then using the following code:
int whileCount = 0;
for (int i = 0; i < n; i++)
{
while (input[i] != i)
{
whileCount++;
// swap
int swapPoint = input[i];
input[i] = input[swapPoint];
input[swapPoint] = swapPoint;
}
Console.WriteLine("for: {0}, while: {1}", i, whileCount);
}
The output will be as follows:
for: 0, while: 9
for: 1, while: 9
for: 2, while: 9
for: 3, while: 9
for: 4, while: 9
for: 5, while: 9
for: 6, while: 9
for: 7, while: 9
for: 8, while: 9
for: 9, while: 9
so you see even in the worst case where you have the while loop run n-1 times in the first iteration of the for loop, you still only get n-1 iterations of the while loop for the entire process.
Further examples with random data:
{7, 1, 2, 4, 3, 5, 0, 6, 8, 9} => 2 on i=0, 1 on i=3 and nothing more. (total 3 while loop runs)
{7, 8, 2, 1, 0, 3, 4, 5, 6, 9} => 7 on i=0 and nothing more (total 7 while loop runs)
{9, 8, 7, 4, 3, 1, 0, 2, 5, 6} => 2 on i=0, 2 on i=1, 1 on i=2, 1 on i=3 (total 6 while loop runs)
Each you put input[i] to the position swapPoint, which is exactly where it needs to go. So in the following steps those elements are already at the right place and the total time of exchange won't exceed the size n.

Resources