Comparing the contents of in two linked lists - java

This is my first time working with linked lists and I've created both of my lists from two separate files and tokenized the data.
Now I need to compare the data and look for similarities, by that I mean the same data.
Such has list 1: 1, 3, dog and list 2: 1, dog, cat. Both have 1 and dog.
I am unsure how to approach this, and would love some tips, input, or hints.

The code which compares two Lists only in case when their elements are comparable (i.e. implements Comparable interface).
This is parametrized so you can provide any type of List element which implements Comparable (<T extends Comparable<T>>)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ComparatorTest {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>(Arrays.asList(new Integer[]{1, 2, 3, 6, 7}));
List<Integer> list2 = new ArrayList<>(Arrays.asList(new Integer[]{1, 2, 3, 6}));
final int result = new ComparatorTest().compareTo(list1, list2);
System.out.println("result = " + result);
}
<T extends Comparable<T>> int compareTo(List<T> list1, List<T> list2) {
int minLength = Math.min(list1.size(), list2.size());
for (int i = 0; i < minLength; i++) {
final int compareValue = list1.get(i).compareTo(list2.get(i));
if (compareValue != 0) {
return compareValue; // They are already not equal
}
}
if (list1.size() == list2.size()) {
return 0; // They are equal
} else if (list1.size() < list2.size()) {
return -1; // list 1 is smaller
} else {
return 1;
}
}
}

Related

Java Recursion Pass by Reference in ArrayList

I am working on a problem to find which all combinations of integer in a given list can sum up to a given number.
public class SumProblem {
/*
* Input 2-2-3-7
* Output 2+2+3 and 7
*/
public static ArrayList<ArrayList<Integer>> find(ArrayList<Integer> input, int requiredSum) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
find(result, requiredSum, 0, new ArrayList<>(), 0, input);
return result;
}
public static void find(ArrayList<ArrayList<Integer>> result , int requiredSum , int currentSum, ArrayList<Integer> partialResult, int i, ArrayList<Integer> input) {
if (currentSum == requiredSum ) {
ArrayList<Integer> temp = new ArrayList<>();
temp = (ArrayList<Integer>) partialResult.clone();
result.add(temp);
return;
}
if (i >= input.size()) {
return;
}
find(result, requiredSum, currentSum , partialResult, i +1, input );
partialResult.add(input.get(i));
find(result, requiredSum, currentSum + input.get(i) , partialResult, i +1, input );
}
public static void main(String[] args) {
ArrayList<Integer> input = new ArrayList<>();
input.add(2);
input.add(1);
input.add(3);
ArrayList<ArrayList<Integer>> output = find(input, 3);
System.out.println(output.toString());
}
}
I have written code below.
I am facing one problem. In the below line of code, it is adding up all the numbers i traverse even if i create new ArrayList object and assign it to partialResult.
partialResult.add(input.get(i));
Could anyone suggest the solution ?
You have two recursive calls in this dynamic programming solution to the problem. One is supposed to not include the current value in the result, the other does.
You need to make a defensive copy of partialResult, otherwise both recursive calls are going to have a reference to the same list. A list is a mutable object. If both calls get a reference to the same list object, then when you add something to it anywhere, both of them will see the modified list.
The easiest way to make a defensive copy of a list is just to write:
new ArrayList<>(partialResult)
Here is a working version of the program:
import java.util.*;
public class SumProblem {
public static List<List<Integer>> find(List<Integer> input, int requiredSum) {
List<List<Integer>> result = new ArrayList<>();
find(result, requiredSum, 0, new ArrayList<>(), 0, input);
return result;
}
public static void find(List<List<Integer>> result, int requiredSum, int currentSum,
List<Integer> partialResult, int i, List<Integer> input) {
if (currentSum == requiredSum) {
result.add(new ArrayList<>(partialResult)); // add a copy of the list
return;
}
if (i >= input.size()) {
return;
}
// make defensive copies in the recursive calls
find(result, requiredSum, currentSum, new ArrayList<>(partialResult), i + 1, input);
partialResult.add(input.get(i));
find(result, requiredSum, currentSum + input.get(i), new ArrayList<>(partialResult), i + 1, input);
}
public static void main(String[] args) {
List<Integer> input = List.of(2, 8, 2, 3, 4);
List<List<Integer>> output = find(input, 7);
System.out.println(output);
}
}
Output:
[[3, 4], [2, 2, 3]]
I've made a few other changes:
Use List<Integer> and List<List<Integer>> as the types (code to the interface)
Use List.of() to create the input list (added in Java 9)
Don't call toString() on objects passed to println — it's unneeded

