Concurrent modification Exception while iterating over ArrayList - java

The sort method results in a concurrent modification error when i use temp = iterator.next(). Can you please help me resolve the concurrent modification error.
I gave the code for the entire class but I'm only trying complete the sort method. Thanks in advance for your help.
I have to sort all the the arrays in the arraylist.
package HashSet;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ListIterator;
import java.util.Scanner;
public class PhoneBook {
int capacity = 10;
private ArrayList<PhoneBookEntry>[] buckets;
public PhoneBook() {
this(10);
load();
}
public PhoneBook(int size) {
capacity = size;
buckets = new ArrayList[size];
for (int i = 0; i < buckets.length; i++)
buckets[i] = new ArrayList<PhoneBookEntry>();
}
public int getSize() {
int tot = 0;
for (ArrayList<PhoneBookEntry> x : buckets)
tot += x.size();
return tot;
}
public boolean add(PhoneBookEntry entry) {
if (contains(entry))
return false;
int x = Math.abs(entry.hashCode());
buckets[x % buckets.length].add(entry);
return true;
}
public void load() {
InputStream is = getClass().getClassLoader().getResourceAsStream(
"phone.txt");
Scanner scan = new Scanner(is);
while (scan.hasNext())
add(new PhoneBookEntry(scan.next(), scan.nextInt()));
scan.close();
}
public void bucketSize() {
for (int i = 0; i < buckets.length; i++)
System.out.println(i + " " + buckets[i].size());
}
public boolean contains(PhoneBookEntry word) {
int x = Math.abs(word.hashCode());
return buckets[x % buckets.length].contains(word);
}
public int getCapacity() {
return capacity;
}
public int getLongestList() {
int numb = 0;
for (ArrayList<PhoneBookEntry> x : buckets)
if (x.size() > numb)
numb = x.size();
return numb;
}
public void display() {
for (ArrayList<PhoneBookEntry> x : buckets)
System.out.println(x);
}
public int getNumberOfNulls() {
int numb = 0;
for (ArrayList<PhoneBookEntry> x : buckets)
if (x.size() == 0)
numb++;
return numb;
}
public String lookup(String name) {
String numb = name + "'s number not found";
for (ArrayList<PhoneBookEntry> x : buckets)
for (int i = 0; i < x.size(); i++)
if (x.get(i).getN().equals(name))
numb = name + "'s" + " number is " + x.get(i).getNr();
return numb;
}
public int internalLookUp(String name) {
int numb = 0;
for (ArrayList<PhoneBookEntry> x : buckets)
for (int i = 0; i < x.size(); i++)
if (x.get(i).getN().equals(name))
numb = x.get(i).getNr();
return numb;
}
public void sort() {
String temp = "";
ArrayList<String> list = new ArrayList<String>();
ListIterator<String> iterator = list.listIterator();
final ArrayList<PhoneBookEntry>[] data = buckets.clone();
for (ArrayList<PhoneBookEntry> x : buckets) {
for (int i = 0; i < x.size(); i++) {
list.add(x.get(i).getN());
}
Collections.sort(list);
for (int b = 0; b < x.size(); b++) {
temp = iterator.next(); //error line
x.get(b).setN(temp);
x.get(b).setNr(internalLookUp(temp));
}
}
}
public static void main(String[] args) {
PhoneBook phone = new PhoneBook();
phone.display();
System.out.println();
System.out.println("Capacity is " + phone.getCapacity());
System.out.println();
System.out.println("Size is " + phone.getSize());
System.out.println();
System.out.println("Get longest list " + phone.getLongestList());
System.out.println();
System.out.println("Number of Nulls " + phone.getNumberOfNulls());
System.out.println();
System.out.println(phone.lookup("Fish"));
phone.sort();
}
}

