Index of duplicate elements of ArrayList is giving same index value - java-7

I have tried to find index of duplicate elements of 2 in ArrayList - [1, 2, 3, 4, 2, 5, 6, 2, 7, 2].
Which the Output should be [1,4,7,9]. But I am getting as [1,1,1,1]. Please anyone help me in getting the correct output.
package com.practice.first;
import java.util.ArrayList;
import java.util.List;
public class SampleList {
public static void main(String[] args) {
List<Integer> al = new ArrayList<Integer>();
al.add(1);
al.add(2);
al.add(3);
al.add(4);
al.add(2);
al.add(5);
al.add(6);
al.add(2);
al.add(7);
al.add(2);
for (int i = 0; i < al.size(); i++) {
if (al.get(i).equals(2)) {
System.out.println("Element 2 is present at " + al.indexOf(al.get(i)));
}
}
}
}

Your problem is in al.indexOf(al.get(i)). From official documentation:
get(int index) Returns the element at the specified position in this list.
indexOf(Object o) Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
You probably want just:
System.out.println("Element 2 is present at " + i);

From the javadoc of indexOf:
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
So indexOf will always return the first occurence of the element even if it is present multiple times in the list. To get the right index, you just need to print your loop variable i like this:
for (int i = 0; i < al.size(); i++) {
if (al.get(i).equals(2)) {
System.out.println("Element 2 is present at " + i);
}
}

Related

How to extract items from nested lists in a dart

I was trying to write a recursive quicksort algorithm. The problem is that it returns elements in a set of nested arrays
void main(List<String> arguments) {
List myList = [2, 4, 9, 7, 1, 12];
print(quickSort(myList));
}
List quickSort(var arr){
if (arr.length < 2){
return arr;
} else {
int pivot = arr[0];
List less = [];
List greater = [];
arr.removeAt(0);
arr.forEach((element) {
if (element > pivot){
greater.add(element);
} else {
less.add(element);
}
});
return [quickSort(less), pivot, quickSort(greater)];
}
}
Here is the result of the algorithm
[[1], 2, [[], 4, [[7], 9, [12]]]]
I want to get the data in this format:
[1, 2, 4, 7, 9, 12]
There are one problem which are the main reason for your problems. But there are also multiple related problems when is the reason why you did not discover the main problem.
The main problem is that you are inserting lists instead of the content of the returned lists in:
return [quickSort(less), pivot, quickSort(greater)];
What you want here is to insert all elements from the returned list from of e.g. quickSort(less). Instead, you are inserting it as a List itself which makes your import like you are seeing it.
To fix this, you should use ... to tell Dart that it should iterate over the list and insert all the elements. So something like this:
return [...quickSort(less), pivot, ...quickSort(greater)];
The reason why you got this problem is because of missing types in general in your code. You should, in general, never just write List since that means List<dynamic> in Dart. dynamic means whatever type so the List are allowed to contain a mix of types. This is bad since that also means extracting data from these List are also going to be dynamic and Dart can therefore not help us preventing type issues.
I have rewritten your code to make it more type safe here:
void main(List<String> arguments) {
List<int> myList = [2, 4, 9, 7, 1, 12];
print(quickSort(myList));
}
List<int> quickSort(List<int> arr) {
if (arr.length < 2) {
return arr;
} else {
int pivot = arr[0];
List<int> less = [];
List<int> greater = [];
arr.removeAt(0);
for (final element in arr) {
if (element > pivot) {
greater.add(element);
} else {
less.add(element);
}
}
return [...quickSort(less), pivot, ...quickSort(greater)];
}
}
Also, I would suggest not using .forEach() but instead use normal for-each loops as I have done.
And at last, this would also be as type safe since we are allowed to use var/final to tell Dart that it should automatically figure out the correct type based on context. You should still, however, specify types when it comes to method signatures:
void main(List<String> arguments) {
final myList = [2, 4, 9, 7, 1, 12];
print(quickSort(myList));
}
List<int> quickSort(List<int> arr) {
if (arr.length < 2) {
return arr;
} else {
final pivot = arr[0];
final less = <int>[];
final greater = <int>[];
arr.removeAt(0);
for (final element in arr) {
if (element > pivot) {
greater.add(element);
} else {
less.add(element);
}
}
return [...quickSort(less), pivot, ...quickSort(greater)];
}
}
So the point is really that if you are ever going to specify types in Dart, then please write the full type since just List is much worse than final/var in most situations. :)

