Finding the 'maximum' character in a linked list Java recursively - java

I am trying to find the "maximum" value in a linked list recursively using a helper function. I am just starting to learn about these in my class and am pretty confused. We have a custom class that defines the type Node and another function to calculate the size of the Node or linkedlist. I solved this problem when I was comparing integers, but with characters I am lost. Here is my code:
'''
static class Node {
public Node (char item, Node next) { this.item = item; this.next = next; }
public char item;
public Node next;
}
Node first; // this is the only instance variable,
// the access point to the list
// size
//
// a function to compute the size of the list, using a loop
// an empty list has size 0
public int size () {
int count = 0;
for (Node tmp = first; tmp != null; tmp = tmp.next)
count++;
return count;
}
/*
* maxCharacter
*
* a function to compute the 'maximum' character in the list using recursion
* You will want to create a helper function to
* do the recursion
*
* precondition: list is not empty
*
* Examples:
* ["ababcdefb"].maxCharacter() == 'f'
* ["eezzg"].maxCharacter() == 'z'
* ["a"].maxCharacter() == 'a'
*/
public char maxCharacter () {
return maxCharacterHelper(first, first.size());
}
public char maxCharacterHelper(Node first, int index) {
char[] alpha = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int max = 0;
while(index > 0 )
max = alpha.indexOf(first.item) > max ? first.item : max;
maxCharacterHelper(first, index-1);
return max;
}
'''
If you could explain how I would loop through the list recursively while maintaining the greatest char I would greatly appreciate it.

The golden rule with recursion is "Think of the base case first, then write the recurrence".
In this case, the base is the empty list. In this case, the maximum is the last value you've seen.
The recurrence is just a call to the rest of the list with the highest value you've called.
public static MaxNode(Node n, char currentMax) {
if (n == null) // base case, we're at the end.
return currentMax;
// recurrence
return MaxNode(n.next, currentMax > n.item ? currentMax : n.item);
}
For simple ASCII values, you can treat the maximum using the > operator.

Your while loop is confusing because of indentation and because you never change index. However, I don't think you need it if your intent is to use recursion. Generally with recursion you need to establish a base case from which you cannot recurse. For a linked list the natural base case is where there is no next node, rather than index-based.
if (current.next == null)
return alpha.indexOf(current.item);
Otherwise combine the recursion return with the current value
int remainingMax = maxCharacterHelper(current);
int currentValue = alpha.indexOf(current.item);
return (remainingMax > currentValue) ? remainingMax : currentValue;
Here is how I would put it together
//I made it static because it is not a method of a specific Node
public static int maxCharacterHelper(Node currentNode){
// remaining list includes only current node, so this one has max value
if (current.next == null)
return alpha.indexOf(current.item);
//otherwise take the larger of remaining list and current node
int remainingMax = maxCharacterHelper(current.next);
int currentValue = alpha.indexOf(current.item);
return (remainingMax > currentValue) ? remainingMax : currentValue;
}

Related

Solution timing out for question: build binary tree from inorder and postorder