How does this recursion make sense?

import java.util.*;
public class ArrayList5 {
static int max(ArrayList list) { // to be completed
if (list.size() == 0) {
return 0;
}
else
{
int first = (Integer) list.get(0);
list.remove(0);
if (first > max(new ArrayList(list)))
{
return first;
}
else
{
return max(list);
}
}
}
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList();
Collections.addAll(list, 4, 5, 3, 2, 3, 1, 3);
// int t=Console.readInt("Enter Target:");
int res1 = max(new ArrayList(list));
System.out.println("max=" + res1);
}
}
I don't understand why the max(new ArrayList(list))) part is required. Why does it have to create a new one and why can't it continue to work with the one list?
Also why doesn't it get caught in a loop (it's recursion so it will keep sending up a new list so I don't understand why 'first' isn't going to be 4 every time)?
Actually, there is a lot of superfluous code that is not required and make the code cumbersome/more difficult to read/understand.
You can simplify the code a lot and get rid of any reference to ArrayList which are not really necessary and by using proper generic at the right places, make the code actually readable.
You don't need to cast or create list all over the place.
public class ArrayList5 {
static int max(final List<Integer> list) {
if(list.isEmpty()) return 0;
final int head = list.get(0);
final List<Integer> tail = list.subList(1, list.size());
return (head > max(tail)? head:max(tail));
}
public static void main(final String... args) {
final int res1 = max(Arrays.asList(4, 5, 3, 2, 3, 1, 3));
System.out.printf("max=%d", res1);
}
}
You should try this:
static int max(ArrayList<Integer> list) {...}
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList();
Collections.addAll(list, 4, 5, 3, 2, 3, 1, 3);
// int t=Console.readInt("Enter Target:");
int res1 = max(new ArrayList(list));
System.out.println("max=" + res1);
}
The compiler is probably throws a warning because you don't declare the type of the ArrayList.

Making a main method to test linked lists