Remove duplicates in O(n) by hand

I need to remove all duplicates in a list, but only if the item in list a is the same in list b aswell. This is my current code, but at 100k items it's taking literal days, is there a fast way to do this?
Any help appreciated.
List<int> ind = new List<int>();
List<int> used = new List<int>();
for (int i = 0; i < a.Count; i++)
{
for (int j = 0; j < a.Count; j++)
{
if (i != j&&!used.Contains(i))
{
if (a[j] == a[i] && b[i] == b[j])
{
ind.Add(j);
used.Add(j);
}
}
}
}
List<string> s2 = new List<string>();
List<string> a2 = new List<string>();
for (int i = 0; i < a.Count; i++)
{
if (!ind.Contains(i))
{
s2.Add(a[i]);
a2.Add(b[i]);
}
}
The key to many such problems is the correct data structure. To avoid duplicates, you need to use Sets, as they remove duplicates automatically.
Here is the code in Java, I hope it is similar in C#:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
class Duplicates
{
static List<Integer> list1 = new ArrayList<>();
static List<Integer> list2 = new ArrayList<>();
static final int SIZE = 100_000;
static final int MAX_VALUE = 1000_000;
public static void main(String[] args)
{
// populate the lists with random values for testing
Random r = new Random();
for(int i=0; i<SIZE; i++)
{
list1.add(r.nextInt(MAX_VALUE));
list2.add(r.nextInt(MAX_VALUE));
}
Set<Integer> set1 = new HashSet<>(list1);
Set<Integer> set2 = new HashSet<>(list2);
// items that are in both lists
Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
Set<Integer> notSeenYet = new HashSet<>(intersection);
List<Integer> list1Unique = new ArrayList<Integer>();
for(int n: list1)
{
if(intersection.contains(n)) // we may have to skip this one
{
if(notSeenYet.contains(n)) // no, don't skip, it's the first occurrence
{
notSeenYet.remove(n);
}
else
{
continue;
}
}
list1Unique.add(n);
}
System.out.println("list 1 contains "+list1Unique.size()+" values after removing all duplicates that are also in list 2");
}
}
It takes less than a second for 100k values.
Output
list 1 contains 99591 values after removing all duplicates that are
also in list 2
Create a HashSet.
First, iterate through the list b and add all elements into the HashSet.
Then, iterate through each element of the list a. When you visit an element, ask the HashSet if it already contains that element. If if doesn't, it's a new element, so just keep it. If it does, it is a duplicate and you can remove it from a.
HashSets can perform the Do you have this element? question in O(1), so for the whole list, you have O(n).
For more information, check the documentation.
Here is a general algorithm to consider. We can start by sorting both lists in ascending order. Using a good sorting algorithm such as merge sort, this would take O(NlgN) time, where N is the length of the list. Once we have paid this penalty, we need only maintain two pointers in each of the lists. The general algorithm would basically involve walking up both lists, searching for duplicates in the first a list, should the value in question match the pointer into the b list. If there be a match, then duplicates would be removed from the a list, otherwise we keep walking until reaching the end of the a list. This process would be only O(N), making the biggest penalty the initial sort, which is O(NlgN).
To "remove duplicates" I understand to mean "from n identical items, leave the first and remove the remaining n - 1". If so then this is the algorithm:
Convert list b to set B. Also introduce set A_dup. Run through list a and for each item:
if item is found in A_dup then remove it from a,
else if item is found in set B then add it to A_dup.
Repeat.
Checking for existence in sets (both A_dup and B) is O(1) operation, also to add new item in the set. So, you're left with iterating through list a, which in total gives us O(n).
I think what you are trying to do is find distinct pairs, right?
If so, you can do that in one line using Zip and Distinct and a C# Tuple (or use an anonymous type).
var result = a.Zip(b, (x,y) => (x, y)).Distinct();
import java.util.*;
import java.util.stream.Collectors;
public class Test {
public static void main(String args[]) {
List<String> dupliKhaneList = new ArrayList<>();
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Khan");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Khan");
dupliKhaneList.add("Vaquar");
dupliKhaneList.add("Zidan");
// Solution 1 if want to remove in list
List<String> uniqueList = dupliKhaneList.stream().distinct().collect(Collectors.toList());
System.out.println("DupliKhane => " + dupliKhaneList);
System.out.println("Unique 1 => " + uniqueList);
// Solution 2 if want to remove using 2 list
List<String> list1 = new ArrayList<>();
list1.add("Vaquar");
list1.add("Khan");
list1.add("Vaquar");
list1.add("Vaquar");
list1.add("Khan");
list1.add("Vaquar");
list1.add("Zidan");
List<String> list2 = new ArrayList<>();
list2.add("Zidan");
System.out.println("list1 => " + list1);
System.out.println("list2 => " + list2);
list1.removeAll(list2);
System.out.println("removeAll duplicate => " + list1);
}
}
Results :
DupliKhane => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar, Zidan]
Unique 1 => [Vaquar, Khan, Zidan]
list1 => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar, Zidan]
list2 => [Zidan]
removeAll duplicate => [Vaquar, Khan, Vaquar, Vaquar, Khan, Vaquar]