It looks like your problem is that you're creating an iterator for a list, then modifying the list (adding + sorting), then attempting to use the iterator.
If you instead created the iterator after this, it should work.
eg.
for (ArrayList<PhoneBookEntry> x : buckets) {
for (int i = 0; i < x.size(); i++) {
list.add(x.get(i).getN());
}
Collections.sort(list);
ListIterator<String> iterator = list.listIterator(); // Iterator created here
for (int b = 0; b < x.size(); b++) {
temp = iterator.next(); //error line
x.get(b).setN(temp);
x.get(b).setNr(internalLookUp(temp));
}

The bug is that you iterate over list while you add to it. you should not do that.

Here is the javadoc for the ConcurrentModificationException.
http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html
if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
As other posters have said, you should do all sorting and adding before or after using your iterator. You can remove an element during iteration, but you must use Iterator.remove() to prevent getting the same exception again.

Related

Why am I getting this IndexOutOfBoundsException error?

hi so im currently trying to get past this error in my code, if anyone could explain where I went wrong, would be greatly appreciated.
public class Lab07vst100SD
{
public static void main (String[] args)
{
System.out.println();
int size = 10;
School bhs = new School(size);
System.out.println(bhs);
System.out.println(bhs.linearSearch("Meg"));
System.out.println(bhs.linearSearch("Sid"));
System.out.println();
bhs.selectionSort();
System.out.println(bhs);
System.out.println(bhs.binarySearch("Meg"));
System.out.println(bhs.binarySearch("Sid"));
System.out.println();
}
}
class School
{
private ArrayList<Student> students;
private int size;
public School (int s)
{
students = new ArrayList<Student>();
size = s;
}
public void addData()
{
String [] name = {"Tom","Ann","Bob","Jan","Joe","Sue","Jay","Meg","Art","Deb"};
int[] age = {21,34,18,45,27,19,30,38,40,35};
double[] gpa = {1.685,3.875,2.5,4.0,2.975,3.225,3.65,2.0,3.999,2.125};
for(int i = 0; i < name.length; i++)
{
students.add(new Student(name[i], age[i], gpa[i]));
}
size = students.size();
}
public void selectionSort ()
{
for(int h = 0; h < students.size(); h++)
{
int index = h;
Student least = students.get(h);
for (int t = 0; t < size; t++) {
if (students.get(t).equals(least)) {
least = students.get(t);
index = t;
}
Student temp = students.get(h);
students.set(h, least);
students.set(t, temp);
}
}
}
public int linearSearch (String str)
{
// new arraylist
ArrayList<String> names = new ArrayList<String>();
for (int q = 0; q < size; q++) {
names.add(students.get(q).getName());
}
//comparison
for (int y = 0; y < size; y++) {
if (names.get(y).equals(str))
return y;
}
return -1;
};
public int binarySearch (String str) {
// new arraylist and variables
ArrayList<String> names = new ArrayList<String>();
Boolean found = false;
int lo = 0;
int hi = size;
int mid = (lo + hi) / 2;
//for loop for to transverse the array.
for (int m = 0; m < size; m++) {
names.add(students.get(m).getName());
}
while (lo <= hi && !found) {
if (names.get(mid).compareTo(str) == 0)
{
found = true;
return mid;
}
if (names.get(mid).compareTo(str) < 0) {
lo = mid + 1;
mid = (lo + hi) / 2;
}
else {
hi = mid -1;
mid = (lo + hi) / 2;
}
}
if (found)
return mid;
else
return -1;
}
public String toString() {
String temp = "";
for (int s = 0; s < students.size(); s++) {
temp += students.get(s);
}
return temp;
}
}
also, I should mention this uses the student class.
here
public class Student
{
private String name;
private int age;
private double gpa;
public Student (String n, int a, double g)
{
name = n;
age = a;
gpa = g;
}
public String getName() {
return name; }
public int getAge() {
return age; }
public double getGPA() {
return gpa; }
public String toString()
{
String temp = name + " " + age + " " + gpa + "\n";
return temp;
}
}
the school class calls to the student class.
this is what comes back.
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:359)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at School.linearSearch(Lab07vst100SD.java:78)
at Lab07vst100SD.main(Lab07vst100SD.java:16)
I'm completely confused on why this is happening, I think it may have to do with the ArrayList, other than that, I'm not sure.
please help, and thank you
p.s. I'm new so please bear with my horrible format.
You need call addData:
public static void main (String[] args)
{
System.out.println();
int size = 10;
School bhs = new School(size);
bhs.addData(); // here
System.out.println(bhs);
System.out.println(bhs.linearSearch("Meg"));
System.out.println(bhs.linearSearch("Sid"));
System.out.println();
bhs.selectionSort();
System.out.println(bhs);
System.out.println(bhs.binarySearch("Meg"));
System.out.println(bhs.binarySearch("Sid"));
System.out.println();
}
...
class School
{
private ArrayList<Student> students;
private int size;
public School (int s)
{
students = new ArrayList<Student>(); // Here, it can throw IndexOutOfBoundsException
size = s;
}
...
Please see https://www.tutorialspoint.com/java/util/arraylist_add_index.htm
The capacity of ArrayList must be initialized before ArrayList.add method
.

Sort objects highest-lowest in Java with ArrayList?

Write a method to return the Toy that occurs in the list most frequent and another method to sort the toys by count.
This is my code
import java.util.ArrayList;
public class ToyStore {
private ArrayList<Toy> toyList;
public ToyStore() {
}
public void loadToys(String toys) {
toyList = new ArrayList<Toy>();
for (String item : toys.split(" ")) {
Toy t = getThatToy(item);
if (t == null) {
toyList.add(new Toy(item));
} else {
t.setCount(t.getCount() + 1);
}
}
}
public Toy getThatToy(String nm) {
for (Toy item : toyList) {
if (item.getName().equals(nm)) {
return item;
}
}
return null;
}
public String getMostFrequentToy() {
int position = 0;
int maximum = Integer.MIN_VALUE;
for (int i = toyList.size() - 1; i >= 0; i--) {
if (toyList.get(i).getCount() > maximum)
maximum = toyList.get(i).getCount();
position = i;
}
return toyList.get(position).getName();
}
public void sortToysByCount() {
ArrayList<Toy> t = new ArrayList<Toy>();
int count = 0;
int size = toyList.size();
for (int i = size; i > 0; i--) {
t.add(new Toy(getMostFrequentToy()));
t.get(count).setCount(getThatToy(getMostFrequentToy()).getCount());
toyList.remove(getThatToy(getMostFrequentToy()));
count++;
}
toyList = t;
}
public String toString() {
return toyList + "" + "\n" + "max == " + getMostFrequentToy();
}
}
Here is the method I care about
public void sortToysByCount() {
ArrayList<Toy> t = new ArrayList<Toy>();
int count = 0;
int size = toyList.size();
for (int i = size; i > 0; i--) {
t.add(new Toy(getMostFrequentToy()));
t.get(count).setCount(getThatToy(getMostFrequentToy()).getCount());
toyList.remove(getThatToy(getMostFrequentToy()));
count++;
}
toyList = t;
}
Here is my output
[sorry 4, bat 1, train 2, teddy 2, ball 2]
Here is what I want
[sorry 4, train 2, teddy 2, ball 2, bat 1];
What is wrong in my code? How do I do it?
The problem is in your getMostFrequentToy() method:
Replace
if (toyList.get(i).getCount() > maximum)
maximum = toyList.get(i).getCount();
position = i;
with
if (toyList.get(i).getCount() > maximum) {
maximum = toyList.get(i).getCount();
position = i;
}
because you want to get the position that corresponds to that maximum.
You have some in-efficiencies in your code. Every single time you call getMostFrequentToy(), you are iterating over the whole list, which may be fine as you are constantly removing objects, but you really don't need to make new Toy objects for those that already exist in the list.
So, this is "better", but still not sure you need to getThatToy when you should already know which one is the most frequent.
String frequent;
for (int i = size; i > 0; i--) {
frequent = getMostFrequentToy();
t.add(new Toy(frequent));
t.get(count).setCount(getThatToy(frequent).getCount());
toyList.remove(getThatToy(frequent));
count++;
}
Anyways, I think the instructions asked you to return the Toy object, not its name.
It's quite simple, just keep track of the max count.
public Toy getMostFrequentToy() {
Toy mostFrequent = null;
int maximum = Integer.MIN_VALUE;
for (Toy t : toyList) {
if (t.getCount() > maximum)
mostFrequent = t;
}
return t;
}
Now, the above code can become
public void sortToysByCount() {
ArrayList<Toy> t = new ArrayList<Toy>();
// int count = 0;
int size = toyList.size();
Toy frequent;
for (int i = size; i > 0; i--) {
frequent = getMostFrequentToy();
t.add(frequent);
// t.get(count).setCount(frequent.getCount()); // Not sure about this
toyList.remove(frequent);
// count++;
}
toyList.clear();
toyList.addAll(t);
}
Realistically, though, when you want to sort, you really should see how to create a Comparator for your Toy objects.

Implementing merge sort in java 7

I have a problem with implementation of merge sort in java. I am looking for the error almost week unfortunately without result. ArrayList at the entrance is the same as the output.
import java.util.ArrayList;
import java.util.Scanner;
public class MergeSort
{
private ArrayList<Integer> basicArrayList = new ArrayList<Integer>();
ArrayList<Integer> arrayListA = new ArrayList<Integer>();
ArrayList<Integer> arrayListB = new ArrayList<Integer>();
Scanner input = new Scanner(System.in);
private int firstIndexOfArrayList = 0;
private int lastIndexOfArrayListA;
private int lastIndexOfArrayListB;
public void Scal(ArrayList<Integer> basicArrayList, int p, int q, int r) {
this.firstIndexOfArrayList = p;
this.lastIndexOfArrayListA = q;
this.lastIndexOfArrayListB = r;
int numberOfElementsArrayListA = lastIndexOfArrayListA
- firstIndexOfArrayList + 1;
int numberOfElementsArrayListB = lastIndexOfArrayListB
- lastIndexOfArrayListA;
for (int i = 0; i < numberOfElementsArrayListA; i++) {
arrayListA.set(i, basicArrayList.get(firstIndexOfArrayList + i));
}
for (int j = 0; j < numberOfElementsArrayListB; j++) {
arrayListB.set(j, basicArrayList.get(lastIndexOfArrayListA + j));
}
arrayListA.add(Integer.MAX_VALUE);
arrayListB.add(Integer.MAX_VALUE);
int i = 0;
int j = 0;
for (int k = firstIndexOfArrayList; k <= lastIndexOfArrayListB; k++) {
if (arrayListA.get(i) <= arrayListB.get(j)) {
basicArrayList.set(k, arrayListA.get(i));
i = i + 1;
} else {
basicArrayList.set(k, arrayListB.get(j));
j = j + 1;
}
}
}
public void MergeSort(ArrayList basicArrayList, int p, int r) {
this.firstIndexOfArrayList = p;
this.lastIndexOfArrayListB = r;
if (firstIndexOfArrayList < lastIndexOfArrayListB) {
int lastIndexOfArrayListA = (firstIndexOfArrayList + lastIndexOfArrayListB) / 2;
MergeSort(basicArrayList, firstIndexOfArrayList,
lastIndexOfArrayListA);
MergeSort(basicArrayList, lastIndexOfArrayListA + 1,
lastIndexOfArrayListB);
Scal(basicArrayList, firstIndexOfArrayList,
lastIndexOfArrayListA,
lastIndexOfArrayListB);
}
}
public void setSize() {
System.out.println("Enter the number of elements to sort: ");
this.lastIndexOfArrayListB = input.nextInt();
}
public int getSize() {
return lastIndexOfArrayListB;
}
public void setData() {
System.out.println("Enter the numbers: ");
for (int i = 0; i < lastIndexOfArrayListB; i++) {
int number;
number = input.nextInt();
basicArrayList.add(number);
}
}
public void getTable() {
System.out.println(basicArrayList.toString());
}
public static void main(String[] args) {
MergeSort output = new MergeSort();
output.setSize();
output.setData();
output.MergeSort(output.basicArrayList,
output.firstIndexOfArrayList, (output.getSize() - 1));
output.getTable();
}
}
In terms of fixing your code I had a crack at it and as far as I can tell this seems to work. To do this a lot of your code had to be changed but it does now sort all Integers properly
import java.util.ArrayList;
import java.util.Scanner;
public class MergeSort
{
private ArrayList<Integer> basicArrayList = new ArrayList<Integer>();
Scanner input = new Scanner(System.in);
private int numbersToSort;
public void doMergeSort(int firstIndexOfArrayList,int lastIndexOfArrayListB, ArrayList<Integer> arrayList)
{
if(firstIndexOfArrayList<lastIndexOfArrayListB && (lastIndexOfArrayListB-firstIndexOfArrayList)>=1)
{
int mid = (lastIndexOfArrayListB + firstIndexOfArrayList)/2;
doMergeSort(firstIndexOfArrayList, mid, arrayList);
doMergeSort(mid+1, lastIndexOfArrayListB, arrayList);
Scal(firstIndexOfArrayList,mid,lastIndexOfArrayListB, arrayList);
}
}
public void Scal(int firstIndexOfArrayList,int lastIndexOfArrayListA,int lastIndexOfArrayListB, ArrayList<Integer> arrayList)
{
ArrayList<Integer> mergedSortedArray = new ArrayList<Integer>();
int leftIndex = firstIndexOfArrayList;
int rightIndex = lastIndexOfArrayListA+1;
while(leftIndex<=lastIndexOfArrayListA && rightIndex<=lastIndexOfArrayListB)
{
if(arrayList.get(leftIndex)<=arrayList.get(rightIndex))
{
mergedSortedArray.add(arrayList.get(leftIndex));
leftIndex++;
}
else
{
mergedSortedArray.add(arrayList.get(rightIndex));
rightIndex++;
}
}
while(leftIndex<=lastIndexOfArrayListA)
{
mergedSortedArray.add(arrayList.get(leftIndex));
leftIndex++;
}
while(rightIndex<=lastIndexOfArrayListB)
{
mergedSortedArray.add(arrayList.get(rightIndex));
rightIndex++;
}
int i = 0;
int j = firstIndexOfArrayList;
while(i<mergedSortedArray.size())
{
arrayList.set(j, mergedSortedArray.get(i++));
j++;
}
}
public void setSize()
{
System.out.println("Enter the number of elements to sort: ");
this.numbersToSort = input.nextInt();
}
public int getSize()
{
return numbersToSort;
}
public void setData()
{
System.out.println("Enter the numbers: ");
for (int i = 0; i < numbersToSort; i++)
{
int number;
number = input.nextInt();
basicArrayList.add(number);
}
}
public void getTable()
{
System.out.println(basicArrayList.toString());
}
public void runSort(ArrayList<Integer> arrayList)
{
doMergeSort(0, this.numbersToSort-1, arrayList);
}
public static void main(String[] args)
{
MergeSort output = new MergeSort();
output.setSize();
output.setData();
output.runSort(output.basicArrayList);
output.getTable();
}
}
Try this code. The following code takes an ArrayList input and outputs an ArrayList as well so it still works along the same basis of your code. The actual sort is handled in a different class MergeSort and is passes into ForMergeSort. Hope this helps
MergeSort.java
public class MergeSort
{
private int[] array;
private int[] tempMergArr;
private int length;
public void sort(int[] inputArr)
{
}
public int[] getSortedArray(int[] inputArr)
{
this.array = inputArr;
this.length = inputArr.length;
this.tempMergArr = new int[length];
doMergeSort(0, length - 1);
for(int i=0;i<length;i++)
{
int correctNumber = i+1;
System.out.println("Value "+correctNumber+" of the sorted array which was sorted via the Merge Sort is: "+inputArr[i]);
}
return inputArr;
}
private void doMergeSort(int lowerIndex, int higherIndex)
{
if (lowerIndex < higherIndex)
{
int middle = lowerIndex + (higherIndex - lowerIndex) / 2;
doMergeSort(lowerIndex, middle);
doMergeSort(middle + 1, higherIndex);
mergeParts(lowerIndex, middle, higherIndex);
}
}
private void mergeParts(int lowerIndex, int middle, int higherIndex)
{
for (int i = lowerIndex; i <= higherIndex; i++)
{
tempMergArr[i] = array[i];
}
int i = lowerIndex;
int j = middle + 1;
int k = lowerIndex;
while (i <= middle && j <= higherIndex)
{
if (tempMergArr[i] <= tempMergArr[j])
{
array[k] = tempMergArr[i];
i++;
}
else
{
array[k] = tempMergArr[j];
j++;
}
k++;
}
while (i <= middle)
{
array[k] = tempMergArr[i];
k++;
i++;
}
}
}
ForMergeSort.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class ForMergeSort
{
ArrayList<Integer> arrayList = new ArrayList<Integer>();
ArrayList<Integer> sortedArrayList = new ArrayList<Integer>();
MergeSort mS = new MergeSort();
public void buildArrayList()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter the number of elements to sort: ");
int toSort = input.nextInt();
System.out.println("Enter the numbers: ");
for(int i =0; i<toSort; i++)
{
int number = input.nextInt();
arrayList.add(number);
}
}
public void runMergeSort(ArrayList<Integer> arrayList)
{
int[] arrayOfValues = new int[arrayList.size()];
int i = 0;
for(int a:arrayList)
{
arrayOfValues[i] = a;
i++;
}
MergeSort mS = new MergeSort();
for(int intOfArray:mS.getSortedArray(arrayOfValues))
{
sortedArrayList.add(intOfArray);
}
System.out.println(sortedArrayList.toString());
}
public static void main(String[] args)
{
ForMergeSort fMS = new ForMergeSort();
fMS.buildArrayList();
fMS.runMergeSort(fMS.arrayList);
}
}

