Creating a binary tree in Java for Genetic Programming Purposes - java

I'm working on a project for a software engineering class I'm taking. The goal is to design a program that will use genetic programming to generate a mathematical expression that fits provided training data.
I've just started working on the project, and I'm trying to wrap my head around how to create a binary tree that will allow for user-defined tree height and keep each node separate to make crossover and mutation simpler when I get to implementing those processes.
Here are the node classes I've created so far. Please pardon what I am sure is my evident inexperience.
public class Node
{
Node parent;
Node leftchild;
Node rightchild;
public void setParent(Node p)
{
parent = p;
}
public void setLeftChild(Node lc)
{
lc.setParent(this);
leftchild = lc;
}
public void setRightChild(Node rc)
{
rc.setParent(this);
rightchild = rc;
}
}
public class OperatorNode extends Node
{
char operator;
public OperatorNode()
{
double probability = Math.random();
if (probability <= .25)
{
operator = '+';
}
else if (probability > .25 && probability <= .50)
{
operator = '-';
}
else if (probability > .50 && probability <= .75)
{
operator = '*';
}
else
{
operator = '/';
}
}
public void setOperator(char op)
{
if (op == '+' || op == '-' || op == '*' || op == '/')
{
operator = op;
}
}
/**
* Node that holds x variables.
*/
public class XNode extends Node
{
char x;
public XNode()
{
x = 'x';
}
}
import java.util.Random;
public class OperandNode extends Node
{
int operand;
/**
* Initializes random number generator, sets the value of the node from zero to 9.
*/
public OperandNode()
{
Random rand = new Random();
operand = rand.nextInt(10);
}
/**
* Manually changes operand.
*/
public void setOperand(int o)
{
operand = o;
}
}
This accomplishes everything I need out of the nodes themselves, but I'm running into problems trying to figure out how to turn these into a larger tree. I realize I need to use a collection type of some sort, but can't seem to find one in the Library that seems appropriate for what I'm trying to do.
Even a nudge in the right direction would be greatly appreciated.

So you want to build a random tree of OperatorNodes, OperandNodes, and XNodes? And you said you want to make the tree depth user defined?
Define a recursive function called buildRandomTree or something similar. It should take a single int parameter for tree depth. If the depth parameter is 1, return a random leaf node (OperandNode or XNode). If the depth parameter is more than 1, generate a random OperatorNode, and make recursive calls to generate the left and right subtrees (with depth 1 less than the current level).
Depending on what you want to do with the nodes, you will have to define other recursive functions. For example, you will probably want to generate textual representations of your expression trees. For that, you can define toString() on each of the node classes. (OperatorNode.toString() will have to call toString() on the left and right subtrees.)
You will probably also want to evaluate the expression trees (with given values for the variables). For that, you can define another recursive function, perhaps called evaluate(). It will have to take one parameter, probably a Map, which will give the variable values (or "bindings") which you want to evaluate the expression with. (Right now your expression trees can only contain a single variable "x", but I imagine you may want to add more. If you are sure you will only ever use a single variable, then evaluate can take a single numeric argument for the value of "x".)
The implementation of evaluate for your 3 node classes will all be very simple. OperandNode and VariableNode will just return a value directly; OperatorNode will have to call evaluate on the left and right subtrees, combine the values using the appropriate operation, then return the result.

Maybe looking at this will help you.

Related

Why do I need a helper method to recursively search a binary search tree?

Here is the code for the implementation of the Binary Search Tree:
public class BST<T extends Comparable<T>> {
BSTNode<T> root;
public T search(T target)
{
//loop to go through nodes and determine which routes to make
BSTNode<T> tmp = root;
while(tmp != null)
{
//c can have 3 values
//0 = target found
//(negative) = go left, target is smaller
//(positive) = go left, target is greater than current position
int c = target.compareTo(tmp.data);
if(c==0)
{
return tmp.data;
}
else if(c<0)
{
tmp = tmp.left;
}
else
{
tmp = tmp.right;
}
}
return null;
}
/*
* Need a helper method
*/
public T recSearch(T target)
{
return recSearch(target, root);
}
//helper method for recSearch()
private T recSearch(T target, BSTNode<T> root)
{
//Base case
if(root == null)
return null;
int c = target.compareTo(root.data);
if(c == 0)
return root.data;
else if(c<0)
return recSearch(target, root.left);
else
return recSearch(target, root.right);
}
Why do I need the recursive helper method? Why can't I I just use "this.root" to carry out the recursive process that is taking place? Furthermore, if screwing up the root property of the object this method is being called on is a problem, then how is does the helper method prevent this from happening? Does it just create a pointer that is separate from the this.root property, and therefore won't mess up the root property of the object that the method is being called on?
Sorry if the question doesn't seem straight forward, but if anyone can enlighten me on what's exactly going on behind the scenes I would really appreciate it.
The method needs a starting point. It needs to have a non changing Target node and it needs to compare it with some other node to see if they are a match lets call this node current instead of root since it is the current Node the recursive method is evaluating. There really isn't a concise way of doing this when using a recursive method other than using a helper function and passing in both variables (this is the case for many recursive methods). As you said stated if you updated root you would completely alter your tree when going left or right which you wouldn't want to do. The helper function is used because it gives your recursive method a starting point. And it also keeps track of the current node you are working on as you said the method points to the Node object being evaluated but doesn't make any changes. When going left or right it doesn't modify anything it just passes in a reference to the left or right node and continues to do this until the target is found or the base case is hit.

Recursive evaluate() in expression tree class

I am new in Java and trying to add evaluate method to my class. The ExpTree class and its testing program is given to me. I wrote my code as I learned in the class, but do not know why it does not work.
An evaluate() method, which returns the arithmetic evaluation of the ExpTree. This should be done recursively, so you will need 2 methods to do it. In the case where it would result in division or mod by 0, it should throw a new ArithmeticException with a descriptive String. If the tree is empty, evaluate() should also throw a new ArithmeticException with a descriptive String.
Here is my code:
// This will implement an "Expression Tree" which stores an arithmetic expression
import java.util.*;
public class ExpTree
{
//-------data
private ExpNode root;
//-------constructor
public ExpTree()
{
root = null;
}
//constructor where a string is passed in. It is parsed and stored
public ExpTree(String expString)
{
//declare StringTokenizer, Stacks, and other variables used in parsing
StringTokenizer tokenizer = new StringTokenizer (expString, "()+-*/%", true);
String token;
ExpNode operator, leftOperand, rightOperand;
Stack<ExpNode> operators = new Stack<ExpNode>();
Stack<ExpNode> operands = new Stack<ExpNode>();
//break up expString into tokens
while (tokenizer.hasMoreTokens())
{
token = tokenizer.nextToken();
// if the current token is a left paren, ignore it
if (token.equals ("("))
;
// if the current token is an operator, put it on the
// operator stack
else if ((token.equals ("+")) || (token.equals ("-")) ||
(token.equals ("*")) || (token.equals ("/")) || (token.equals ("%")))
operators.push (new ExpNode(token));
//if the current token is a right paren, pop the operators stack
//to get the operator, pop the operands stack twice to get the two
//operands (stored as expression trees). Then make the two operands
//children of the operator and push back on the operands tree.
else if (token.equals (")"))
{
operator = operators.pop();
rightOperand = operands.pop();
leftOperand = operands.pop();
operator.setLeft(leftOperand);
operator.setRight(rightOperand);
operands.push(operator);
}
//otherwise, the token should be a number - put it in the operands stack
else
operands.push (new ExpNode(token));
} // while (tokenizer.hasMoreTokens())
//when finished parsing, the operands stack should contain the fully-built
//expression tree.
if (!operands.isEmpty())
root = operands.pop();
}
//-------methods
//isEmpty()
public boolean isEmpty()
{
return (root == null);
}
//printTree methods - prints the tree in RNL order, with indents. Called from "outside"
public void printTree()
{
if (root == null)
System.out.println("The tree is empty");
else
printTree(root, 0); //start with the root with 0 indentations
}
//recursive, private version of printTree
private void printTree(ExpNode subTree, int indents)
{
//if there is a right side, handle it first (with 1 more indent)
if (subTree.getRight() != null)
printTree(subTree.getRight(), indents+1);
//then print the node itself (first move over the right amount of indents)
System.out.println("\n\n\n");
for (int i=0; i<indents; i++)
System.out.print("\t");
System.out.println(subTree);
//if there is a left side, handle it first (with 1 more indent)
if (subTree.getLeft() != null)
printTree(subTree.getLeft(), indents+1);
}
//inorder traversal - starts the recursive calls to print inorder
public String inOrder()
{
return inOrder(root);
}
//inorder traversal - recursive left side of tree, print node, right side of tree
private String inOrder(ExpNode theTreeToTraverse)
{
if (theTreeToTraverse == null)
return ""; //don't try to do anything if tree is null
//else build up a String to return. It will involve recursive calls
String returnString = "";
if (theTreeToTraverse.getLeft() != null)
{
returnString += "(" + inOrder(theTreeToTraverse.getLeft());
}
returnString += theTreeToTraverse;
if (theTreeToTraverse.getRight() != null)
{
returnString += inOrder(theTreeToTraverse.getRight()) + ")";
}
return returnString;
}
//public version of evaluate
public double evaluate(){
if (root == null) //Am I null?
throw new ArithmeticException("The tree is empty, nothing to be evaluated!");
else //You handle it!
return recursiveEvaluate(root);
}
//Recursive version of evaluate
private double recursiveEvaluate(ExpNode subTree){
//If subTree is empty
if (subTree == null)
return 0;
//What are you subTree? A number? An operator?
else if(subTree.getData().equals("+"))
return recursiveEvaluate(subTree.getLeft()) +
recursiveEvaluate(subTree.getRight()) ;
else if(subTree.getData().equals("-"))
return recursiveEvaluate(subTree.getLeft()) -
recursiveEvaluate(subTree.getRight()) ;
else if(subTree.getData().equals("*"))
return recursiveEvaluate(subTree.getLeft()) *
recursiveEvaluate(subTree.getRight()) ;
else if(subTree.getData().equals("/")){
double right = recursiveEvaluate(subTree.getRight());
if(right == 0.0)
throw new ArithmeticException("Divide by zero is undefined!");
return recursiveEvaluate(subTree.getLeft()) / right;
}
else if(subTree.getData().equals("%")){
double right = recursiveEvaluate(subTree.getRight());
if(right == 0.0)
throw new ArithmeticException("Mod by zero exception");
return recursiveEvaluate(subTree.getLeft()) % right;
}
//Converting String type to double
else
return Double.parseDouble(subTree.getData());
}
//Public version of numPlus
public int numPlus(){
return recursiveNumPlus(root);
}
//Recursive version of numPlus
private int recursiveNumPlus(ExpNode subTree){
if (subTree == null)
return 0;
//If you are a '+' sign
if(subTree.getData().equals("+"))
return recursiveNumPlus(subTree.getLeft()) +
recursiveNumPlus(subTree.getRight()) + 1;
else
return recursiveNumPlus(subTree.getLeft()) +
recursiveNumPlus(subTree.getRight());
}
}
//***************************************************************************
// ExpNode holds a "node" for an ExpTree.
class ExpNode
{
//data
private String data;
private ExpNode left;
private ExpNode right;
//constructor
public ExpNode(String el)
{
data = el;
left = right = null;
}
//methods
//toString() - this is how an ExpNode represents itself as a String
public String toString()
{
return data;
}
//getLeft - returns the reference to the left subTree
public ExpNode getLeft()
{
return left;
}
//getRight - returns the reference to the right subTree
public ExpNode getRight()
{
return right;
}
//getData - returns the data (could be an operator or a number, so returns as a String)
public String getData()
{
return data;
}
//setLeft - sets the left subTree to whatever is passed in
public void setLeft(ExpNode newNode)
{
left = newNode;
}
//setRight - sets the right subTree to whatever is passed in
public void setRight(ExpNode newNode)
{
right = newNode;
}
}
The object oriented approach to your problem is to define a dedicated type for each kind of node. In order to keep the length of this answer reasonable and to avoid doing your homework, I'll only show a minimal example for integer expressions only involving addition and multiplication.
The first step is to define what an expression node must provide. For this, we define the interface ExprNode. If you did not learn about polymorphism in your class yet (which should surprise me) you'll probably want to stop reading now and come back after you have learned about it.
We want to evaluate nodes so we'll add an evaluate method that should return the value of the sub-expression rooted at that node. We'll defer its implementation to the specific node classes as these will know best how to evaluate themselves.
We also want to format expressions so we will add another method to format the sub-expression in infix notation.
public interface ExprNode {
int evaluate();
String asInfixString();
}
Now, let's see what nodes we need. Certainly, any expression will contain numbers at the leafs so we'll better start defining a class for them. The implementation of ValueNode is really simple, not to say trivial.
public final class ValueNode implements ExprNode {
private final int value;
public ValueNode(final int value) {
this.value = value;
}
#Override
public int evaluate() {
return this.value;
}
#Override
public String asInfixString() {
return String.valueOf(this.value);
}
}
Next, we have our two binary operations + and *. The implementation of the respective classes is again very simple.
public final class PlusNode implements ExprNode {
private final ExprNode lhs;
private final ExprNode rhs;
public PlusNode(final ExprNode lhs, final ExprNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
#Override
public int evaluate() {
return this.lhs.evaluate() + this.rhs.evaluate();
}
#Override
public String asInfixString() {
return String.format("(%s) + (%s)",
this.lhs.asInfixString(),
this.rhs.asInfixString());
}
}
public final class TimesNode implements ExprNode {
private final ExprNode lhs;
private final ExprNode rhs;
public TimesNode(final ExprNode lhs, final ExprNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
#Override
public int evaluate() {
return this.lhs.evaluate() * this.rhs.evaluate();
}
#Override
public String asInfixString() {
return String.format("(%s) * (%s)",
this.lhs.asInfixString(),
this.rhs.asInfixString());
}
}
Equipped with that, we can elegantly build expression trees, print and evaluate them. Here is an example for the expression 2 * (3 + 4).
ExprNode expr = new TimesNode(
new ValueNode(2),
new PlusNode(new ValueNode(3), new ValueNode(4)));
System.out.println(expr.asInfixString() + " = " + expr.evaluate());
It will print (2) * ((3) + (4)) = 14.
So, for your ExprTree, you would simply check if the root != null and if so, return root.evaluate().
What if we want more expressions?
Clearly, we will define another sub-type of ExprNode. For example, we can define more binary operators to handle subtraction and division, another unary node for the unary minus and so on. Each of these classes must implement the interface dictated by ExprNode so any sub-class can be used the same way, encapsulating the logic how it evaluates itself.
What if we want more operations?
For example, we might want to format expressions in postfix notation. To be able to do this, we could add another method asPostfixString to ExprNode. However, this is a little awkward since it means we'll have to go and edit all sub-classes we have implemented so far, adding the new operation.
This is a rather fundamental problem. If you lay out a composite structure to encapsulate operations in the nodes, then it is elegant to use and simple to add new node types but difficult to add mode operations. If you are using a case selection in every operation (somewhat like in your code) then it is simpler to add new operations but the code for the operations gets convoluted and it is difficult to add more node types (the code for all operations needs to be altered). This dilemma is known as the tyranny of the dominant model decomposition. The visitor pattern is an attempt to break out of it.
Anyway, if you are taking a basic Java class, I think what you are expected to learn is implementing a polymorphic tree with operations defined in the nodes as shown above.

first common ancestor of two nodes in a binary tree

I was trying to solve the problem 4.7 from the book cracking the code interview (very cool book!).
Design an algorithm and write code to find the first common ancestor
of two nodes in a binary tree. Avoid storing additional nodes in a
data structure. NOTE: This is not necessarily a binary search tree.
And I came up with this solution which is not even close to the ones provided in the book. I wonder if someone can find any flaws on it?
Solution:
I created a wraper class to hold the first common ancestor (if its found) and 2 booleans to track if a or b was found when recoursively searching the tree. Please read added comments in the code below.
public static void main (String args[]){
NodeTree a, b, head, result; //initialise and fill with data
fillTreeTestData(head);
pickRandomNode(a);
pickRandomNode(b);
result = commonAnsestor(a,b,head);
if(result != null)
System.out.println("First common ansestor "+result);
else
System.out.println("Not found");
}
class TreeNode{
Object value;
TreeNode right, left;
}
class WraperNodeTree{
boolean found_a;
boolean found_b;
NodeTree n;
WraperNodeTree (boolean a, boolean b, NodeTree n){
this.n = n;
this.a = a;
this.b = b;
}
}
static WraperNodeTree commonAnsestor(NodeTree a, NodeTree b, NodeTree current){
// Let's prepare a wraper object
WraperNodeTree wraper = new WraperNodeTree(false, false, null);
// we reached the end
if(current == null) return wraper;
// let's check if current node is either a or b
if(a != null)
wraper.found_a = current.value.equals(a.value);
else if(b != null)
wraper.found_b = current.value.equals(b.value);
else
return wraper; // if both are null we don't need to keep searching recoursively
// if either a or b was found let's stop searching for it for performance
NodeTree to_search_a = wraper.found_a ? null : a;
NodeTree to_search_b = wraper.found_b ? null : b;
// let's search the left
WraperNodeTree wraperLeft = common(to_search_a,to_search_b,current.left);
// if we already have a common ancester just pass it back recoursively
if(wraperLeft.n != null) return wraperLeft;
WraperNodeTree wraperRight = common(to_search_a,to_search_b,current.right);
if(wraperRight.n != null)return wraperRight;
// keep the wraper up to date with what we found so far
wraper.a = wraper.found_a || wraperLeft.found_a || wraperRight.found_a;
wraper.b = wraper.found_b || wraperLeft.found_b || wraperRight.found_b;
// if both a and b were found, let's pass the current node as solution
if(wraper.found_a && wraper.found_b)
wraper.n = current;
return wraper;
}
If it's about finding flaws:
Flaw #1:
I think there are too many typos in your code, which may confuse the interviewer on their first read of the code (and you don't want that!). For example, you write 'NodeTree' and 'TreeNode' interchangeably. Also, you define 'commonAncestor()' and then call 'common()'. Those things make the interviewer confused and make him drift apart from the important thing, which is understanding your way of solving the problem.
Flaw #2: Typos aside, I think another flaw is that this code is difficult to follow. I think one of the reasons is because you have 'return' statements all over the body of your function (at the beginning, at the middle and at the end). This should 'normally' be avoided in favor of readability.
Usually my approach is to organize the code in the following way:
Basic border case checks (which might include return)
Main body of the function (which should NOT return under any conditions)
Last checks and final RETURN
But when you have return statements in the middle, it makes it harder for the reader to imagine the flow.
Flaw #3: I think you're trying to solve two problems with the same function (commonAncestor). You are trying to both search for 'a' and 'b' and also keeping track of the common ancestor. I think if this is an interview question, you could separate those two objectives in favor of simplicity.
For example, consider this code (might not be perfect and need some extra border checks):
/**
* [Assumption]: If we call firstCommonAncestor(a, b, root)
* we TRUST that root contains both a and b.
*
* You can (and should) discuss this
* assumption with your interviewer.
*/
public static Node firstCommonAncestor(Node a, Node b, Node root) {
// If root matches any of the nodes (a or b),
// then root is the first common ancestor
// (because of our assumption)
if(root == a || root == b) return root;
// Search for a and b in both sides
SearchResult leftResult = searchNodes(a, b, root.left);
SearchResult rightResult = searchNodes(a, b, root.right);
// If a and b are on the same side (left or right), then we
// call firstCommonAncestor on that side and that’s it
if(leftResult.aFound && leftResult.bFound)
return firstCommonAncestor(a, b, root.left);
else if(rightResult.aFound && rightResult.bFound)
return firstCommonAncestor(a, b, root.right);
else {
// If a and b are in different sides,
// then we just found the first common ancestor
return root;
}
}
class SearchResult {
boolean aFound, bFound;
}
On the code above, I'm separating the task of actually searching for 'a' and 'b' in a different function called searchNodes, which is fairly easy to implement if your interviewer asks for it. But he might not even do that. And if he does, at that point he already understood your approach, so it's easier now to "make the code a bit more complicated" without confusing the interviewer.
I hope this helps.

Develop a 2-3 search tree in java

I have been given an assignment to create a 2-3 search tree that is supposed to support a few different operations each divided in to different stages of the assignment.
For stage 1 I'm supposed to suport the operations get, put and size. I'm curently trying to implement the get operation but I'm stuck and I can't wrap my head around how to continue so I'm questioning all of my code I have written and felt like a need someone elses input.
I have looked around how to develop a 2-3 search tree but what I found was alot of code that made no sence to me or it just did not do what I needed it to do, and I wanted to try and make it for my self from scratch and here we are now.
My Node class
package kth.id2010.lab.lab04;
public class Node {
boolean isLeaf = false;
int numberOfKeys;
String[] keys = new String[2]; //each node can contain up to 2 keys
int[] values = new int[2]; //every key contains 2 values
Node[] subtrees = new Node[3]; //every node can contain pointers to 3 different nodes
Node(Node n) {
n.numberOfKeys = 0;
n.isLeaf = true;
}
}
My Tree creating class
package kth.id2010.lab.lab04;
public class Tree {
Node root; // root node of the tree
int n; // number of elements in the tree
private Tree(){
root = new Node(root);
n = 0;
}
//Return the values of the key if we find it
public int[] get(String key){
//if the root has no subtrees check if it contain the right key
if(this.root.subtrees.length == 0){
if(this.root.keys[0] == key){
return(this.root.keys[0].values);
}
else if(this.root.keys[1] == key){
return(this.root.keys[1].values);
}
}
//if noot in root, check its subtree nodes
//and here I can't get my head around how to traverse down the tree
else{
for(int i = 0; i < this.root.subtrees.length; i++){
for(int j = 0; j < this.root.subtrees[i].keys.length; j++){
if(this.root.subtrees[i].keys[j] == key){
return(this.root.subtrees[i].keys[j].values);
}
}
}
}
return null;
}
}
What I can tell for my self is that I need to find a way to bind values[] to each key but I can't figure out a way how. Might be the lack of sleep or that I'm stuck in this way of thinking.
bind values[] to each key
It might make more sense to use a HashMap to do that mapping for you, since that's what it's for. Beyond that, if you have two keys and each key has two values, you have 4 values, not 2 ;)
In general, the get method in a tree structure is almost always implementable recursively. Here is a very general implementation of a get algorithm for a 2-3 tree in psudo-code.
V get<K, V>(Node<K, V> node, K key)
{
if(node.is_leaf())
{
return node.keys.get(key); // This will either return the value, or null if the key isn't in the leaf and thus not in the tree
}
if(key < node.left_key)
{
return get(node.left_child, key); // If our key goes to the left, go left recursively
}
else if(node.two_node && key <= node.right_key)
{
return get(node.center_child, key) // If we have two keys, and we're less than the second one, we go down the center recursively
}
else
{
return get(node.right_child, key); // If we've gotten here, we know we're going right, go down that path recursively
}
}
That should get you started in the right direction. Insertion/deletion for 2-3 trees is a bit more complicated, but this should at least get your head around how to think about it. Hint; Your Node class needs to be doubly-linked, that is each node/leaf needs to reference its parent node as well as its children, and the root is simply a node whose parent is null.

Recursively determine if it is possible to find a target number

I will explain the title better for starters. My problem is very similar to the common: find all permutations of an integer array problem.
I am trying to find, given a list of integers and a target number, if it is possible to select any combination of the numbers from the list, so that their sum matches the target.
It must be done using functional programming practices, so that means all loops and mutations are out, clever recursion only. Full disclosure: this is a homework assignment, and the method header is set as is by the professor. This is what I've got:
public static Integer sum(final List<Integer> values) {
if(values.isEmpty() || values == null) {
return 0;
}
else {
return values.get(0) + sum(values.subList(1, values.size()));
}
}
public static boolean groupExists(final List<Integer> numbers, final int target) {
if(numbers == null || numbers.isEmpty()) {
return false;
}
if(numbers.contains(target)) {
return true;
}
if(sum(numbers) == target) {
return true;
}
else {
groupExists(numbers.subList(1, numbers.size()), target);
return false;
}
}
The sum method is tested and working, the groupExists method is the one I'm working on. I think it's pretty close, if given a list[1,2,3,4], it will return true for targets such as 3 and 10, but false for 6, which confuses me because 1,2,3 are right in order and add to 6. Clearly something is missing. Also, The main problem I am looking at is that it is not testing all possible combinations, for example, the first and last numbers are not being added together as a possibility.
UPDATE:
After working for a bit based on Simon's answer, this is what I'm looking at:
public static boolean groupExists(final List<Integer> numbers, final int target) {
if(numbers == null || numbers.isEmpty()) {
return false;
}
if(numbers.isEmpty()) {
return false;
}
if(numbers.contains(target)) {
return true;
}
if(sum(numbers.subList(1, numbers.size())) == (target - numbers.get(0))) {
return true; }
else {
return groupExists(numbers.subList(1, numbers.size()), target);
}
}
For convenience, declare
static Integer head(final List<Integer> is) {
return is == null || is.isEmpty()? null : is.get(0);
}
static List<Integer> tail(final List<Integer> is) {
return is.size() < 2? null : is.subList(1, is.size());
}
Then your function is this:
static boolean groupExists(final List<Integer> is, final int target) {
return target == 0 || target > 0 && head(is) != null &&
(groupExists(tail(is), target) || groupExists(tail(is), target-head(is)));
}
There are no surprises, really, regular checking of base cases plus the final line, where the left and right operands search for a "group" that does or does not, respectively, include the head.
The way I have written it makes it obvious at first sight that these are all pure functions, but, since this is Java and not an FP language, this way of writing it is quite suboptimal. It would be better to cache any function calls that occur more than once into final local vars. That would still be by the book, of course.
Suppose you have n numbers a[0], a[1], ..., a[n-1], and you want to find out if some subset sums to N.
Suppose you have such a subset. Now, either a[0] is included, or it isn't. If it's included, then there must exist a subset of a[1], ..., a[n] which sums to N - a[0]. If it isn't, then there exists a subset of a[1], ..., a[n] which sums to N.
This leads you to a recursive solution.
Checking all combinations is factorial (there's a bit missing on your implementation).
Why not try a different (dynamic) approach: see the Hitchhikers Guide to Programming Contests, page 1 (Subset Sum).
Your main method will be something like:
boolean canSum(numbers, target) {
return computeVector(numbers)[target]
}
computeVector return the vector with all numbers that can be summed with the set of numbers.
The method computeVector is a bit trickier to do recursively, but you can do something like:
boolean[] computeVector(numbers, vector) {
if numbers is empty:
return vector
addNumber(numbers[0], vector)
return computeVector(tail(numbers), vector);
}
addNumber will take vector and 'fill it' with the new 'doable' numbers (see hitchhikers for an explanation). addNumber can also be a bit tricky, and I'll leave it for you. Basically you need to write the following loop in recrusive way:
for(j=M; j>=a[i]; j--)
m[j] |= m[j-a[i]];
The lists of all possible combinations can be reached by asking a very simple decision at each recursion. Does this combination contain the head of my list? Either it does or it doesn't, so there are 2 paths at each stage. If either path leads to a solution then we want to return true.
boolean combination(targetList, sourceList, target)
{
if ( sourceList.isEmpty() ) {
return sum(targetList) == target;
} else {
head = sourceList.pop();
without = combination(targetList, sourceList, target); // without head
targetList.push(head);
with = combination(targetList, sourceList, target); // with head
return with || without;
}
}

Categories

Resources