I need help to make a main method to test this program I've made for an assignment
Write a method to merge two linked lists of integers that are sorted into descending order. The result should be a third linked list that is the sorted combination of the original lists. Do not destroy the original lists.
import java.util.Iterator;
import java.util.LinkedList;
public class Exercise6
{
public static LinkedList<Integer> merge(LinkedList<Integer> a,LinkedList<Integer> b)
{
//Initialize variables
LinkedList<Integer> result = new LinkedList<Integer>();
Iterator<Integer> aI = a.iterator();
Iterator<Integer> bI = b.iterator();
int aTemp = 0;
int bTemp = 0;
//Get the first values from both lists using the next method
aTemp = aI.next();
bTemp = bI.next();
while(aI.hasNext() && bI.hasNext())
{
//Comparing the two elements
if(aTemp > bTemp)
{
result.add(bTemp);
bTemp = bI.next();
}
}
if(!aI.hasNext())
{
result.add(aTemp);
}
while(aI.hasNext())
{
result.add(aTemp);
aTemp = aI.next();
}
while(bI.hasNext())
{
result.add(bTemp);
bTemp = bI.next();
}
if(!aI.hasNext())
{
result.add(aTemp);
}
else
{
result.add(bTemp);
}
return result;
}
}
I think this is all you are asking for:
LinkedList<Integer> list1 = new LinkedList<Integer>();
list1.add(9);
list1.add(7);
list1.add(3);
LinkedList<Integer> list2 = new LinkedList<Integer>();
list1.add(8);
list1.add(5);
list1.add(1);
Exercise6 test = new Exercise6();
test.merge(list1,list2)
First, you are missing an else for your if in while(aI.hasNext() && bI.hasNext()). Next, I would strongly recommend you program to the List interface (instead of the concrete LinkedList type). Also, I would make the merge method generic on some comparable type T. Something like,
public static <T extends Comparable<? super T>> List<T> merge(List<T> a, List<T> b) {
// Initialize variables
List<T> result = new LinkedList<>();
Iterator<T> aI = a.iterator();
Iterator<T> bI = b.iterator();
// Get the first values from both lists using the next method
T aTemp = aI.hasNext() ? aI.next() : null;
T bTemp = bI.hasNext() ? bI.next() : null;
while (aI.hasNext() && bI.hasNext()) {
// Comparing the two elements
if (aTemp.compareTo(bTemp) < 0) {
result.add(bTemp); // <-- add the right-hand side
bTemp = bI.next();
} else {
result.add(aTemp); // <-- add the left-hand side
aTemp = aI.next();
}
}
// Add the final two values from the loop.
if (aTemp.compareTo(bTemp) < 0) {
result.add(bTemp);
result.add(aTemp);
} else {
result.add(aTemp);
result.add(bTemp);
}
while (aI.hasNext()) { // Add any remaining values from a
result.add(aI.next());
}
while (bI.hasNext()) { // Add any remaining values from b
result.add(bI.next());
}
return result;
}
Then you can test merge like
public static void main(String[] args) {
System.out.println(merge(Arrays.asList(6, 4, 2), Arrays.asList(5, 3, 1)));
System.out.println(merge(Arrays.asList("bat", "ant"),
Arrays.asList("dog", "cat")));
}
I get
[6, 5, 4, 3, 2, 1]
[dog, cat, bat, ant]
So do you write your code without ever testing it? I would suggest you get familiar with writing driver classes since as your code gets bigger you will need to test it along the way.
Create another class in the same package of your Exercise class: you can call it ExerciseDriver. Import classes as needed.
Declare Initialize and populate two linked lists. Declare a third linked lost to store the result.
Call the static method of your Exercise6 class
Print the result to verify
You could do something like:
import java.util.LinkedList;
public Class ExcerciseDriver{
public static void main (String[] args){
LinkedList<Integer> list1 = new LinkedList<>();
LinkedList<Integer> list2 = new LinkedList<>();
LinkedList<Integer> resultList;
list1.add(77);
list1.add(7);
list1.add(6);
list2.add(100);
list2.add(43);
list2.add(8);
resultList = Excercise6.merge(list1, list2);
System.out.println(resultList);
}
}
Now all you have to do is running the main method and verify the correctness of your algorithm

comparing values of two arrays if exist or not

