Getting a sum from ArrayList<Number> using non-loop recursion - java

I am working on this lab assignment for school and I was wondering if anyone could give me some advice. My instructor wants us to add different number objects up from an array list and display the result. He wants us to do the addition in a non-loop recursive format. I've done a similar problem like this before with just integers, but I cannot seem to get this solution because there is more than one primitive type this time. Here is the Code I have so far:
Main:
import java.math.BigInteger;
import java.util.ArrayList;
public class TestSummation {
public static void main(String[] args) {
ArrayList<Number> aList = new ArrayList<Number>();
aList.add(new Integer(4));
aList.add(new Double(3.423));
aList.add(new Float(99.032));
aList.add(new BigInteger("32432"));
double result = Summation.sum(aList);
System.out.println(result);
}
}
Class that holds the recursive method:
import java.util.ArrayList;
public class Summation {
public static double sum(ArrayList<Number> aList) {
if (aList.size() < 1) {
return 0;
} else {
return sum(aList);
}
}
}
Right now this code throws a StackOverflowException and I was wondering if anyone had advice that would help me. I definitely know I need to add more to it, but I feel I'm on the right track with this current section of code. I'm just hitting a bad roadblock right now. Thanks in advance for any advice!

Recursion always works by cons two different cases:
the base case which is used to end the recursion
the recursive case which is applied on a specific N-th step
By thinking about your problem you can consider as your base case either a list of size 1 or a list of size 0. Let's choose the first for simplicity: the sum of all values of a list of size 1 is the only value that it is contained.
Now let's look for the recursive case: suppose that the list has length N. What we know is that the sum of all elements of a list of N elements is the N-th element added to the sum of a list containing N-1 elements (by removing the N-th element). It's pretty self explicatory as most of recursive implementations.
As you can see the recursive step reduces the size of the list so that the algorithm step-by-step reaches the base case, this is not what is happening to your code.

Since you've done something similar with integers, I gather that the problem is how to deal with the multitude of number class types. Since you want a double result and all Number objects must implement a doubleValue() method, you can use that to build your recursion. To recurse, you need to take the first element's value and add it to the (recurive) summation of the sublist that starts with the second element:
public class Summation {
public static double sum(List<Number> aList) {
final int len = aList.size();
if (len == 0) {
return 0;
}
final double val = aList.get(0).doubleValue();
if (len == 1) {
return val;
}
// help future compilers recognize tail recursion
return val + sum(aList.sublist(1, len));
}
}

Well, without giving it all away, I'll tell you that your code is throwing the exception because you're not modifying the list at all, simply passing it back into your recursive method, which is resulting in an infinite loop. The bit you'll have to add involves modifying the list before passing it into the recursive call (and, of course, doing the actual summation).

Related

Another way to compare two values of an array List to find the lonely integer in Java?

