So, I am trying to write two overloaded remove methods for LinkedList class, where one takes an index of an element that needs to be removed and another one that takes Object that needs to be removed. But when I try to make a LinkedList of integer and call the latter method, method that takes in index is called instead. Is there any way around this??
(PS. I know you can just change the name of the method, but I am given an interface file that requires me to write overloaded methods)
public E remove(int index) {
for (int i = 0; i < index;i++) {
curNode = curNode.next();
}
if (curNode == head && curNode == tail) {
head = null;
tail = null;
}
else {
URNode sucNode = curNode.next();
URNode prevNode = curNode.prev();
if (sucNode != null)
sucNode.setPrev(prevNode);
else {
prevNode.setNext(null);
tail = prevNode;
}
if (prevNode != null)
prevNode.setNext(sucNode);
else {
sucNode.setPrev(null);
head = sucNode;
}
}
numElements--;
return null;
}
public boolean remove(Object o) {
URNode curNode = head;
for (int i = 0; i < numElements;i++) {
if (curNode.element() == o) {
remove(i);
return true;
}
curNode = curNode.next();
}
return false;
}
public static void main(String args[]){
LinkedList intList = new LinkedList();
intList.add(1);
intList.add(2);
intList.add(3);
intList.remove(1); //I want this to remove node with element 1, instead of node with index of 1
//[2][3] should be returned, not [1][3]
}
intList.remove(Integer.valueOf(1)); // just make it Integer but not int
My recursive function to count number of leaves in a Binary Tree works correctly:
public static int numberOfLeaves(BinaryTree<String> root) {
if (root == null) return 0;
else if(root.isLeaf()) return 1;
int left = numberOfLeaves(root.leftTree);
int right = numberOfLeaves(root.rightTree);
return (left + right);
}
But now I want to sum up the data of all the leaves in a List and return it.
Have a look at my hopeless attempt:
public ArrayList<String> getDataLeaves(BinaryTree<String> root) {
ArrayList<String> list = new ArrayList<>();
if (root == null) return list;
else if (root.isLeaf()) list.add(root.data);
else if(root.leftTree != null ) getDataLeaves(root.leftTree);
else getDataLeaves(root.rightTree);
return list;
}
Can I (how do I) use the functionality/style of my numberOfLeaves function to help me write a recursive function which will sum up the data of all the leaves in a list and return it.
Note:
a node is of type BinaryTree<String>
with data, leftTree,RightTree as instance variables.
You should add the leaves returned by the recursive calls:
public ArrayList<String> getDataLeaves(BinaryTree<String> root) {
ArrayList<String> list = new ArrayList<>();
if (root == null)
return list;
else if (root.isLeaf())
list.add(root.data);
else {
list.addAll(getDataLeaves(root.leftTree));
list.addAll(getDataLeaves(root.rightTree));
}
return list;
}
Given a singly linked list, remove all the nodes which have a greater value on right side. This is not a home work and it was asked me in an interview.
e.g.
input:
2--->4--->2--->1--->3--->0
then the output should be
4--->3--->0.
input:
30--->40--->50--->60
then the output should be
60
My approach was below:
1. reverse the link list
2. maintain the max value if the current node is less than max than remove else move next
3. reverse again
But the interviewer asked me to optimize this. I think he was expecting the same as mentioned by #Trying.
Time complexity O(N). please let me know if you have any doubts. Thanks.
Node delete(Node n){
if(n==null){
return null;
}
Node t = delete(n.next);
if(t==null){
return n; // i.e. right most node so just return this
}
else{
Comparable c = (Comparable)n.k;
if(c.compareTo((Comparable)t.k)<0){ //no need of this node so return t.
return t;
}
else{
n.next=t; //valid node so change the next pointer of current node
return n;
}
}
}
Split the problem, and borrow from the solution.
decreasingList(List list) {
if list empty then return empty
List restSolution = decreasingList(list.next)
... list.first ... // What now
Ask yourself, having the restSolution and list.first what you should return.
This makes computer science sooo much funnier than math: laziness, doing just a bit, and delegating work.
Sorry thought this was homework
static class List {
int value;
List next;
List(int value, List next) {
this.value = value;
this.next = next;
}
static List makeList(int... values) {
List list = null;
List tail = null;
for (int value: values) {
List node = new List(value, null);
if (tail == null) {
list = node;
} else {
tail.next = node;
}
tail = node;
}
return list;
}
#Override
public String toString() {
if (next == null) {
return String.valueOf(value);
}
return String.valueOf(value) + "-->" + next.toString();
}
}
static List decreasingList(List list) {
if (list == null) {
return null;
}
List rest = decreasingList(list.next);
if (rest != null && list.value < rest.value) {
return rest;
}
list.next = rest;
return list;
}
public static void main(String[] args) {
List list = List.makeList(2, 4, 2, 1, 3, 0);
System.out.println("List: " + list);
list = decreasingList(list);
System.out.println("Decreasing: " + list);
}
The recursion might be resolved, just as you did: reversal by walking the nexts and changing the next to the prior node. And then at the tail going back.
static List decreasingList(List list) {
List prior = null;
while (list != null) {
List next = list.next;
list.next = prior;
prior = list;
list = next;
}
list = prior; // The reversed list.
prior = null;
while (list != null) {
List next = list.next;
list.next = prior;
if (prior == null || list.value > prior.value) {
prior = list;
}
list = next;
}
list = prior;
return list;
}
for homework I was asked to write a contain method for a custom linked list.
I know that the recursive method should have a base case and then the recursive case.However, I am having some trouble understanding how to write the recursive case of the method. So far this is what I have written, but my code is executing the base case more than once. Can you please give me some guidance?
public class OrderedList {
private Node first;
//Constructor
public OrderedList() {
this.first = null;
}
//Return the number of items in the list
public int size() {
int counter = 0;
Node pointer = this.first;
while (pointer != null) {
counter++;
pointer = pointer.next;
}
return counter;
}
//Return an array of copies of the stored elements
public Comparable[] getStore() {
Comparable[] elements = new Comparable[size()];
Node pointer = this.first;
if (this.first == null) {
return elements;
} else {
int i = 0;
while (pointer != null) {
elements[i] = pointer.data;
pointer = pointer.next;
i++;
}
return elements;
}
}
//true iff item matches a stored element
//Recursive
public boolean contains(Comparable item) {
//Base case
if (this.first == null) {
return false;
}
Node pointer = this.first;
this.first = this.first.next;
if (pointer.data.compareTo(item) == 0) {
return true;
}
//Recursive case
else {
boolean info = contains(item);
pointer.next = this.first;
this.first = pointer;
return info;
}
}
First of all I like to do something like this:
public boolean contains(Comparable item)
{
return containsHelper(this.first, Comparable item);
}
private boolean containsHelper(Node node, Comparable item)
{
//base case
if(node == null)
{
return false;
}
else
{
if(node.data.compareTo(item) == 0)
{
return true;
}
return containsHelper(node.next, item);
}
}
This hides implementation details from the user and it stops your list from getting overridden when you run that method.
To implement a recursive solution, you need an auxiliary method for contains. The auxiliary method should have an additional argument that is the Node from which to start testing. The public contains method should call the auxiliary method and pass this.first as the start node. The rest of the logic should then be pretty simple for you to figure out.
From what I am seeing, your code will return true once the else statemnet have been executed once. I think what you need to do is to set the boolean value to false everytime because recursion acts very much like a while loop and if the values are not updated, the base case would be executed over and over again.
I have two list **ListA<MyData> listA = new ArrayList<MyData>()** and ListB<MyData> listB = new ArrayList<MyData>() both contain object of type MyData and MyData contain these variables.
MyData {
String name;
boolean check;
}
ListA and ListB both contains MyData objects ,now I have to compare both the list's object values here name as well check variable like if ListA contains these object values
ListA = ["Ram",true],["Hariom",true],["Shiv",true];
and ListB also contain
ListB = ["Ram",true],["Hariom",true],["Shiv",true];
then i have to compare lists and return false because both list are same
But if ListA contains
ListA = ["Ram",true],["Hariom",true],["Shiv",false];
and ListB Contain
ListB = ["Ram",true],["Hariom",true],["Shiv",true];
then I have to compare lists and return true because both list are not same
or vice-versa so any slight change in the any list values I have to return true.
One thing I have to mentioned here objects can be in any order.
It's not the most efficient solution but the most terse code would be:
boolean equalLists = listA.size() == listB.size() && listA.containsAll(listB);
Update:
#WesleyPorter is right. The solution above will not work if duplicate objects are in the collection.
For a complete solution you need to iterate over a collection so duplicate objects are handled correctly.
private static boolean cmp( List<?> l1, List<?> l2 ) {
// make a copy of the list so the original list is not changed, and remove() is supported
ArrayList<?> cp = new ArrayList<>( l1 );
for ( Object o : l2 ) {
if ( !cp.remove( o ) ) {
return false;
}
}
return cp.isEmpty();
}
Update 28-Oct-2014:
#RoeeGavriel is right. The return statement needs to be conditional. The code above is updated.
ArrayList already have support for this, with the equals method. Quoting the docs
...
In other words, two lists are defined to be equal if they contain the same elements in the same order.
It does require you to properly implement equals in your MyData class.
Edit
You have updated the question stating that the lists could have different orders. In that case, sort your list first, and then apply equals.
I got this solution for above problem
public boolean compareLists(List<MyData> prevList, List<MyData> modelList) {
if (prevList.size() == modelList.size()) {
for (MyData modelListdata : modelList) {
for (MyData prevListdata : prevList) {
if (prevListdata.getName().equals(modelListdata.getName())
&& prevListdata.isCheck() != modelListdata.isCheck()) {
return true;
}
}
}
}
else{
return true;
}
return false;
}
EDITED:-
How can we cover this...
Imagine if you had two arrays "A",true "B",true "C",true and "A",true "B",true "D",true. Even though array one has C and array two has D there's no check that will catch that(Mentioned by #Patashu)..SO for that i have made below changes.
public boolean compareLists(List<MyData> prevList, List<MyData> modelList) {
if (prevList!= null && modelList!=null && prevList.size() == modelList.size()) {
boolean indicator = false;
for (MyData modelListdata : modelList) {
for (MyData prevListdata : prevList) {
if (prevListdata.getName().equals(modelListdata.getName())
&& prevListdata.isCheck() != modelListdata.isCheck()) {
return true;
}
if (modelListdata.getName().equals(prevListdata.getName())) {
indicator = false;
break;
} else
indicator = true;
}
}
}
if (indicator)
return true;
}
}
else{
return true;
}
return false;
}
First, implement the MyData.equals(Object o) and MyData.hashCode() methods.
Once you implemented the equals method, you can iterate over the lists as follows:
if(ListA == null && ListB == null)
return false;
if(ListA == null && ListB != null)
return true;
if(ListA != null && ListB == null)
return true;
int max = ListA.size() > ListB.size() ? ListA.size() : ListB.size();
for(int i = 0; i < max; i++) {
myData1 = ListA.get(i);
myData2 = ListB.get(i);
if(!myData1.equals(myData2)) {
return true;
}
}
return false;
I found a very basic example of List comparison at List Compare
This example verifies the size first and then checks the availability of the particular element of one list in another.
This can be done easily through Java8 using forEach and removeIf method.
Take two lists. Iterate from listA and compare elements inside listB
Write any condition inside removeIf method.
Hope this will help
listToCompareFrom.forEach(entity -> listToRemoveFrom.removeIf(x -> x.contains(entity)));
Override the equals method in your class and use Collection#equals() method to check for equality.
See if this works.
import java.util.ArrayList;
import java.util.List;
public class ArrayListComparison {
public static void main(String[] args) {
List<MyData> list1 = new ArrayList<MyData>();
list1.add(new MyData("Ram", true));
list1.add(new MyData("Hariom", true));
list1.add(new MyData("Shiv", true));
// list1.add(new MyData("Shiv", false));
List<MyData> list2 = new ArrayList<MyData>();
list2.add(new MyData("Ram", true));
list2.add(new MyData("Hariom", true));
list2.add(new MyData("Shiv", true));
System.out.println("Lists are equal:" + listEquals(list1, list2));
}
private static boolean listEquals(List<MyData> list1, List<MyData> list2) {
if(list1.size() != list2.size())
return true;
for (MyData myData : list1) {
if(!list2.contains(myData))
return true;
}
return false;
}
}
class MyData{
String name;
boolean check;
public MyData(String name, boolean check) {
super();
this.name = name;
this.check = check;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (check ? 1231 : 1237);
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyData other = (MyData) obj;
if (check != other.check)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
You can subtract one list from the other using CollectionUtils.subtract, if the result is an empty collection, it means both lists are the same. Another approach is using CollectionUtils.isSubCollection or CollectionUtils.isProperSubCollection.
For any case you should implement equals and hashCode methods for your object.
Using java 8 removeIf to compare similar items
public int getSimilarItems(){
List<String> one = Arrays.asList("milan", "dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta");
List<String> two = new ArrayList<>(Arrays.asList("hafil", "iga", "binga", "mike", "dingo")); //Cannot remove directly from array backed collection
int initial = two.size();
two.removeIf(one::contains);
return initial - two.size();
}
Logic should be something like:
First step: For class MyData implements Comparable interface, override the compareTo method as per the per object requirement.
Second step: When it comes to list comparison (after checking for nulls),
2.1 Check the size of both lists, if equal returns true else return false, continue to object iteration
2.2 If step 2.1 returns true, iterate over elements from both lists and invoke something like,
listA.get(i).compareTo(listB.get(i))
This will be as per the code mentioned in step-1.
It's been about 5 years since then and luckily we have Kotlin now.
Comparing of two lists now looks is as simple as:
fun areListsEqual(list1 : List<Any>, list2 : List<Any>) : Boolean {
return list1 == list2
}
Or just feel free to omit it at all and use equality operator.
I know it's old question but in case anyone needs it. I use this in my application and it works well. i used it to check if the cart has been changed or not.
private boolean validateOrderProducts(Cart cart) {
boolean doesProductsChanged = false;
if (originalProductsList.size() == cart.getCartItemsList().size()) {
for (Product originalProduct : originalProductsList) {
if (!doesProductsChanged) {
for (Product cartProduct : cart.getCartProducts()) {
if (originalProduct.getId() == cartProduct.getId()) {
if (originalProduct.getPivot().getProductCount() != cartProduct.getCount()) {
doesProductsChanged = true;
// cart has been changed -> break from inner loop
break;
}
} else {
doesProductsChanged = false;
}
}
} else {
// cart is already changed -> break from first loop
break;
}
}
} else {
// some products has been added or removed (simplest case of Change)
return true;
}
return doesProductsChanged;
}
String myData1 = list1.toString();
String myData2 = list2.toString()
return myData1.equals(myData2);
where :
list1 - List<MyData>
list2 - List<MyData>
Comparing the String worked for me. Also NOTE I had overridden toString() method in MyData class.
I think you can sort both lists and convert to List if some of them was a HashSet colleciton.
java.utils.Collections package lets you do it.
List<Category> categoriesList = new ArrayList<>();
Set<Category> setList = new HashSet<>();
Collections.sort(categoriesList);
List<Category> fileCategories = new ArrayList<>(setList);
Collections.sort(fileCategories);
if(categoriesList.size() == fileCategories.size() && categoriesList.containsAll(fileCategories)) {
//Do something
}