Generate ordered list of sum between elements in large lists

I'm not sure whether this question should be posted in math of overflow, but here we go.
I have an arbitrary amount of ordered lists (say 3 for example) with numerical values. These lists can be long enough that trying all combinations of values becomes too computationally heavy.
What I need is to get an ordered list of possible sums when picking one value from each of the lists. Since the lists can be large, I only want the N smallest sums.
What I've considered is to step down one of the lists for each iteration. This however misses many cases that would have been possible if another list would have been chosen for that step.
An alternative would be a recursive solution, but that would generate many duplicate cases instead.
Is there any known methods that could solve such a problem?
Let we have K lists.
Make min-heap.
a) Push a structure contaning sum of elements from every list (the first ones at this elements) and list of indexes key = Sum(L[i][0]), [ix0=0, ix1=0, ix2=0]
b) Pop the smallest element from the heap, output key (sum) value
c) Construct K new elements from popped one - for every increment corresponding index and update sum
key - L[0][ix0] + L[0][ix0 + 1], [ix0 + 1, ix1, ix2]
key - L[1][ix1] + L[1][ix1 + 1], [ix0, ix1 + 1, ix2]
same for ix2
d) Push them into the heap
e) Repeat from b) until N smallest sums are extracted
A Java implementation of the min heap algorithm with a simple test case:
The algorithm itself is just as described by #MBo.
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
class MinHeapElement {
int sum;
List<Integer> idx;
}
public class SumFromKLists {
public static List<Integer> sumFromKLists(List<List<Integer>> lists, int N) {
List<Integer> ans = new ArrayList<>();
if(N == 0) {
return ans;
}
PriorityQueue<MinHeapElement> minPq = new PriorityQueue<>(new Comparator<MinHeapElement>() {
#Override
public int compare(MinHeapElement e1, MinHeapElement e2) {
return e1.sum - e2.sum;
}
});
MinHeapElement smallest = new MinHeapElement();
smallest.idx = new ArrayList<>();
for(int i = 0; i < lists.size(); i++) {
smallest.sum += lists.get(i).get(0);
smallest.idx.add(0);
}
minPq.add(smallest);
ans.add(smallest.sum);
while(ans.size() < N) {
MinHeapElement curr = minPq.poll();
if(ans.get(ans.size() - 1) != curr.sum) {
ans.add(curr.sum);
}
List<MinHeapElement> candidates = nextPossibleCandidates(lists, curr);
if(candidates.size() == 0) {
break;
}
minPq.addAll(candidates);
}
return ans;
}
private static List<MinHeapElement> nextPossibleCandidates(List<List<Integer>> lists, MinHeapElement minHeapElement) {
List<MinHeapElement> candidates = new ArrayList<>();
for(int i = 0; i < lists.size(); i++) {
List<Integer> currList = lists.get(i);
int newIdx = minHeapElement.idx.get(i) + 1;
while(newIdx < currList.size() && currList.get(newIdx) == currList.get(newIdx - 1)) {
newIdx++;
}
if(newIdx < currList.size()) {
MinHeapElement nextElement = new MinHeapElement();
nextElement.sum = minHeapElement.sum + currList.get(newIdx) - currList.get(minHeapElement.idx.get(i));
nextElement.idx = new ArrayList<>(minHeapElement.idx);
nextElement.idx.set(i, newIdx);
candidates.add(nextElement);
}
}
return candidates;
}
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>();
list1.add(2); list1.add(4); list1.add(7); list1.add(8);
List<Integer> list2 = new ArrayList<>();
list2.add(1); list2.add(3); list2.add(5); list2.add(8);
List<List<Integer>> lists = new ArrayList<>();
lists.add(list1); lists.add(list2);
sumFromKLists(lists, 11);
}
}