The problem to solve is to find a non-repeating integer in an Integer list. I used a while loop to compare each value with another. The function, however, returns the wrong value. This is a Hackerrank challenge which can be found here .
public static int lonelyinteger(List<Integer> a) {
int lonelyInt = 0;
for (int i = 0; i < a.size(); i++) {
for (int j=1;j<a.size();j++){
while (a.get(i)!=a.get(j)){
lonelyInt+=a.get(i);
}
}
}
return lonelyInt;
}
I would really appreciate any hints and/or more straightforward solutions. I am new to Java and practicing my skills.
Your approach of comparing each number with all the other numbers is correct in principle.
If we compare the ith element of the array with all the other elements, and none are equal to it, then we know it is the unique number.
Your program is not doing this correctly.
Think of the loops like this:
The outer loop using the index i is giving us the number we are checking for loneliness, a.get(i).
The inner loop using the index j is giving us each number to check against the current candidate selected by the outer loop, a.get(j).
So for each iteration of the outer loop we will need to keep track of whether any iteration of the inner loop matched. We could use a local boolean named equalNumberFound, which we set to false at the start of each iteration of the outer loop.
In the inner loop, we check whether we've found an equal number, and if we have, set it to true. Make sure that you don't check a number against itself!
At the end of each iteration of the outer loop, we check equalNumberFound, and if it's still false we can return the current outer loop number, because we now know that no other number was equal.
You need to review what you know about while loops, as it seems you have some incorrect assumptions about how they behave.
One of the ways you could approach the problem is by sorting the list first then compare each element to its adjacent element since the elements are limited to occurring either once or twice. Since only one element occurs once, then the element without an identical adjacent element is the stop condition. This approach achieves O(log(N)) time complexity and O(1) space complexity.
public static int lonelyInteger(List<Integer> a) {
Collections.sort(a);
for (int i = 1; i < a.size(); i += 2) {
if (a.get(i - 1).intValue() != a.get(i).intValue()) return a.get(i - 1);
}
return a.get(a.size()-1);
}
You can make use of hashset. Iterate through the list of integers:
Add element to hashset, if integer is not present in the hashset.
Remove the integer element, if it is already present in the hashset
Now return the lone non-repeating integer in the hashset.
public static int lonelyinteger(List<Integer> a) {
Set<Integer> set = new HashSet<>();
for (int n : a) {
if (set.contains(n)) {
set.remove(n);
} else {
set.add(n);
}
}
return set.stream().findFirst().get();
}
A better solution without using Streams
public static int lonelyinteger(List<Integer> a) {
Set<Integer> s = new HashSet<>();
for (int num : a) {
if(!s.add(num)){
s.remove(num);
}
}
return new ArrayList<>(s).get(0);
}

How can I fix my array so I don't have an IndexOutOfBoundsException?