Mean, Median, and Mode - Newb - Java

We had a lab in Comsci I couldn't figure out. I did a lot of research on this site and others for help but they were over my head. What threw me off were the arrays. Anyway, thanks in advance. I already got my grade, just want to know how to do this :D
PS: I got mean, I just couldn't find the even numbered median and by mode I just gave up.
import java.util.Arrays;
import java.util.Random;
public class TextLab06st
{
public static void main(String args[])
{
System.out.println("\nTextLab06\n");
System.out.print("Enter the quantity of random numbers ===>> ");
int listSize = Expo.enterInt();
System.out.println();
Statistics intList = new Statistics(listSize);
intList.randomize();
intList.computeMean();
intList.computeMedian();
intList.computeMode();
intList.displayStats();
System.out.println();
}
}
class Statistics
{
private int list[]; // the actual array of integers
private int size; // user-entered number of integers in the array
private double mean;
private double median;
private int mode;
public Statistics(int s)
{
size = s;
list = new int[size];
mean = median = mode = 0;
}
public void randomize()
{
Random rand = new Random(12345);
for (int k = 0; k < size; k++)
list[k] = rand.nextInt(31) + 1; // range of 1..31
}
public void computeMean()
{
double total=0;
for (int f = 0; f < size; f++)
{
total = total + list[f];
}
mean = total / size;
}
public void computeMedian()
{
int total2 = 0;
Arrays.sort(list);
if (size / 2 == 1)
{
// total2 =
}
else
{
total2 = size / 2;
median = list[total2];
}
}
public void computeMode()
{
// precondition: The list array has exactly 1 mode.
}
public void displayStats()
{
System.out.println(Arrays.toString(list));
System.out.println();
System.out.println("Mean: " + mean);
System.out.println("Median: " + median);
System.out.println("Mode: " + mode);
}
}
Here are two implementations for your median() and mode() methods:
public void computeMedian() {
Arrays.sort(list);
if ( (list.size & 1) == 0 ) {
// even: take the average of the two middle elements
median = (list[(size/2)-1] + list[(size/2)]) / 2;
} else {
// odd: take the middle element
median = list[size/2];
}
}
public void computeMode() {
// precondition: The list array has exactly 1 mode.
Map<Integer, Integer> values = new HashMap<Integer, Integer>();
for (int i=0; i < list.size; ++i) {
if (values.get(list[i]) == null) {
values.put(list[i], 1);
} else {
values.put(list[i], values.get(list[i])+1);
}
}
int greatestTotal = 0;
// iterate over the Map and find element with greatest occurrence
Iterator it = values.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
if (pair.getValue() > greatestTotal) {
mode = pair.getKey();
greatestTotal = pair.getValue();
}
it.remove();
}
}