Is There Some Stream-Only Way To Determine The Index Of The Max Stream Element?

I have a Stream<Set<Integer>> intSetStream.
I can do this on it...
Set<Integer> theSetWithTheMax = intSetStream.max( (x,y)->{ return Integer.compare( x.size(), y.size() ); } ).get( );
...and I get a hold of the Set<Integer> that has the highest number of Integer elements in it.
That's great. But what I really need to know is, is it the 1st Set in that Stream that's the max? Or is it the 10th Set in the Stream? Or the ith Set? Which one of them has the most elements in it?
So my question is: Is there some way — using the Stream API — that I can determine "It was the ith Set in the Stream of Sets that returned the largest value of them all, for the Set.size( ) call"?
The best solution I can think of, is to iterate over the Stream<Set<Integer>> (using intSetStream.iterator()) and do a hand-rolled max( ) calculation. But I'm hoping to learn a more Stream-y way to go about it; if there is such a thing.
You can do this with a custom collector:
int posOfMax = stream.mapToInt(Set::size)
.collect(() -> new int[] { 0, -1, -1 },
(a,i) -> { int pos = a[0]++; if(i>a[2]) { a[1] = pos; a[2] = i; } },
(a1,a2) -> {
if(a2[2] > a1[2]) { a1[1] = a1[0]+a2[1]; a1[2] = a2[2]; }
a1[0] += a2[0];
})[1];
This is the most lightweight solution. Its logic becomes clearer when we use a dedicated class instead of an array:
int posOfMax = stream.mapToInt(Set::size)
.collect(() -> new Object() { int size = 0, pos = -1, max = -1; },
(o,i) -> { int pos = o.size++; if(i>o.max) { o.pos = pos; o.max = i; } },
(a,b) -> {
if(b.max > a.max) { a.pos = a.size+b.pos; a.max = b.max; }
a.size += b.size;
}).pos;
The state object holds the size, which is simply the number of elements encountered so far, the last encountered max value and its position which we update to the previous value of the size if the current element is bigger than the max value. That’s what the accumulator function (the second argument to collect) does.
In order to support arbitrary evaluation orders, i.e. parallel stream, we have to provide a combiner function (the last argument to collect). It merges the state of two partial evaluation into the first state. If the second state’s max value is bigger, we update the first’s max value and the position, whereas we have to add the first state’s size to the second’s position to reflect the fact that both are partial results. Further, we have to update the size to the sum of both sizes.
One way to do it is to firstly map Stream<Set<Integer>> to a Collection<Integer> where each element is the size of each Set<Integer> and then you can extract what is the largest number of elements given Stream<Set<Integer>> and then get the "index" of this set by finding an index of the largest number in the collection of sizes.
Consider following example:
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class IntSetStreamExample {
public static void main(String[] args) {
final Stream<Set<Integer>> stream = Stream.of(
new HashSet<>(Arrays.asList(1,2,3)),
new HashSet<>(Arrays.asList(1,2)),
new HashSet<>(Arrays.asList(1,2,3,4,5)),
new HashSet<>(Arrays.asList(0)),
new HashSet<>(Arrays.asList(0,1,2,3,4,5)),
new HashSet<>()
);
final List<Integer> result = stream.map(Set::size).collect(Collectors.toList());
System.out.println("List of number of elements in Stream<Set<Integer>>: " + result);
final int max = Collections.max(result);
System.out.println("Largest set contains " + max + " elements");
final int index = result.indexOf(max);
System.out.println("Index of the largest set: " + index);
}
}
The exemplary output may look like this:
List of number of elements in Stream<Set<Integer>>: [3, 2, 5, 1, 6, 0]
Largest set contains 6 elements
Index of the largest set: 4
Streams methods are not designed to be aware of the current element iterated.
So I think that you actual way : find the Set with the max of elements and then iterate on the Sets to find this Set is not bad.
As alternative you could first collect the Stream<Set<Integer>> into a List (to have a way to retrieve the index) and use a SimpleImmutableEntry but it seems really overkill :
Stream<Set<Integer>> intSetStream = ...;
List<Set<Integer>> list = intSetStream.collect(Collectors.toList());
SimpleImmutableEntry<Integer, Set<Integer>> entry =
IntStream.range(0, list.size())
.mapToObj(i -> new SimpleImmutableEntry<>(i, list.get(i)))
.max((x, y) -> {
return Integer.compare(x.getValue()
.size(),
y.getValue()
.size());
})
.get();
Integer index = entry.getKey();
Set<Integer> setWithMaxNbElements = entry.getValue();
Insight provided in #Holzer's custom Collector-based solution (on top of my downright shameless plagiarizing of the source code of IntSummaryStatistics.java), inspired a custom Collector-based solution of my own; that might, in turn, inspire others...
public class IndexOfMaxCollector implements IntConsumer {
private int max = Integer.MIN_VALUE;
private int maxIdx = -1;
private int currIdx = 0;
public void accept( int value ){
if( value > max )
maxIdx = currIdx;
max = Math.max( max, value );
currIdx++;
}
public void combine( IndexOfMaxCollector other ){
if( other.max > max ){
maxIdx = other.maxIdx + currIdx;
max = other.max;
}
currIdx += other.currIdx;
}
public int getMax( ){ return this.max; }
public int getIndexOfMax( ){ return this.maxIdx; }
}
...Using that custom Collector, I could take the intSetStream of my OQ and determine the index of the Set<Integer> that contains the highest number of elements, like this...
int indexOfMax = intSetStream.map( Set::size )
.collect( IndexOfMaxCollector::new,
IndexOfMaxCollector::accept,
IndexOfMaxCollector::combine )
.getIndexOfMax( );
This solution — admittedly not the most "beautiful" — possibly has a teensie bit of an edge over others in both the reusability and understandability stakes.