For a HW assignment, I was tasked to add a bunch of methods into a BinarySearchTree class. Two methods I have are balance and InsertTree (I think it should've been named InsertNode). The authors from the textbook provided pseudo code of what the methods should look like. Both methods work with each other; balance is supposed to take an unbalanced tree and insert each element into an array. I believe InsertTree is supposed to take the elements from the array and put them back into the new formed tree.
The BST Class itself is quite large so I don't think posting it is a good idea. But you can find the Source code here under Sample Materials. The code in reference is in the ch07.trees package.
This is my interpretation of the authors pseudo code so far:
ArrayList<T> array = new ArrayList<T>();
public void balance()
// Will read, store, and recreate the tree
{
Iterator<T> iter = this.iterator();
int index = 0;
while(iter.hasNext())
{
array.add(iter.next());
index++;
}
System.out.println(array.toString());
System.out.println(index);
tree = new BinarySearchTree<T>();
tree.InsertTree(0, index -1);
}
public void InsertTree(int low, int high)
// Will find the mid-point and insert other elements into left and right subtrees
{
if (low == high)
{
tree.add(array.get(low));
}
else if((low + 1) == high)
{
tree.add(array.get(low));
tree.add(array.get(high));
}
else
{
int mid = (low + high)/2;
tree.add(array.get(mid));
tree.InsertTree(low,mid-1);
tree.InsertTree(mid+1,high);
}
}
I have to use ArrayList because all of the methods are generics of type T. In my driver class I am simply adding an unbalanced set of elements [A, B, C, D, E, F] and index will correctly show I have incremented index to 6. But, when the new tree calls for InsertTree( 0, index - 1), I get this:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at ch07.trees.BinarySearchTree.InsertTree(BinarySearchTree.java:180)
at ch07.trees.BinarySearchTree.balance(BinarySearchTree.java:163)
at ch07.trees.HWDriver.main(HWDriver.java:67)
Line 163 is tree.InsertTree(0, index -1); and Line 180 is tree.add(array.get(mid));
Seems the problem is involved with the mid-point, but I'm not sure what the issue could be. I'm not an expert at using ArrayLists, so any help on solving this would be much appreciated.
edit:
I believe the problem has been fixed. I put the array that I created back into the balance method instead of outside the method, and added the array to the InsertTree methods arguments. Then, I had to change every conditional output from this.tree.add to this.add. I also moved my BinarySearchTree tree back into the balanced method because before I was getting a NullPointerException.
Whether or not my method is working as intended is still to be determined.
Look what happens when you have an empty collection...
int index = 0;
[...]
tree = new BinarySearchTree<T>();
tree.InsertTree(0, index -1);
You are trying to insert something at index (-1). That is not legal.
Here is your answer more concisely:
this.tree = new BinarySearchTree<T>();
this.tree.InsertTree(0, index-1);
So you have created a new, empty tree and stored it in the member variable "tree". You then attempt tell your new, empty tree to insertTree(0, 5) .

intersection of two given LinkedList

Find the intersection of two given LinkedList (where each node has a character).
Return the LinkedList which has character which appears in both LinkedList (same sequence order as LinkedList1).
error:variable temp might not have been initialized
I tried a lot to resolve this error, but I cant step forward in this problem. Please help to resolve my error.
public SchNode func(SchNode head1, SchNode head2)
{
SchNode temp;
for(SchNode ptr=head1;ptr!=null;ptr=ptr.nextNode)
{
for(SchNode ptr2=head2;ptr2!=null;ptr2=ptr2.nextNode)
{
if(ptr.ch==ptr2.ch)
{
temp.ch=ptr2.ch;
temp=temp.nextNode;
}
}
}
return temp ;
}
You can use this method if don't understand it wrong.
measure list1 length, lets call it A
measure list2 length, lets call it B
difference is: C = A - B
if C < 0 then choose list2, else choose list1, lets call chosen list choosenList
answer is choosenList[abs(C)] //i mean absolute value of C
EDIT: what i understand is you have two linked lists that have a common node(pointer)

Java: Recursively Finding the minimum element in a list

I will preface this by saying it is homework. I am just looking for some pointers. I have been racking my brain with this one, and for the life of me i am just not getting it. We are asked to find the minimum element in a list. I know i need a sublist in here, but after that i am not sure. any pointers would be great. thanks.
/** Find the minimum element in a list.
*
* #param t a list of integers
*
* #return the minimum element in the list
*/
public static int min(List<Integer> t) {
if (t.size() == 1){
return t.get(0);
}
else{
List<Integer> u = t.subList(1, t.size());
The point of a recursive algorithm is that everything that must be computed is done through return values or additional parameters. You shouldn't have anything outside the local call of the recursive step.
Since you have to find the minimum element you should take some considerations:
the min element of a list composed by one element is that element
the min element of a generic list is the minimum between the first element and the minimum of the remaining list
By taking these into consideration it should be easy to implement. Especially because recursive algorithms have the convenience of being really similar to their algorithmic description.
You need to find the relationship between the function min applied to a list and the function min applied to a sublist.
min([a b c d e ...]) = f(a, min([b c d e ...]))
Now you just need to find the function f. Once you have the relationship, then to implement it is easy. Good luck.
In the most general sense, recursion is a concept based on breaking down work, and then delegating the smaller chunk of work to a copy of yourself. For recursion to work, you need three main things:
The breakdown of work. How are you going to make each step "simpler"?
The recursive call. At some point your function must call itself, but with less "work".
The base case. What is a (usually trivial) end case that will stop the recursion process?
In your case, you're trying to create a function min that operates on a list. You're correct in thinking that you could somehow reduce (breakdown) your work by making the list one smaller each time (sublist out the first element). As others have mentioned, the idea would be to check the first element (which you just pulled off) against the "rest of the list". Well here's where the leap of faith comes in. At this point, you can "assume" that your min function will work on the sublist, and just make a function call on the sublist (the recursive call). Now you have to make sure all your calls will return (i.e. make sure it will not recurse forever). That's where your base case comes in. If your list is of size 1, the only element is the smallest of the list. No need to call min again, just return (that part you already have in your original post).
/**
* The function computes the minimum item of m (-1 if m is empty).
* #param m: The MyList we want to compute its minimum item.
* #return: The minimum item of MyList
*/
public int minimum(MyList<Integer> m){
int res = 0;
int e0 = 0;
int e1 = 0;
// Scenarios Identification
int scenario = 0;
// Type 1. MyLyst is empty
if(m.length() == 0) {
scenario = 1;
}else {
// Type 2. MyLyst is not empty
scenario = 2;
}
// Scenario Implementation
switch(scenario) {
// If MyLyst is empty
case 1:
res = -1;
break;
// If there is 1 or more elements
case 2:
//1. Get and store first element of array
e0 = m.getElement(0);
//2. We remove the first element from MyList we just checked
m.removeElement(0);
//3. We recursively solve the smaller problem
e1 = minimum(m);
//4. Compare and store results
if(e0 < e1) {
res = e0;
}
else {
res = e1;
}
//5. Return removed element back to the array
m.addElement(0, e0);
break;
}
//6. Return result
return res;
}
There you go, Try this out in the method:
public static Integer minimum(List<Integer> t) {
int minInt;
if (t.size() == 1) {
return t.get(0);
} else {
int first = t.get(0);
List<Integer> u = t.subList(1, t.size());
minInt = Math.min(first, u.get(0));
minInt = IntegerList.minimum(u);
}
return minInt;
}
Hopefully this solves your issue.

question on java list remove

The method public boolean remove(Object o) of List removes an object from list but does not shift the elements following.Just nulls the object value.
IMHO this is an uninintuitive design choice since the size of the list before and after removal remains the same.
Is there an elegant way to get a list with the elements shifted?
Thanks
No, that's not what it does. The element is removed and all indices following it are reduced by one. What makes you think it acts differently?
According to the Java API here it sais that the remove function of List DOES shift
Removes the element at the specified position in this list (optional operation). Shifts any subsequent elements to the left (subtracts one from their indices). Returns the element that was removed from the list.
EDIT:
Main class:
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
ArrayList<A> x = new ArrayList<A>();
A one = new A("one");
A two = new A("two");
A three = new A("three");
A four = new A("four");
A five = new A("five");
A six = new A("six");
A seven = new A("seven");
A eight = new A("eight");
A nine = new A("nine");
A ten = new A("ten");
x.add(one);
x.add(two);
x.add(three);
x.add(four);
x.add(five);
x.add(six);
x.add(seven);
x.add(eight);
x.add(nine);
x.add(ten);
for(A item:x){
System.out.println(item.getStr());
}
x.remove(four);
Iterator<A> i = x.iterator();
while(i.hasNext()){
A item = i.next();
System.out.println(item.getStr());
}
}
}
The A Class:
public class A {
private String str;
public A(String x){
this.str = x;
}
public String getStr(){
return this.str;
}
}
works perfectly! no null pointer exception.
This is how it should be done. the first For loop is the alternative syntax for what i did wit the Iterator object. Actually Java automatically translates the first for loop in something that looks like the while loop.
If you look at ArrayList remove implementation, it uses a local method fastRemove(index) as follows:-
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
It does use arraycopy which is a proof that you get whole new list of fresh objects and not the null filled in between. Is this a proof?
The contract for java.util.List implies that calling remove will cause the size() to be decremented. If you're talking specifically about java.util.ArrayList then you might be right about the internal array not shifting its elements, but this is an implementation detail that shouldn't matter to you in 99% of all cases. If it still does matter, then you're trying to optimize for a specific situation and you should probably implement your own List or use something like java.util.LinkedList.
Either your observation is wrong or you are using some other kind of List implementation (and not ArrayList) that doesn't shift the elements to the right of the element being removed. Can you post your code?
If you look at the java.util.ArrayList source code in JDK8, you will see that the remove(Object o) method effectively copies the elements to the right of the element being removed, to the same array starting from the index of the element being removed. Look at the ArrayList source code for more info:
If all you need is an array of the data, then just call toArray().

Categories