I have this code which is to check in the two arrays and print out the values that dont exist in the other array. I think the way i did it is not the most efficient way to do it hence can anyone offer a better OOP way to write this code in Java?
Thanks
public class Calculate {
static int [] x = {1,2,4,6,7};
static int [] y = {2,3,4,6,7};
static boolean xflag = true;
static boolean yflag = true;
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i = 0; i<x.length; i++)
{
for (int b=0; b<y.length; b++)
{
if(x[i]!= y[b])
{
xflag= false;
}
else
{
xflag = true;
break;
}
}
if(xflag==false)
{
System.out.println(x[i] +" does not exist in array 2");
}
}
for(int i = 0; i<x.length; i++)
{
for (int b=0; b<y.length; b++)
{
if(y[i]!= x[b])
{
yflag= false;
}
else
{
yflag = true;
break;
}
}
if(yflag==false)
{
System.out.println(y[i] +" does not exist in array1");
}
}
}
}
Using Collection class removeAll method
String original[] = { "1","2","3","4","6"};
String testStr[] = { "1","2","3","5","7" };
List origList = new ArrayList(Arrays.asList(original));
List testList = new ArrayList(Arrays.asList(testStr));
System.out.println(origList.removeAll(testList));
System.out.println(origList);
you can use java collection framework, Many function are there,
here is simple example check it.
public static void main(String a[]){
List<String> sl = new ArrayList<String>();
sl.add("apple");
sl.add("java");
sl.add("c++");
sl.add("unix");
sl.add("orange");
sl.add("airtel");
List<String> tl = new ArrayList<String>();
tl.add("job");
tl.add("oracle");
tl.add("jungle");
tl.add("cricket");
boolean isCommon = Collections.disjoint(sl,tl);
System.out.println("Does not found any common elements? "+isCommon);
tl.add("java");
isCommon = Collections.disjoint(sl,tl);
System.out.println("Does not found any common elements? "+isCommon);
}
You may use Apache's CollectionUtils for this purpose if you want an abstraction from the implementation logic.E.g:
public static void main(String[] args) {
List<Integer> list1=Arrays.asList(1,2,4,6,7);
List<Integer> list2=Arrays.asList(2,3,4,6,7);
System.out.println(CollectionUtils.disjunction(list1,list2));
}
You can code this way
List<Integer> array1 = Arrays.asList(1,2,4,6,7);
List<Integer> array2 = Arrays.asList(2,3,4,6,7);
List<Integer> disjointArray = new ArrayList<Integer>();
for (Integer value : array1) {
if (!array2.contains(value)) {
disjointArray.add(value);
}
}
And then you can print disjointArray or do whatever manipulation you want.
Here a running example using Javas Collection classes:
public class Disjunction {
public static void main(String args[]) throws UnsupportedEncodingException {
//Some data preparation
List<Integer> list1=Arrays.asList(1,2,4);
List<Integer> list2=Arrays.asList(5,2,8);
//Here calculating data1-data2 and data2-data1, collect all list items
//that are in data1 or in data2 but not in both.
List<Integer> data1 = new ArrayList<>(list1);
data1.removeAll(list2);
List<Integer> data2 = new ArrayList<>(list2);
data2.removeAll(list1);
//Merging both results. data1 contains now exclusive or of list1 and list2
data1.addAll(data2);
System.out.println("exclusive or is " + data1);
}
}
It prints out
exclusive or is [1, 4, 5, 8]
Try the following program that checks two arrays for numbers they both have and numbers they don't have:
package test;
import java.util.ArrayList;
public class ArrayDifferentiater {
public static void main(String[] args) {
int[] ori = { 1, 5, 4, 8, 6, 65, 16, 6, 575, 64, 561, 57, 57 };
int[] che = { 1, 4, 8, 6 };
sort(ori, che);
}
public static void sort(int[] a, int[] b) {
/**
* 'foundNum' contains the numbers which exists in both array.
* 'notFoundNum' contains the numbers which exists in only first array.
*/
ArrayList<Integer> foundNum = new ArrayList<>();
ArrayList<Integer> notFoundNum = new ArrayList<>();
// First for loop starts
for (int i = 0; i < a.length; i++) {
// Second for loop starts
for (int j = 0; j < b.length; j++) {
/**
* Check if array 1 contains value of array 2.
* If contains than add it to "foundNum" arraylist.
*/
if (a[i] == b[j]) {
foundNum.add(a[i]);
// Remove the number which exists in both arrays from "notFoundNum" arraylist.
if (notFoundNum.contains(a[i])) {
for (int k = 0; k < notFoundNum.size(); k++) {
if (notFoundNum.get(k) == a[i]) {
notFoundNum.remove(k);
}
}
}
break;
} // First if block ends
/**
* Checks if a not found number does not exists in 'notFoundNum' arraylist (to reduce redundancy)
* then adds a not found number to 'notFoundNum' arraylist
* */
if (!notFoundNum.contains(a[i]))
notFoundNum.add(a[i]);
} // Second for loop ends
} // First for loop ends
System.out.println("Found Numbers : " + foundNum);
System.out.println("Not Found Numbers : " + notFoundNum);
}
}
Here is the output for the above program:
Found Numbers : [1, 4, 8, 6, 6]
Not Found Numbers : [5, 65, 16, 575, 64, 561, 57]