I've been grinding leetcode recently and am perplexed on why my solution is timing out when I submit it to Leetcode.
Here is the question:
https://leetcode.com/explore/learn/card/data-structure-tree/133/conclusion/942/
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
Here is my solution that times out in one of the test cases:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder == null || inorder.length == 0) {
return null; // input error
}
if (postorder == null || postorder.length == 0) {
return null; // input error
}
if (postorder.length != inorder.length) {
return null; // input error
}
List<Integer> inOrder = new ArrayList<Integer>();
List<Integer> postOrder = new ArrayList<Integer>();
for (int i = 0; i < inorder.length; i++) {
inOrder.add(inorder[i]);
postOrder.add(postorder[i]);
}
return buildBinaryTree(inOrder, postOrder);
}
public TreeNode buildBinaryTree(List<Integer> inOrder, List<Integer> postOrder) {
boolean found = false;
int root = 0;
int rootIndex = 0;
// for given in-order scan the post-order right to left to find the root
for (int j = postOrder.size() - 1; j >= 0 && !found; j--) {
root = postOrder.get(j);
if (inOrder.contains(root)) {
rootIndex = inOrder.indexOf(root);
root = inOrder.get(rootIndex);
found = true;
break;
}
}
if (found) {
List<Integer> leftOfRoot = new ArrayList<Integer>();
List<Integer> rightOfRoot = new ArrayList<Integer>();
if (rootIndex > 0) {
leftOfRoot.addAll(inOrder.subList(0, rootIndex));
}
if ((rootIndex + 1) < inOrder.size()) {
rightOfRoot.addAll(inOrder.subList(rootIndex + 1, inOrder.size()));
}
TreeNode node = new TreeNode(root);
node.left = buildBinaryTree(leftOfRoot, postOrder);
node.right = buildBinaryTree(rightOfRoot, postOrder);
return node;
}
return null;
}
}
Can anyone help determine why this is happening? I'm thinking it is the Leetcode judge at fault here and my code is fine.
Leetcode's judge is probably OK. This code is too casual about nested linear array operations and heap allocations. Creating ArrayLists and calling contains, addAll, subList and indexOf may appear innocuous, but they should all be thought of as extremely expensive operations when inside a recursive function that spawns two child calls in every frame.
Let's unpack the code a bit:
List<Integer> inOrder = new ArrayList<Integer>();
List<Integer> postOrder = new ArrayList<Integer>();
for (int i = 0; i < inorder.length; i++) {
inOrder.add(inorder[i]);
postOrder.add(postorder[i]);
}
This is a minor up-front cost but it's an omen of things to come. We've done 2 heap allocations that weren't necessary and walked n. I'd stick to primitive arrays here--no need to allocate objects other than the result nodes. A lookup map for inOrder with value -> index pairs might be useful to allocate if you feel compelled to create a supporting data structure here.
Next, we step into buildBinaryTree. Its structure is basically:
function buildBinaryTree(root) {
// do some stuff
if (not base case reached) {
buildBinaryTree(root.left)
buildBinaryTree(root.right)
}
}
This is linear on the number of nodes in the tree, so it's important that // do some stuff is efficient, hopefully constant time. Walking n in this function would give us quadratic complexity.
Next there's
for (int j = postOrder.size() - 1; j >= 0 && !found; j--) {
root = postOrder.get(j);
if (inOrder.contains(root)) {
rootIndex = inOrder.indexOf(root);
This looks bad, but by definition the root is always the last element in a postorder traversal array, so if we keep a pointer to it, we can remove this outer loop. You can use indexOf directly and avoid the contains call since indexOf returns -1 to indicate a failed search.
The code:
if (found) {
List<Integer> leftOfRoot = new ArrayList<Integer>();
List<Integer> rightOfRoot = new ArrayList<Integer>();
does more unnecessary heap allocations for every call frame.
Here,
leftOfRoot.addAll(inOrder.subList(0, rootIndex));
Walks the list twice, once to create the sublist and again to add the entire sublist to the ArrayList. Repeat for the right subtree for two full walks on n per frame. Using start and end indices per call frame means you never need to allocate heap memory or copy anything to prepare the next call. Adjust the indices and pass a reference to the same two arrays along the entire time.
I recommend running your code with a profiler to see exactly how much time is spent copying and scanning your ArrayLists. The correct implementation should do at most one walk through one of the lists per call frame to locate root in inOrder. No array copying should be done at all.
With these modifications, you should be able to pass, although wrangling the pointers for this problem is not obvious. A hint that may help is this: recursively process the right subtree before the left.
Yes, it would be much faster with arrays. Try this:
public static TreeNode buildTree(int[] inorder, int[] postorder, int start,
int end) {
for (int i = postorder.length-1; i >= 0; --i) {
int root = postorder[i];
int index = indexOf(inorder, start, end, root);
if (index >= 0) {
TreeNode left = index == start
? null
: buildTree(inorder, postorder, start, index);
TreeNode right = index+1 == end
? null
: buildTree(inorder, postorder, index+1, end);
return new TreeNode(root, left, right);
}
}
return null;
}
private static int indexOf(int[] array, int start, int end, int value) {
for (int i = start; i < end; ++i) {
if (array[i] == value) {
return i;
}
}
return -1;
}

How to make a move on a gameboard from MiniMax Alpha-Beta's returned value?

The game I'm talking about is something similar to Gomoku or a "large", simplified version of Tic-Tac-Toe. Basically, you have an 8x8 board and the winner is the one that chains 4 in a row or column (no diagonal).
I've set up a minimax with alpha-beta pruning, the problem I have is that I'm not sure how returned values can let you know which move to make. Or like how to connect values to a move.
Currently, I've considered returning a GameStateNode instead. With the GameStateNode having fields: char[][] (the current state of the board), evaluationVal(the value of the current state when it is not a terminal node).
But I still can't think of a way to use the returned node to decide on the best move.
// Alpha-Beta Pruning Search
private static Node alphaBeta(Node initial, int depth) {
Node bestMove = max(initial, depth, NEGATIVE_INFINITY, POSITIVE_INFINITY);
return bestMove;
}
private static Node max(Node n, int depth, int alpha, int beta) {
int value = NEGATIVE_INFINITY;
Node currentBestMove = null;
Node temp = null;
// Terminal state
if(n.fourInALine() != 0) {
return n;
}
// Depth limit reached
if(depth == 0) {
return n;
}
ArrayList<Node> successors = n.generateSuccessors('X');
// Iterate through all the successors, starting with best evaluationValues
for(Node s : successors) {
temp = min(s, depth - 1, alpha, beta);
if(temp.evaluationVal > value) {
value = temp.evaluationVal;
currentBestMove = temp;
}
alpha = Math.max(alpha, value);
if(alpha >= beta) {
break;
}
}
return currentBestMove;
}
// I have similar min method just with the correct comparison
You cannot get the move information out of the returned bestMove because that Node represents the position of the board after depth moves. If you diff bestMove's position and initial's position, you will find multiple differences, and you won't be able to tell what order the moves were played in.
To get the move to play out of your search code:
Add a boolean isRoot parameter to max() to tell the method whether it is called directly from alphaBeta() and n is the search tree's root node.
In max(), if isRoot is true, instead of keeping track of the best temp (the Node returned from min()) for currentBestMove, keep track of the best s (the Node from n.generateSuccessors()).
In alphaBeta(), take bestMove (the Node returned from max()) and diff its state array against initial. Find the coordinates of the slot where bestMove has an 'X' and initial doesn't.
That is the move to play.
Code:
private static int[] alphaBeta(Node initial, int depth) {
Node bestMove = max(initial, depth, NEGATIVE_INFINITY, POSITIVE_INFINITY, true);
for(int i = 0; i < bestMove.state.length; i++) {
for(int j = 0; j < bestMove.state[i].length; j++) {
if(bestMove.state[i][j] != initial.state[i][j]) {
return new int[] { i, j };
}
}
}
}
private static Node max(Node n, int depth, int alpha, int beta, boolean isRoot) {
int value = NEGATIVE_INFINITY;
Node currentBestMove = null;
Node temp = null;
// Terminal state
if(n.fourInALine() != 0) {
return n;
}
// Depth limit reached
if(depth == 0) {
return n;
}
ArrayList<Node> successors = n.generateSuccessors('X');
// Iterate through all the successors, starting with best evaluationValues
for(Node s : successors) {
temp = min(s, depth - 1, alpha, beta);
if(temp.evaluationVal > value) {
value = temp.evaluationVal;
currentBestMove = isRoot ? s : temp;
}
alpha = Math.max(alpha, value);
if(alpha >= beta) {
break;
}
}
return currentBestMove;
}
// I have a similar min() method with the opposite comparison,
// and without an isRoot argument.
Note that none of this is tested, at all.

LinkedList function from InterviewBit

I'm struggling with my solution for a question on InterviewBit.
I linked to the full description, but in short:
1) You are given the head node of a linkedlist
2) take the first half of the list and change the values so that:
"1st node’s new value = the last node’s value - first node’s current value
2nd node’s new value = the second last node’s value - 2nd node’s current value"
Here is my approach (it compiles but does not mutate the list at all)
I see that my method does not actually modify the original list -- it seems like what I'm doing is making a new list with the correctly altered values, but not changing the original.
/**
* Definition for singly-linked list.
* class ListNode {
* public int val;
* public ListNode next;
* ListNode(int x) { val = x; next = null; }
* }
*/
public class Solution {
public ListNode subtract(ListNode a) {
ListNode current = a;
int length = 0;
//get length
while(current.next != null){
length++;
current = current.next;
}
length += 1;
while(current.next != null){
double half = Math.floor(length/2);
for(int i=0; i<half; i++ ){
//
// if(i == 0){
// int aval = (nthToLast(a, length)).val - a.val;
// a.val = ((nthToLast(a, length-i)).val - a.val);
// a.next = current;
// }
current.val = ((nthToLast(a, length-i)).val - current.val);
current = current.next;
}
}
return a;
}
/* Helper function that given LinkedList head, and int n,
returns the nth to last ListNode in the LinkedList */
public ListNode nthToLast(ListNode head, int n){
ListNode nth = head;
ListNode ahead = head;
/* strategy: set nth to head, and 'ahead' to n places in front of 'nth'
increment at same speed and then when 'ahead' reaches the end, 'nth'
will be in the nth place from the end.
*/
while(ahead.next != null){
for(int i=0; i<n; i++){
ahead = ahead.next;
}
nth = nth.next;
ahead = ahead.next;
}
return nth;
}
}
Also -- I'm trying to get better at questions like these. Is this an ok approach for this question? I'd like to figure out how to make this work, but also if this is an all around bad approach please let me know.
break code into simple helper functions,
make a function to get value of nth element in the linked list(this function is very easy to write)
,and then traverse the list upto the half every time calling that function to get the value of listSize-i member of the list and edit the value of the the ith member of the list. and make changes to the 1st few elements manually to check weather your linkList implementation is working or not
/**
* Definition for singly-linked list.
**/
class ListNode {
public int val;
public ListNode next;
ListNode(int x) { val = x; next = null; }
}
public class Solution {
public ListNode subtract(ListNode a) {
ListNode current = a;
int length = 0;
//get length
while(current.next != null){
length++;
current = current.next;
}
length += 1;
int half = length/2;
//logic of this loop is
//go from 0 to half of the list
// j goes from the last element to half
//for example if size of list is 6 (indexing from 0)
//when i is 0 j is 5
//when i is 1 j is 4 and so on
//so you get what you wanted
for(int i=0,j=length-1; i<half; i++,j-- ){
current.val=nthElement(a,j).val-current.val;
current = current.next;
}
return a;
}
/* Helper function that given LinkedList head, and int n,
returns the nth node of LinkedList */
public ListNode nthElement(ListNode head, int n){ //e.g-if n is 5 it will return the 5th node
ListNode nth = head;
for(int i=0; i<n; i++){
nth = nth.next;
}
return nth;
}
}

Uniquely number nodes of a Binary Tree

How would I go about setting an index for each node after generating a binary tree?
(a) (1)
(x) (r) => (2) (3)
(o)(t)(t)(x) (4)(5)(6)(7)
So I can then use a call such as getIndex()at a particular node to return its index.
My tree class:
public class BT<E>{
E value;
BT<E> left, right;
int Index;
public BT(E value)
{
this.value=value;
}
public BT (E value, BT left, BT right)
{
this.value = value;
this.left = left;
this.right = right;
}
Breadth-first traversal.
Queue<BT> queue = new LinkedList<BT>() ;
public void breadth(BT root) {
if (root == null)
return;
queue.clear();
queue.add(root);
int index = 0;
while(!queue.isEmpty()){
BT node = queue.remove();
node.Index = index;
index++;
if(node.left != null) queue.add(node.left);
if(node.right != null) queue.add(node.right);
}
}
Adapted from here.
If you are doing this after the tree is fully created, then something that uses level-order traversal will work. It's not terribly efficient, but it's straight-forward recursion:
/* Method to set index based on level-order traversal of tree */
public void initIndices(BT root) {
int maxIndexSoFar = 0;
for (int d = 1; d <= root.height(); ++d)
maxIndexSoFar = setIndexAtLevel(root, d, maxIndexSoFar);
}
/* Method to set index of all nodes at a given level */
private int setIndexAtLevel(BT node, int level, int index) {
if (tree == null)
return index;
if (level == 1) {
index++;
node.setIndex(index);
return index;
}
else if (level > 1) {
int newIndex = setIndexAtLevel(node.left, level-1, index);
newIndex = setIndexAtLevel(node.right, level-1, newIndex);
return newIndex;
}
return -1;
}
I'll leave you to create the height() method and setIndex() methods. Fair warning, I have not tested this at all, so pardon any typos.
So you are to implement a procedure getIndex(int index) which has to return you the node with that index?
If so, you are looking for an efficient way to represent a binary tree.
You could traverse the tree for each call to getIndex but this wouldn't be efficient...
An efficient solution is to store the complete binary tree in an array, because of the O(1) access it provides. Store a node n at index n in the array and its child nodes at index 2*n and (2*n) - 1. But here the restrictions are that the tree has to be complete and the size of an array is not variable (if the binary tree becomes too big, a bigger array (usually twice as big) should be made and all elements should be copied).
This is a handy solution because :
Node access is in O(1) but a procedure like addNode() would become amortized in O(1). (*)
A node does not have to remember it's child nodes --> this.left becomes this.left() with the implementation of left() provided below.
A possible implementation for left() procedure.
static int[] binaryTreeArray = new int[maxTreeSize]; // BT of integers for example
...
public int left() { // returns integer or ... (type of your nodes)
return binaryTreeArray[(this.Index)*2]; // O(1)
}
(*) An addNode()-like procedure would add nodes in O(1) (binaryTreeArray[index] = nodeValue;) most of the time but when the binaryTreeArray is full it will have to make a bigger array that is usually twice as big (O(n) for the copying). It can be shown that this has an amortized cost of O(1) but this has no added value for this answer.

Measure size/length of singly linked list in Java?

I need help making the int size(); method for a singly linked list in Java.
This is what I have so far, but it does not return the correct size of the list.
public int size()
{
int size = 0;
Node CurrNode = head;
while(CurrNode.next != null)
{
CurrNode = CurrNode.next;
size++;
}
return size;
}
Can someone help me implement this method in Java?
The biggest improvement you can make is to use Java Coding Convension and use camelCase local variables.
You can write it like this.
public int size() {
int size = 0;
for(Node n = head; n.next != null; n = n.next)
size++;
return size;
}
as you are re-writing a commonly used class in Java, I suggest you have a look at how it is done there if you want a better way of doing things.
From LinkedList
/**
* Returns the number of elements in this list.
*
* #return the number of elements in this list
*/
public int size() {
return size;
}
As you can see, when an element is added size is incremented and when an element is removed it id decremented saving you having to traverse the list to get the size.
The easiest way would be to have variable that tracks the size initialised at 0. Then each time you add a node it's just size++, or size-- when you remove a node. You size() method then just has to return this variable without traversing the list.
You need to pass the list to your method and check currNode!= null :
public static int size(Node currNode){
int count = 0;
while (currNode!= null){
count++;
currNode=currNode.getNext();
}
return count;
}
Well, the easiest way to calculate the length is by checking whether the currentNode!=null and keep the currentNode incrementing .
We can use while or a for loop to implement this.
Below is an example where for loop is used.
public int getLength(){
ListNode temp = head;
for(temp = head; temp!=null; temp=temp.getNextNode()){
length++;
}
return length;
}

Categories