Odd elements at odd and even elements at even position

This is question asked in one of the interview. Please suggest some view.
Given an array containing all positive integers. You have to arrange elements in such a way that odd elements are at odd position and even elements are at even positions.
PS. No extra space. O(N) solution
Iterate over the even positions until you find an odd number. Iterate over the odd positions until you find and even number (using a different index). Swap the two numbers, and repeat.
Are you allowed to double the size of the array? Otherwise, the question doesn't make sense. Why?!? assume you are given an array full of odd numbers, can you think of any solution then? No, there is not.
So, I assume that you are allowed to double the size of the array. Then for any i, put the i-element ( a(i) ) into the location 2*i or 2*i +1 depending on whether a(i) is even or odd resp.
Two two new Arrays OddArray and EvenArray of same size as that of given array. Traverse through the given array and keep sending all the odd to OddArray and keep at odd positions and even number to EvenArray keeping numbers at even positions.
The efficiency will be O(n) and extra memory will be 2n where n is the size of original array.
list1 = [5, 7, 6, 8, 10, 3, 4, 9, 2, 1, 12]
odd_list = []
even_list = []
for i in range(len(list1)):
if((list1[i] % 2) == 0):
even_list.append(list1[i])
else:
odd_list.append(list1[i])
print(list1)
j = 0
k = 0
for i in range(0, len(list1)):
if((i % 2 == 0) and (j < len(odd_list))):
list1[i] = odd_list[j]
j += 1
elif(k < len(even_list)):
list1[i] = even_list[k]
k += 1
print(list1)
//Putting even number on even position and odd number on odd position
package com.learnJava;
public class ArrangeArray {
private int [] array={2,5,7,8,1,6,9};
private int len=array.length;
public static void main(String [] args)
{
ArrangeArray a=new ArrangeArray();
a.print();
a.arrange();
a.print();
}
public void print()
{
for(int i=0;i<array.length;i++)
{
System.out.print(array[i] + " ");
}
System.out.println();
}
public void arrange()
{
int oddinx=1;
int evenidx=0;
while(true)
{
while(evenidx<len && array[evenidx]%2==0)
{
evenidx+=2;
}
while(oddinx<len && array[oddinx]%2==1)
{
oddinx+=2;
}
if (evenidx < len && oddinx < len)
swap (evenidx, oddinx);
else
break;
}
}
public void swap(int a,int b)
{
int tmp=array[b];
array[b]=array[a];
array[a]=tmp;
}
}

Resources