Given a target sum, find if there is a pair of element in the given array which sums up to it

import java.util.HashMap;
public class target
{
public static void hash(int []a,int sum)
{
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
int i;
for (i = 0; i < a.length; ++i)
map.put(a[i], sum-a[i]);
for (i = 0; i < a.length; ++i)
if(map.containsValue(a[i]) && map.get(a[i])!=null)
{
System.out.println("("+a[i]+","+map.get(a[i])+")");
map.remove(a[i]);
}
}
public static void main(String[] args)
{
int []a={1, 2, 13, 34, 9, 3, 23, 45, 8, 7, 8, 3, 2};
hash(a,11);
}
}
I want to know if there is a better and more efficient solution that the above one. Complexity of this is n. Can I do better?
Your implementation misses duplicated pairs.
You could
sort the array
iterate from the start and for each element
calculate the required complement (sum - element)
do a reverse binary search (from the end of the sorted array) looking for that precise value
if found, remove both
It boils down to the observation that, with elements sorted:
n1 < n2 < n3 < n4 < n5 < n6
the most likely pairs are coming symmetrically from both ends to the middle. Now, the worst case is still bad, but at least you don't have the hashtable overhead
As I commented, your sollution is not O(N), because the containsValue make a search of all values stored at the HashMap. To solve it, I made a different approach using your solution:
public static void newVersion(int[] a, int sum){
HashMap<Integer, Boolean> map = new HashMap<Integer, Boolean>();
for (int i= 0; i< a.length; i++) {
map.put(sum - a[i], true);
}
for (int i = 0; i < a.length; i++) {
if (map.containsKey(a[i]) && map.get(a[i])) {
System.out.println("("+(sum-a[i])+","+a[i]+")");
map.put(a[i], false);
map.put(sum-a[i], false);
}
}
}
At the first step, it stores the "complement value" of each integer and at the second step it checks if the complement exists. If it exists, mark both pair as used.
This complexity is:
* O(N) for the first looping
* O(N) * (O(1) + O(1)) for the second loop and the containsValue and get.
* Finally: O(N) + O(N) .:. O(N) solution,
I have the following solution for this problem. The time complexity should be O(N) because the HashMap operations put, get and keySet are O(1).
import java.util.HashMap;
import java.util.Map;
/**
* Find a pair of numbers in an array given a target sum
*
*
*/
public class FindNums {
public static void findSumsForTarget(int[] input, int target)
{
// just print it instead of returning
Map<Integer, String> myMap = populateMap(input);
// iterate over key set
for (Integer currKey : myMap.keySet()) {
// find the diff
Integer diff = target - currKey;
// check if diff exists in the map
String diffMapValue = myMap.get(diff);
if(diffMapValue!=null)
{
// sum exists
String output = "Sum of parts for target " + target + " are " + currKey + " and " + diff;
System.out.println(output);
return; // exit; we're done - unless we wanted all the possible pairs and permutations
}
// else
// keep looking
}
System.out.println("No matches found!");
}
private static Map<Integer, String> populateMap(int[] input)
{
Map<Integer,String> myMap = new HashMap<Integer,String>();
for (int i = 0; i < input.length; i++) {
String currInputVal = myMap.get(input[i]);
if(currInputVal!=null) // value already exists
{
// append current index location to value
currInputVal = currInputVal + ", " + i;
// do a put with the updated value
myMap.put(input[i], currInputVal);
}
else
{
myMap.put(input[i], Integer.toString(i)); // first argument is autoboxed to Integer class
}
}
return myMap;
}
// test it out!
public static void main(String[] args)
{
int[] input1 = {2,3,8,12,1,4,7,3,8,22};
int[] input2 = {1,2,3,4,5,6,7,8,9,10};
int[] input3 = {2,-3,8,12,1,4,7,3,8,22};
int target1 = 19;
int target2 = 16;
// test
FindNums.findSumsForTarget(input1, target1);
FindNums.findSumsForTarget(input1, -1);
FindNums.findSumsForTarget(input2, target2);
FindNums.findSumsForTarget(input3, target1);
}
}
import java.util.*;
import java.io.*;
class hashsum
{
public static void main(String arg[])throws IOException
{
HashMap h1=new HashMap();
h1.put("1st",new Integer(10));
h1.put("2nd",new Integer(24));
h1.put("3rd",new Integer(12));
h1.put("4th",new Integer(9));
h1.put("5th",new Integer(43));
h1.put("6th",new Integer(13));
h1.put("7th",new Integer(5));
h1.put("8th",new Integer(32));
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter no.");
int no=Integer.parseInt(br.readLine());
Iterator i=h1.entrySet().iterator();
boolean flag=false;
while(i.hasNext())
{
Map.Entry e1=(Map.Entry)i.next();
Integer n1=(Integer)e1.getValue();
Iterator j=h1.entrySet().iterator();
while(j.hasNext())
{
Map.Entry e2=(Map.Entry)j.next();
Integer n2=(Integer)e2.getValue();
if(no==(n1+n2))
{
System.out.println("Pair of elements:"+n1 +" "+n2);
flag=true;
}
}
}
if(flag==false)
System.out.println("No pairs");
}
}
public static void hash1(int[] a, int num) {
Arrays.sort(a);
// printArray(a);
int top = 0;
int bott = a.length - 1;
while (top < bott) {
while (a[bott] > num)
bott--;
int sum = a[top] + a[bott];
if (sum == num) {
System.out.println("Pair " + a[top] + " " + a[bott]);
top++;
bott--;
}
if (sum < num)
top++;
if (sum > num)
bott--;
}
}
Solution: O(n) time and O(log(n)) space.
public static boolean array_find(Integer[] a, int X)
{
boolean[] b = new boolean[X];
int i;
for (i=0;i<a.length;i++){
int temp = X-a[i];
if(temp >= 0 && temp < X) //make sure you are in the bound or b
b[temp]=true;
}
for (i=0;i<a.length;i++)
if(a[i]<X && b[a[i]]) return true;
return false;
}
Recursively to find the subset whose sum is the targeted sum from given array.
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static Set<List<Integer>> set = new HashSet<>();
public static void main(String[] args) {
int[] biggerArray = {1, 2, 1, 1};
int targetedSum = 3;
findSubset(biggerArray, targetedSum);
}
public static void findSubset(int[] biggerArray, int targetedSum) {
for (int i = 0; i < biggerArray.length; i++) {
List<Integer> subset = new ArrayList<>();
if (biggerArray[i] > targetedSum)
continue;
else
subset.add(biggerArray[i]);
if (i + 1 < biggerArray.length)
find(subset, i, biggerArray, targetedSum, i);
}
System.out.println(set);
}
public static List<Integer> find(List<Integer> subset, int startIndex, final int[] biggerArray, final int targetedSum, final int skipIndex) {
if (skipIndex == startIndex) {
find(subset, startIndex + 1, biggerArray, targetedSum, skipIndex);
return null;
}
int subsetSum = findSumOfList(subset);
int remainedSum = targetedSum - subsetSum;
int i = startIndex;
if (remainedSum == 0) {
set.add(subset);
return null;
}
if ((startIndex < biggerArray.length) && (biggerArray[startIndex] == remainedSum)) {
List<Integer> temp = new ArrayList<Integer>(subset);
temp.add(biggerArray[i]);
set.add(temp);
}
else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] < remainedSum)) {
while (i + 1 <= biggerArray.length) {
List<Integer> temp = new ArrayList<Integer>(subset);
if (i != skipIndex) {
temp.add(biggerArray[i]);
find(temp, ++i, biggerArray, targetedSum, skipIndex);
}
else {
i = i + 1;
}
}
}
else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] > remainedSum)) {
find(subset, ++i, biggerArray, targetedSum, skipIndex);
}
return null;
}
public static int findSumOfList(List<Integer> list) {
int i = 0;
for (int j : list) {
i = i + j;
}
return i;
}
}
We need not have two for loops. The match can be detected in the same loop while populating the map it self.
public static void matchingTargetSumPair(int[] input, int target){
Map<Integer, Integer> targetMap = new HashMap<Integer, Integer>();
for(int i=0; i<input.length; i++){
targetMap.put(input[i],target - input[i]);
if(targetMap.containsKey(target - input[i])){
System.out.println("Mathcing Pair: "+(target - input[i])+" , "+input[i]);
}
}
}
public static void main(String[] args) {
int[] targetInput = {1,2,4,5,8,12};
int target = 9;
matchingTargetSumPair(targetInput, target);
}
We can easily find if any pair exists while populating the array itself. Use a hashmap and for every input element, check if sum-input difference element exists in the hashmap or not.
import java.util.*;
class findElementPairSum{
public static void main(String[] args){
Map<Integer, Integer> hm = new HashMap<Integer, Integer>();
Scanner sc = new Scanner(System.in);
System.out.println("Enter the sum key: ");
int sum=sc.nextInt();
for(int i=0; i<10; i++){
int x = sc.nextInt();
if(!hm.containsKey(sum-x)){
hm.put(x, 1);
} else {
System.out.println("Array contains two elements with sum equals to: "+sum);
break;
}
}
}
}

Categories

Resources