generating the cartesian power of a set

Is there a fast way to generate the cartesian power of a set?
For example, if the set is {1, 2}, then {1, 2} x {1, 2} = {(1, 1), (1, 2), (2, 1), (2, 2)}. How would I go about generating it for any given power?
Thank you.
I guess with power, you mean how often the set is combined with itself? So power 3 would be:
{1, 2} x {1, 2} x {1, 2} = (({1, 2} x {1, 2}) x {1, 2})
so you can solve it recursively, combine the set once, and then the set with the result...
If you like, you can adapt my Iterator for Lists of Lists to List of Sets , and build an interator:
import java.util.*;
class CartesianIterator <T> implements Iterator <List <T>> {
private final List <List <T>> lilio;
private int current = 0;
private final long last;
public CartesianIterator (final List <Set <T>> llo) {
// transform Set<T> to List <T>, because we need an index later
List <List <T>> llt = new ArrayList <List <T>> ();
for (Set <T> st : llo)
{
List <T> lt = new ArrayList <T> ();
for (T t: st)
lt.add (t);
llt.add (lt);
}
lilio = llt;
long product = 1L;
for (List <T> lio: lilio)
product *= lio.size ();
last = product;
}
public boolean hasNext () {
return current != last;
}
public List <T> next () {
++current;
return get (current - 1, lilio);
}
public void remove () {
++current;
}
private List<T> get (final int n, final List <List <T>> lili) {
switch (lili.size ())
{
case 0: return new ArrayList <T> (); // no break past return;
default: {
List <T> inner = lili.get (0);
List <T> lo = new ArrayList <T> ();
lo.add (inner.get (n % inner.size ()));
lo.addAll (get (n / inner.size (), lili.subList (1, lili.size ())));
return lo;
}
}
}
}
class CartesianIterable <T> implements Iterable <List <T>> {
private List <Set <T>> lilio;
public CartesianIterable (List <Set <T>> llo) {
lilio = llo;
}
public Iterator <List <T>> iterator () {
return new CartesianIterator <T> (lilio);
}
}
public class SetItTest
{
public static void main ( String [] args )
{
Set <Integer> si = new HashSet<Integer> ();
si.add (1);
si.add (2);
List <Set<Integer>> ls = new ArrayList <Set<Integer>> ();
ls.add (si);
ls.add (si);
ls.add (si);
CartesianIterable <Integer> ci = new CartesianIterable <Integer> (ls);
for (List <Integer> li : ci)
{
for (int i : li)
System.out.print (i + " ");
System.out.println ();
}
}
}
Output:
java SetItTest
1 1 1
2 1 1
1 2 1
2 2 1
1 1 2
2 1 2
1 2 2
2 2 2
If you can use external libraries, Guava has Sets.cartesianProduct(Set<E>...), so you can just do:
Set<Integer> set = ImmutableSet.of(1, 2);
Set<List<Integer>> = Sets.cartesianProduct(set, set);
// returns {[1, 1], [1, 2], [2, 1], [2, 2]} as desired
(Disclosure: I contribute to Guava.)
You can try with for two vectors v1 = {x1...xn}, v2 = {y1...yn}
public List producto(List a, List b) {
List producto = new ArrayList();
for (String s1 : a);
for (String s2 : b) {
List duo = new ArrayList();
duo.add(s1);
duo.add(s2);
producto.add(duo);
}
}
return producto;
}

Categories

Resources