This question already has answers here:
Handling parenthesis while converting infix expressions to postfix expressions
(2 answers)
Closed 6 years ago.
I coded up this program which will take an infix notation expression and build a binary tree from it. Right now the only input expression that actually works would be like 2 + 2. I can't seem to figure out at all how to make it handle parenthesis and take in longer expressions such as ( ( 2 + 2 ) * 3 ). For my output I am trying to get it into postfix notation and also evaluate the expression. So right now if I plug in 2 + 2 without the parenthesis my output is 22+ and it evaluates it so it prints 4.
I need to figure out a way for it to print out the output with spaces in between each number and operator and also get it to accept longer expressions with parenthesis. I have no idea right now how to continue from here. Can anyone please help me out?
Thanks!
This is my code:
class ExpressionEvaluator<T> {
ExpressionEvaluator() {
Scanner reader = new Scanner(System.in);
System.out.println("Enter your expression: ");
String expression = reader.nextLine(); // Reads the expression and trims the spaces.
expression = expression.replaceAll(" ", "");
ExpressTree<T> tree = new ExpressTree(expression); // Creates a new binary tree.
}
public static void main(String[] args) {
new ExpressionEvaluator();
}
}
interface Tree<T> {
// This is the tree interface with its methods.
public Node<T> getRoot();
public void setRoot(Node<T> value);
}
class ExpressTree<T> implements Tree<T> {
private Node<T> _root;
private String _value, _expression;
private Node<T> _treeNode;
private Stack storage1;
private Stack<String> storage2;
public ExpressTree(String expression) {
expressTreeBuilder(expression); // Calls the expressTreeBuilder method on the expression.
postfixTraversal(this.getRoot());
System.out.println("");
System.out.println(this.storage2.pop());
}
public Node<T> getRoot() { // Gets the root of the tree.
return _root;
}
public void setRoot(Node<T> _treeNode2) { // Sets the root which will always be an operator.
this._root = _treeNode2;
}
public boolean isDigit(char value) { // Method to check if a value is a digit or not.
if (Character.isDigit(value)) {
return true;
} else {
return false;
}
}
public void expressTreeBuilder(String expression) {
storage1 = new Stack(); // Stores the nodes.
storage2 = new Stack<String>(); // Stores the value of the nodes.
_treeNode = new Node(); // Creates a new node
_value = null;
String next = "";
for (int i = 0; i < expression.length(); i++) {
char traverse = expression.charAt(i);
if (i + 1 < expression.length()) {
next = Character.toString(expression.charAt(i + 1));
}
if (traverse == '+') { // This checks to see the expression is an addition operator.
Node<T> pop1, pop2; // It pops the first 2 values from the stack and stores them
String value1, value2; // in pop1 and pop2. Then it uses another stack to add them.
pop1 = (Node<T>) storage1.pop();
value1 = storage2.pop(); // Stores the right side value.
value2 = next; // Stores the left side value.
_treeNode = new Node();
_treeNode.setElement(Character.toString(traverse));
pop2 = new Node();
pop2.setElement(next);
pop1.setParent(_treeNode);
pop2.setParent(_treeNode);
_treeNode.setLeftSide(pop1); // Sets the right side of the subtree.
_treeNode.setRightSide(pop2); // Sets the left side of the subtree.
storage1.push(_treeNode);
storage1.push(pop2);
int add = (Integer.parseInt(value2) + Integer.parseInt(value1));
storage2.push(Integer.toString(add));
this.setRoot(_treeNode);
i++;
} else if (traverse == '-') { // This checks to see the expression is a subtraction operator.
Node<T> pop1, pop2; // It pops the first 2 values from the stack and stores them
String value1, value2; // in pop1 and pop2. Then it uses another stack to subtract them.
pop1 = (Node<T>) storage1.pop();
value1 = storage2.pop(); // Stores the right side value.
value2 = next; // Stores the left side value.
_treeNode = new Node();
_treeNode.setElement(Character.toString(traverse));
pop2 = new Node();
pop2.setElement(next);
pop1.setParent(_treeNode);
pop2.setParent(_treeNode);
_treeNode.setLeftSide(pop1); // Sets the right side of the subtree.
_treeNode.setRightSide(pop2); // Sets the left side of the subtree.
storage1.push(_treeNode);
storage1.push(pop2);
int subtract = (Integer.parseInt(value2) - Integer.parseInt(value1));
storage2.push(Integer.toString(subtract));
this.setRoot(_treeNode);
i++;
} else if (traverse == '*') { // This checks to see the expression is a multiplication operator.
Node<T> pop1, pop2; // It pops the first 2 values from the stack and stores them
String value1, value2; // in pop1 and pop2. Then it uses another stack to multiply them.
pop1 = (Node<T>) storage1.pop();
value1 = storage2.pop(); // Stores the right side value.
value2 = next; // Stores the left side value.
_treeNode = new Node();
_treeNode.setElement(Character.toString(traverse));
pop2 = new Node();
pop2.setElement(next);
pop1.setParent(_treeNode);
pop2.setParent(_treeNode);
_treeNode.setLeftSide(pop1); // Sets the right side of the subtree.
_treeNode.setRightSide(pop2); // Sets the left side of the subtree.
storage1.push(_treeNode);
storage1.push(pop2);
int multiply = (Integer.parseInt(value2) * Integer.parseInt(value1));
storage2.push(Integer.toString(multiply));
this.setRoot(_treeNode);
i++;
} else if (traverse == '(') {
} else {
_treeNode = new Node();
String digits = "";
while (i < expression.length() && isDigit(expression.charAt(i))) {
digits += expression.charAt(i); // Checks if the value found at the expression is digit
if (digits.length() == 1) {
break;
}
i++;
}
_treeNode.setElement(digits); // If it is it will set the element of the node
storage1.push(_treeNode); // The node will be pushed onto the stack.
storage2.push(digits); // This node will store it's value.
}
}
}
public void infixTraversal(Node<T> n) {
if (n != null) {
infixTraversal(n.getLeftSide());
System.out.print(n.element() + "");
infixTraversal(n.getRightSide());
}
}
public void postfixTraversal(Node<T> n) {
if (n != null) {
postfixTraversal(n.getLeftSide());
postfixTraversal(n.getRightSide());
System.out.print(n.element());
}
}
}
class Node<T> {
public Node<T> _left, _right, _parent;
private String _element;
public Node() {
this._element = null;
this._left = null;
this._right = null;
this._parent = null;
}
public String element() { // Gets the value of the node.
return _element;
}
public Node<T> getLeftSide() { // Gets the left side of the node.
return _left;
}
public Node<T> getRightSide() { // Gets the right side of the node.
return _right;
}
public Node<T> getParent() { // Gets the parent of the node.
return _parent;
}
public void setElement(String e) { // Sets the value of the node.
_element = e;
}
public void setLeftSide(Node<T> n) { // Sets the left side of the node.
_left = n;
}
public void setRightSide(Node<T> n) { // Sets the right side of the node.
_right = n;
}
public void setParent(Node<T> n) { // Sets the parent of the node.
_parent = n;
}
}
You will need a proper algorithm for converting your infix expression into a postfix expression. Once you have the expression in postfix it's a fairly easy matter of constructing a parse tree or evaluate the expression outright. A classic algorithm is the Shunting-yard algorithm, which is explained in quite extensive detail on wikipedia.
Once the algorithm to postfix is completed you do no longer have to worry about parathesis or operator precedence. It's just a stack of values and popping and pushing results.
There are several different problems in your question :
1) Parsing an expression and breaking it down into a tree. You need a lexer (or tokenizer) for this, even a simple one, which takes of precedence, parentheses, etc.
2) Converting/Evaluating your tree. There are some good classical algorithms for this.
3) Printing the outcomes (which I suspect is fairly simple once you have part 2 done; it's just a matter of adding the correct whitespaces and parentheses at the right places).
I would suggest to read some existing articles about all of this, let's say for instance :
http://www.javaworld.com/javaworld/jw-01-1997/jw-01-indepth.html (on Lexical Analysis)
http://www.javaworld.com/javaworld/jw-05-1997/jw-05-indepth.html (on building a parse tree and an interpreter)
Related
I am trying to create a binary tree that takes strings but it uses "-" and "+" to go left or right if the sign is + insert left and if it's - then insert right. Here is a visual representation of what I am trying to do.
insert method should take the word and just a single sign for now and based of that insert right or left
Here is my code but I am getting nullpointer error. Apparently, I am not inserting into the right order
public class BinaryTree {
private static Node root = null;
private static Node sign = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
BinaryTree bt = new BinaryTree();
bt.insert("to", "-");
bt.insert("the", "+");
bt.preorder();
}
private class Node {
String data;
String sign;
Node left;
Node right;
public Node(String w) {
data = w;
left = right = null;
}
// public Node(String w, String s) {
// data = w;
// sign = s;
// left = right = null;
//
// }
} // -----------------end of Node
private void insert(String val, String sign) {
root = insert(root, val, sign);
}
Node insert(Node r, String data, String passSign) {
if (r == null) {
return new Node(data);
}
if(r.sign.equals(passSign)) {
r.right = insert(r.right, data, passSign);
}
else if (r.sign.equals(passSign)){
r.left = insert(r.left, data, passSign);
}
return r;
}
public void preorder() {
preorder(root);
}
public void preorder(Node p) {
if (p != null) {
System.out.println(p.data);
preorder(p.left);
preorder(p.right);
}
}
}
The main problems are:
The BinaryTree nor the Node instances should have a sign member. The sign only plays a role during the insertion process, but has no meaning any more once a node is inserted
r.sign.equals(passSign) is therefore also not the correct condition to check. According to your description you should just check whether the sign is a "-" and go right, or else go left ("+"). There is no state of the node that influences this decision. So do passSign.charAt(0) == '-' instead.
When making the recursive call you should not pass the same sign again: it has already been processed. Instead, pass any signs that follow after the consumed one. You can use substring for that purpose.
The image shows a root node that has no value. Yet you are right in creating a tree instance with no node at all. So your insert method should deal with the case where the root is null, but the sign argument is not the empty string. In that case a root node should be created, but it should not hold the target data, as for that we should still go deeper in the tree. This principle could apply to any node, not only the root. So foresee the creation of such "place-holder" nodes and give them some default value (like "(null)").
Not a problem, but I find it more useful to print in inorder order, and indent the deeper nodes. This way you get an idea how the tree is structured.
Here is the corrected code:
public class BinaryTree {
private static Node root = null;
// No sign member needed;
public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.insert("to", "-");
bt.insert("the", "+");
bt.insert("buy", "-+");
bt.insert("imperial", "+-");
bt.insert("afflication", "++");
bt.inorder();
}
private class Node {
String data;
// No sign member needed;
Node left;
Node right;
public Node(String w) {
data = w;
left = right = null;
}
}
private void insert(String val, String sign) {
root = insert(root, val, sign);
}
Node insert(Node r, String data, String passSign) {
// Check whether there is a sign
if (passSign.length() == 0) {
return new Node(data);
}
// If needed, create a placeholder node so to be able to descend further
if (r == null) {
r = new Node("(null)");
}
if (passSign.charAt(0) == '-') {
// Extract the rest of the signs
r.right = insert(r.right, data, passSign.substring(1, passSign.length()));
}
else {
r.left = insert(r.left, data, passSign.substring(1, passSign.length()));
}
return r;
}
public void inorder() {
inorder(root, "");
}
// This method gives a bit more visual output
public void inorder(Node p, String indent) {
if (p != null) {
inorder(p.left, indent + " ");
System.out.println(indent + p.data);
inorder(p.right, indent + " ");
}
}
}
I have a function that receives a binary expression tree and returns a String with the expression in-order. The only "problem" is that the resulting expression have too many parentheses,
e.g.: The function returns (a + (b * c)), but it can be reduced to a + b * c.
It is defined with the binary operators +, -, *, /, and the unary operator _ (negative).
What I really want to know is if I can modify the already existing function to reduce the number of parentheses in an efficient way, or create another function that operates with the String of the in-order expression.
The function is as follows:
private static String infijo(ArbolB t){
String s = "";
if (t != null) {
String info = String.valueOf(t.info);
if ("+-*/".contains(info)) s += "(";
if ("_".contains(info)) s += "-(";
s += infijo(t.left) + (info.equals("_") ? "" : info) + infijo(t.right);
if ("+-*/_".contains(String.valueOf(t.info))) s += ")";
}
return s;
}
Where ArbolB is a binary tree defined by:
public class ArbolB {
ArbolB right;
ArbolB left;
Object info;
public ArbolB(Object info, ArbolB right, ArbolB left){
this.info = info;
this.right = right;
this.left = left;
}
}
After writing this whole thing out, I realized that I didn't really answer your question properly (my solution ignores PEMDAS and just matches pairs, d'oh!). So, take from this what you can... I'm not throwing it out :P
I think you COULD solve this either way, but here would be my preferred method, using and trusting what you already have. There's probably a good way to use nodes to do this, but why not use what you have, right?
Starting from the point where you have your expression as a string (e.g. "((2*2) + _(3+3))" you could try something like:
public string RemoveUnnecessaryParens(string expression)
{
readonly string openParen = "(";
readonly string closeParen = ")";
// char array would also work for this
// multiple ways to track "balance" of parens, lets use int
int unclosedParenCount = 0;
string toReturn = "";
// iterate through the expression
for (int i = 0; i < expression.Length; i++)
{
string current = expression.Substring(i,1);
if (openParen == current)
unclosedParenCount++;
else if (closedParen == current)
unclosedParenCount--;
else
toReturn += current;
if (unclosedParenCount < 0) throw new UnbalancedExpressionException(); // One more close than open! Uh oh!
}
if (0 != unclosedParenCount) throw new UnbalancedExpressionException(); // One more open than close at the end! Uh oh!
else return toReturn;
}
Make sense?
Well, after thinking it a while, I got to a solution myself, by adding a priority function for determining when parentheses were necessary, and a variable that indicates if the operation was on the left or the right side of the formula, this because a-b+c don't need parentheses, but c+(a-b) do need them.
private static String infijo(ArbolB t, int priority, boolean right) {
String s = "";
int oP = 0;
if (t != null) {
String info = String.valueOf(t.info);
int pi = priority(info);
if ("+-*/".contains(info)) {
/* this only adds parentheses if the operation has higher priority or if the
operation on the right side should be done before the one on the left side*/
if ("+-*/".contains(info)) {
if (pi/2 < priority/2) s += "(";
else s += pi/2 == priority/2 && pi != priority && right ? "(" : "";
oP = priority; //stores the old priority
priority= pi; //priority of the new operator
}
}
if ("_".contains(info)) {
s += "-";
oP = priority;
priority = pi;
}
s += infijo(t.left, priority, false) + (info.equals("_") ? "" : info)
+ infijo(t.right, priority, true);
if ("+-*/".contains(info)) {
// adds the closing parentheses following the same rules as for the opening ones
if (priority / 2 < oP / 2) s += ")";
else s += priority / 2 == oP / 2 && priority != oP && right ? ")" : "";
}
}
return s;
}
private static int priority(String op) {
if ("_".contains(op)) return 4;
if ("/".contains(op)) return 3;
if ("*".contains(op)) return 2;
if ("-".contains(op)) return 1;
return 0;
}
#Override
public String toString() {
ArbolB f = getFormula(); //this returns the Binary Expression Tree
return infijo(f, Integer.MIN_VALUE, false);
}
I'm attempting to write a pre-order traversal algorithm on a binary tree using the recursive method. Here's what I have:
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
That doesn't compile for some reason. I think the problem is with the rest of my code. Here's the entire code:
class ZOrep extends TreeAndRepresentation {
private int k;
ZOrep left;
ZOrep right;
ZOrep( int m, int[] b ) { // given sequence build tree
super( m, b );
N = (M-1)/2;
k = -1;
t = build();
}
ZOrep( int n, BT t ) { // given tree build sequence
super(n, t);
t = build();
traverse( t );
}
BT build() {
return(a[++k] == 0 ? null : new BT( build(), build() ));
}
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
}
I feel like I'm missing something when I'm building the tree (with my ZOrep method). Also here's the BT class:
class BT {
BT L; BT R;
BT( BT l, BT r ) { L = l; R = r; }
}
Currently my compiler says it can't find the symbol for t.left and t.right.
When the compiler says it can't find the symbol, it means the field you're trying to reference doesn't exist.
Looking at your class BT, this is correct; BT doesn't have left or right, it has L and R. Thus, replacing
traverse(t.left);
traverse(t.right);
with
traverse(t.L);
traverse(t.R);
Will fix this issue.
Currently my compiler says it can't find the symbol for t.left and t.right.
This is because t is a BT and it doesn't have a left and a right.
I suggest you decide what you want to call your tree node class. Is it ZOrep or BT and only use one of these or you will create confusion.
System.out.print(t);
If you want to print out a BT, you will need to add a toString() method to it as the default won't tell you anything useful.
What are you passing into your transverse function? If it's a BT object, then you can't use left and right, you must use L and R. Left and right are parts of your object that extends from BT, but it looks like you're passing in a BT.
// Java
static String tree = "";
private static void preOrder(HuffTree currentObject) {
if (currentObject == null) {
return;
}
if (currentObject.filling == null) tree += 1;
else tree += 0;
preOrder(currentObject.child0);
preOrder(currentObject.child1);
}
}
// class code here
import java.util.Objects;
/**
Huffman tree as class
*/
class HuffTree implements Comparable {
// element filling
Byte filling;
// element repeats
int repeats;
// zero child
HuffTree child0;
// child 1
HuffTree child1;
/**
* constructor for tree fathers and leaves
*/
public HuffTree(Byte filling, int repeats, HuffTree child0, HuffTree child1) {
// father filling
this.filling = filling;
// father repeats
this.repeats = repeats;
// zero child
this.child0 = child0;
// child 1
this.child1 = child1;
}
/**
* finding difference between our tree's items
*/
#Override
public int compareTo(HuffTree currentByte) {
return currentByte.repeats - repeats;
}
/**
* take byte code as a string by recursive three search in depth
*/
public String getCodeForByte(Byte currentByte, String wayToFather) {
// there is 4 cases:
if (!Objects.equals(filling, currentByte)) {
// case 1 - zero child found
if (child0 != null) {
// recursive code add for zero child
String currentWay = child0.getCodeForByte(currentByte, wayToFather + "0");
// return temporary string
if (currentWay != null) return currentWay;
}
// case 2 - child 1 found. recursive code add for child 1. return temporary string
if (child1 != null) return child1.getCodeForByte(currentByte, wayToFather + "1");
}
// case 3 - correct leaf found. return correct code
if (Objects.equals(filling, currentByte)) return wayToFather;
// case 4 - wrong leaf found. return null
return null;
}
}
I have four classes.
One contains my linkedstack setup
One is infixtopostfix for prioritization and conversion
Parenthesis for matching
Postfix for evaluation
I have setup almost everything here but it is still returning false anyway I put it.
On another note my equals on !stackMatch.pop().equals(c) is not working due to it being a object type with '!' being a problem.
My programs are simple and straight forward:
LinkedStack.java
public class LinkedStack implements StackInterface {
private Node top;
public LinkedStack() {
top = null;
} // end default constructor
public boolean isEmpty() {
return top == null;
} // end isEmpty
public void push(Object newItem) {
Node n = new Node();
n.setData(newItem);
n.setNext(top);
top = n;
} // end push
public Object pop() throws Exception {
if (!isEmpty()) {
Node temp = top;
top = top.getNext();
return temp.getData();
} else {
throw new Exception("StackException on pop: stack empty");
} // end if
} // end pop
public Object peek() throws Exception {
if (!isEmpty()) {
return top.getData();
} else {
throw new Exception("StackException on peek: stack empty");
} // end if
} // end peek
} // end LinkedStack
InfixToPostfix.java
import java.util.*;
public class InfixToPostfix {
Parenthesis p = new Parenthesis();
LinkedStack stack = new LinkedStack();
String token = ""; // each token of the string
String output = ""; // the string holding the postfix expression
Character topOfStackObject = null; // the top object of the stack, converted to a Character Object
char charValueOfTopOfStack = ' '; // the primitive value of the Character object
/**
* Convert an infix expression to postfix. If the expression is invalid, throws an exception.
* #param s the infix expression
* #return the postfix expression as a string
* hint: StringTokenizer is very useful to this iteratively
*/
//public String convertToPostfix(String s) throws Exception {
//}
private boolean isOperand (char c){
return ((c>= '0' && c <= '9') || (c >= 'a' && c<= 'z'));
}
public void precedence(char curOp, int val) throws Exception {
while (!stack.isEmpty()) {
char topOp = (Character) stack.pop();
// charValueOfTopOfStack = topOfStackObject.charValue();
if (topOp == '(') {
stack.push(topOp);
break;
}// it's an operator
else {// precedence of new op
int prec2;
if (topOp == '+' || topOp == '-') {
prec2 = 1;
} else {
prec2 = 2;
}
if (prec2 < val) // if prec of new op less
{ // than prec of old
stack.push(topOp); // save newly-popped op
break;
} else // prec of new not less
{
output = output + topOp; // than prec of old
}
}
}
}
Parenthesis.java
import java.util.*;
public class Parenthesis{
private LinkedStack stack = new LinkedStack();
private Object openBrace;
private String outputString;
/**
* Determine if the expression has matching parenthesis using a stack
*
* #param expr the expression to be evaluated
* #return returns true if the expression has matching parenthesis
*/
public boolean match(String expr) {
LinkedStack stackMatch = new LinkedStack();
for(int i=0; i < expr.length(); i++) {
char c = expr.charAt(i);
if(c == '(')
stackMatch.push(c);
else if(c == ')'){
if (stackMatch.isEmpty() || !stackMatch.pop().equals(c))
return false;
}
}
return stackMatch.isEmpty();
}
}
Just wanted to give you all of it so you could help me. I have tests written already just struggling with the parenthesis problem of pushing it on the stack but unable to compare it to the closing parenthesis so it can check if there is enough while checking to be sure it is not empty.
The problem probably is, that you are trying to test if matching ( is currently on top of the stack when ) comes, but in c is acctual character, ), so you test if ) is on top of stack, not ( as you should.
I know that you can simply solve this question iteratively by using a counter to increment each time you pass a node in linkedlist; also creating an arraylist and setting the data found with each node inside it. Once you hit the tail of the linkedlist, just minus the Nth term from the total number of elements in the arraylist and you will be able to return the answer. However how would someone perform this using recursion? Is it possible and if so please show the code to show your genius :).
Note: I know you cannot return two values in Java (but in C/C++, you can play with pointers :])
Edit: This was a simple question I found online but I added the recursion piece to make it a challenge for myself which I've come to find out that it may be impossible with Java.
The trick is to do the work after the recursion. The array in the private method is basically used as a reference to a mutable integer.
class Node {
Node next;
int data;
public Node findNthFromLast(int n) {
return findNthFromLast(new int[] {n});
}
private Node findNthFromLast(int[] r) {
Node result = next == null ? null : next.findNthFromLast(r);
return r[0]-- == 0 ? this : result;
}
}
As a general rule, anything that can be done with loops can also be done with recursion in any reasonable language. The elegance of the solution may be wildly different. Here is a fairly java idiomatic version. I've omitted the usual accessor functions for brevity.
The idea here is to recur to the end of the list and increment a counter as the recursion unwinds. When the counter reaches the desire value, return that node. Otherwise return null. The non-null value is just returned all the way tot the top. Once down the list, once up. Minimal arguments. No disrespect to Adam intended, but I think this is rather simpler.
NB: OP's statement about Java being able to return only one value is true, but since that value can be any object, you can return an object with fields or array elements as you choose. That wasn't needed here, however.
public class Test {
public void run() {
Node node = null;
// Build a list of 10 nodes. The last is #1
for (int i = 1; i <= 10; i++) {
node = new Node(i, node);
}
// Print from 1st last to 10th last.
for (int i = 1; i <= 10; i++) {
System.out.println(i + "th last node=" + node.nThFromLast(i).data);
}
}
public static void main(String[] args) {
new Test().run();
}
}
class Node {
int data; // Node data
Node next; // Next node or null if this is last
Node(int data, Node next) {
this.data = data;
this.next = next;
}
// A context for finding nth last list element.
private static class NthLastFinder {
int n, fromLast = 1;
NthLastFinder(int n) {
this.n = n;
}
Node find(Node node) {
if (node.next != null) {
Node rtn = find(node.next);
if (rtn != null) {
return rtn;
}
fromLast++;
}
return fromLast == n ? node : null;
}
}
Node nThFromLast(int n) {
return new NthLastFinder(n).find(this);
}
}
Okay, I think think this should do the trick. This is in C++ but it should be easy to translate to Java. I also haven't tested.
Node *NToLastHelper(Node *behind, Node *current, int n) {
// If n is not yet 0, keep advancing the current node
// to get it n "ahead" of behind.
if (n != 0) {
return NToLastHelper(behind, current->next, n - 1);
}
// Since we now know current is n ahead of behind, if it is null
// the behind must be n from the end.
if (current->next == nullptr) {
return behind;
}
// Otherwise we need to keep going.
return NToLastHelper(behind->next, current->next, n);
}
Node *NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n);
}
edit: If you want to return the value of the last node, you can just change it to:
int NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n)->val;
}
This code will fail badly if node is null.
The recursion function:
int n_to_end(Node *no, int n, Node **res)
{
if(no->next == NULL)
{
if(n==0)
*res = no;
return 0;
}
else
{
int tmp = 1 + n_to_end(no->next, n, res);
if(tmp == n)
*res = no;
return tmp;
}
}
The wrapper function:
Node *n_end(Node *no, int n)
{
Node *res;
res = NULL;
int m = n_to_end(no, n, &res);
if(m < n)
{
printf("max possible n should be smaller than or equal to: %d\n", m);
}
return res;
}
The calling function:
int main()
{
List list;
list.append(3);
list.append(5);
list.append(2);
list.append(2);
list.append(1);
list.append(1);
list.append(2);
list.append(2);
Node * nth = n_end(list.head, 6);
if(nth!=NULL)
printf("value is: %d\n", nth->val);
}
This code has been tested with different inputs. Although it's a C++ version, you should be able to figure out the logic :)