K-th largest element in BST - recursion

I am trying to find the K-th largest element in a Binary Search Tree using reverse inorder approach by using a counter. Here is what I have implemented:
int klargest(Node root,int k,int count)
{
if(root != null)
{
klargest(root.right,k,count);
count++;
if(count == k)
return root.data;
klargest(root.left,k,count);
}
return -1;
}
But the issue is that when count = k, the code does not return the answer to the caller function but instead to a sub-call. Due to this, the answer is lost. In other words, the recursion does not stop there and it keeps on going until all the nodes are visited. In the end, I get the answer -1. What I want is that the recursion should end when count = k and the required answer should be returned to the caller function. How can I do this?
Note: I neither want to use a global variable nor an iterative approach.

Actually, you do not return your node - the recursive call results are ignored. Rewrite it so it returns a Node:
Node klargest(Node root,int k,int count)
{
Node result = null;
if(root != null)
{
result = klargest(root.right,k,count);
if (result != null)
return result;
count++;
if(count == k)
return root;
result = klargest(root.left,k,count);
}
return result;
}

You can use this approach:
int kthLargest(Node node, int k) {
int rightCount = count(node.right);
if (k <= rightCount) {
return kthLargest(node.right, k);
} else if (k == rightCount+1) {
return node.data;
} else {
return kthLargest(node.left, k - rightCount + 1);
}
}
int count(Node node) {
if (node != null) {
return count(node.left) + count(node.right) + 1;
}
return 0;
}

Related

merge sort linkedlist - stackoverflow error

I am trying to solve leetcode-148 (https://leetcode.com/problems/sort-list/) i.e. sort given LinkedList, but am getting a stackoverflow error. so far I have tried dry running but am not seeing where the issue could occur.. the base condition of the recursion seems to be right but looks like I am missing something if someone sees what I am not seeing..
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
if (head==null || head.next==null) return head;
ListNode follow = new ListNode(0);
follow.next=head;
ListNode fast = head;
ListNode slow = head;
// Find the mid-point of the list
while (fast.next!=null && fast.next.next!=null) {
slow=slow.next;
fast=fast.next.next;
follow=follow.next;
}
// Split the list
follow.next = null;
// Sort each half
ListNode first = sortList(head);
ListNode second = sortList(slow);
// Merge
return merge(first, second);
}
private ListNode merge(ListNode first, ListNode second) {
if (first==null) return second;
if (second==null) return first;
ListNode result = new ListNode(0);
ListNode head = result;
while (first!=null && second!=null) {
if (first.val<second.val) {
result.next = first;
} else {
result.next = second;
}
result=result.next;
}
if (first!=null) {
result.next = first;
result=result.next;
}
if (second!=null) {
result.next = second;
result=result.next;
}
return head.next;
}
}
Here's the error
WARNING: A command line option has enabled the Security Manager
WARNING: The Security Manager is deprecated and will be removed in a future release
java.lang.StackOverflowError
at line 31, Solution.sortList
at line 31, Solution.sortList
at line 31, Solution.sortList
at line 31, Solution.sortList
at line 31, Solution.sortList
There are two issues:
When sortList is called with a list that has 2 nodes, then after the first loop (which makes no iterations), slow will be equal to head, and follow.next = null will just mutate the dummy node that was prepended before the head node. So essentially the linked list wasn't split, and the recursive call is on the same list, leading to infinite recursion. Solve this by changing the while condition so at least one iteration will be made. Also, you can do this without a third reference (follow).
In merge, the first and second references do not move forward, so the loop will be infinite.
Here is corrected code:
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode fast = head.next;
ListNode slow = head;
// Find the mid-point of the list
while (fast != null && fast.next != null) { // iterate at least once
slow = slow.next;
fast = fast.next.next;
}
// Split the list
ListNode second = slow.next;
slow.next = null;
// Sort each half
head = sortList(head);
second = sortList(second);
// Merge
return merge(head, second);
}
private ListNode merge(ListNode first, ListNode second) {
ListNode result = new ListNode(0);
ListNode head = result;
while (first != null && second != null) {
if (first.val < second.val) {
result.next = first;
first = first.next; // move forward
} else {
result.next = second;
second = second.next;
}
result = result.next;
}
if (first != null) {
result.next = first;
result = result.next;
}
if (second != null) {
result.next = second;
result = result.next;
}
return head.next;
}

Count the number of nodes of a doubly linked list using recursion

Here is what I've done so far:
struct rep_list {
struct node *head;
struct node *tail;
}
typedef rep_list *list;
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
lst->head = lst->head->next;
return 1 + length(lst);
}
}
This works, but the head of the list the function accepts as a parameter gets changed. I don't know how to fix that.
I'm not allowed to change the function definition so it should always accept a list variable.
Any ideas?
EDIT: I tried to do what Tyler S suggested in the comments but I encountered another problem. If I create a node* variable at the beginning, it should point to lst->head. But then every recursive call to the function changes the value back to lst->head and I cannot move forward.
You don't need a local node: just don't change the list head. Instead, pass the next pointer as the recursion head.
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
return 1 + length(lst->head-next);
}
}
I see. Okay; this gets a bit clunky because of the chosen representation. You need a temporary variable to contain the remaining list. This iscludes changing the head.
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
new_lst = new(list)
new_lst->head = lst->head->next;
var result = 1 + length(new_lst);
free(new_lst)
return result
}
}
At each recursion step, you create a new list object, point it to the 2nd element of the current list, and continue. Does this do the job for you?
Although this solution is clunky and I hate it, its the only way I can see to accomplish what you're asking without modifying the method signature. We create a temporary node * as member data of the class and modify it when we start.
struct rep_list {
struct node *head;
struct node *tail;
}
node *temp = NULL;
bool didSetHead = false;
typedef rep_list *list;
int length(const list lst) {
if ((didSetHead) && (lst->head != temp)) {
temp = lst->head;
didSetHead = false;
}
if (temp == NULL) {
didSetHead = true;
return 0;
}
else {
temp = temp->next;
return 1 + length(temp);
}
}
Please note, I haven't tested this code and you may have to play with a bit, but the idea will work.

Issue with Recursive Methods ("missing return statement")

so I have a program that is running a bunch of different recursive methods, and I cannot get it to compile/run. The error is in this method, according to my computer:
public static int fibo(int n)
// returns the nth Fibonacci number
{
if (n==0)
{
return 0;
}
else if (n==1)
{
return 1;
}
else if (n>1)
{
return fibo(n-1) + fibo(n-2);
}
}
I have this method called correctly in my main method, so the issue is in this bit of code.
I think I can help you in this. Add return n; after your else if. Outside of the code but before the last curlicue.
The code will work as long as n ≥ 0 btw; another poster here is right in that you may want to add something to catch that error.
Make sure all possible paths have a return statement. In your code, if n < 0, there is no return statement, the compiler recognizes this, and throws the error.
public static int fibo(int n)
// returns the nth Fibonacci number
{
if (n<=0)
{
return 0;
}
else if (n==1)
{
return 1;
}
else // All other cases, i.e. n >= 1
{
return fibo(n-1) + fibo(n-2);
}
}

Palindrome Recursion Program

public static boolean palindrome(String input, int i, int j)
{
if (i >= j)
return true;
if (input.charAt(i) == input.charAt(j))
{
i++;
j--;
palindrome(input, i, j);
}
else if (input.charAt(i) != input.charAt(j))
return false;
}
My Java platform (eclipse) won't accept this code as working, due to a "lack of return type." Now I know in proper coding ediquite, it's better to use only one return value, but when it comes to recursion, this is somewhat new to me. How can I go about doing this? If I instantiate a Boolean type at the top of this method, it's creating a new instance of that variable (and instantiating it as null or whatever I set it to) each time the method runs, but if I place it above my constructor, my method won't assign a value to it/can't return it.
Basically, how do I go about modifying my code to have a single return value that Eclipse will accept as always executing? I can do this easily enough with loops, but I'm not sure how to approach the topic with Recursion.
Just for improved readability:
public static boolean palindrome(String input, int i, int j)
{
if (i >= j)
return true;
if (input.charAt(i) != input.charAt(j))
return false;
return palindrome(input, i + 1, j - 1);
}
If we could use C# and Linq (since I don't have Java dev environment here) to reversing a char array:
public static bool palindrome(String input)
{
return input.Equals(new String(input.ToCharArray().Reverse().ToArray()));
}
The issue is that you have no return inside the second if statement. If charAt i and j are equal you never return anything.
Keeping the spirit of your code I'd shorten the whole thing up to be:
public static boolean palindrome(String input, int i, int j)
{
if (i >= j)
{
return true;
}
if (input.charAt(i) == input.charAt(j))
{
return palindrome(input, i + 1, j - 1);
}
return false;
}
You can certainly just do this:
return palindrome(input, i, j);
However it is good practice to have a single return to improve readability. Try this on for size:
boolean isPalindrome = false;
if (i >= j)
isPalindrome = true;
else if (input.charAt(i) == input.charAt(j))
{
i++;
j--;
isPalindrome = palindrome(input, i, j);
}
else if (input.charAt(i) != input.charAt(j))
isPalindrome = false;
return isPalindrome;
}
Have that boolean always instantiated. The key here is to make palindrome's return be stored in that boolean.
The recursive portion comes in at the call to palindrome. It will only finally return the final value after all of the recursive calls, because it only ever determines if its a palindrome when it reaches the end of the recursive cycle.
In the second if block, you don't return anything.
Just change the recursive call so that you return its value:
return palindrome(input, i, j);
Also, incidentally, you don't need to do i++ and j-- in the if block-- you can instead call the palindrome method with i+1 and j-1 instead, and that will have basically the same effect.
public static String palindrome(String input, int i, int j)
{
if (i >= j)
return "-1";
//--------------------------------------------//
if (input.charAt(i) == input.charAt(j))
{
i++;
j--;
//--------------------------------------------//
palindrome(input, i, j);
return "is palindrom";
}
//--------------------------------------------//
else
return "not palindrom";
}
}
//--------------------------------------------//
An other option might be this:
boolean isPalindrome(String s) {
boolean ret = true;
if (s.length() == 1 || s.equals("")) {
return ret;
} else {
char first = s.charAt(0);
char last = s.charAt(s.length() - 1);
if (first != last)
ret = false;
else if (s.length() > 2) {
String partial = s.substring(1, s.length() - 1);
ret = isPalindrome(partial);
}
}
return ret;
}
Probably this answer can help(in Python):
def isPalinr(str1):
if len(str1)<=1:
print('Palindrome')
return
if (str1[0] != str1[-1]):
print ('Not palindrome')
return
else:
return isPalinr(str1[1:len(str1)-1])
This will return None though we can return string in first 'if' clause because program will ultimately stop at that point.

Using recursion to sum numbers

I have just been studying the concept of recursion and I thought that I would try a simple example. In the following code, I am attempting to take the numbers: 1, 2, 3, 4, 5, and add them together using recursion. I expected the result to be 15, but my code is returning 16.
What am I doing wrong?
Code:
static void Main(string[] args)
{
Console.WriteLine(Sum(5));
Console.Read();
}
static int Sum(int value)
{
if (value > 0)
{
return value + Sum(value - 1);
}
else
{
return 1;
}
}
You're returning 1 in the else clause. You should be returning 0:
else
{
return 0;
}
If the value is not greater than zero, why would you return one in the first place?
Your code executes as follows:
Sum --> 5
Sum --> 4
Sum --> 3
Sum --> 2
Sum --> 1
Sum --> 0
1 <---
2 <---
4 <---
7 <---
11 <---
16 <---
Check your base case.
Others already noted the error, and I will elaborate on recursion.
Although C# does not currently perform tail call optimization (although IL has special tail instruction), it's worth mentioning that tail recursion is generally a good thing.
Tail recursion is a special case of recursion in which the last operation of the function, the tail call, is a recursive call. Since the last call is the recursive call there is no need to preserve stack frame of the calling function and the compiler can easily use this information to generate machine instruction such that the stack doesn't grow at all. So it can basically turn recursive function into an iterative one.
Rewriting your code to support tail recursion can be done as follws:
static int Sum(int result, int value)
{
if(value == 0)
return result;
return Sum(result + 1, value - 1);
}
static int Sum(int value)
{
if (value > 0)
{
return value + Sum(value - 1);
}
else
{
return 0; //Change this.
}
}
That's because, when the value is = 0, you return 1. Then it get's added.
Sum's "else" clause should return 0.
I always prefer to put the terminating case(s) up front so they're obvious, and I have a violent near-psychopathic hatred of "if cond then return a else return b" constructs. My choice would be (making it clear that it won't work properly for negative numbers):
static unsigned int Sum(unsigned int value) {
if (value == 0)
return 0;
return value + Sum(value - 1);
}
I believe that's far more readable than a morass of braces and control flow.
The others have already answered that question, but when I work with recursion, one of the things I like to do to check that it works is to use check the base case and one additional case. I your case I would test it with 1, which would yield 2. Since this is obviously wrong you might want to check for 0 which is not going to use any recursion and so it should be obvious that the error lies in the base class.
In general recursion is easier to reason about, since you can list the limited number of things you need to check, but it does initially require a leap of faith since your intuition will be wrong. Just test the edge cases and trust the math it will never fail.
int summation(int num){
if (num==1)
return 1;
return summation(num-1)+num;
}
I'm pretty sure the problem is because you want your recursion to terminate when value == 1, and it's currently terminating when value == 0.
Your terminating expression is at issue. When value == 0 (or lower), it should return a 0 rather than 1. For sake of efficiency (which, let's admit it here, obviously isn't a concern, otherwise recursion wouldn't have been used for this task), you should terminate the recursion at value == 1 and return a literal 1 to save one unnecessary level of recursion.
using System;
using NUnit.Framework;
namespace Recursion
{
[TestFixture()]
public class Test
{
[Test()]
public void TestSum ()
{
Assert.AreEqual (Sum (new int[] { }), 0);
Assert.AreEqual (Sum (new int[] { 0 }), 0);
Assert.AreEqual (Sum (new int[] { 1 }), 1);
Assert.AreEqual (Sum (new int[] { 1, 2, 3, 4, 5 }), 15);
}
public int Sum(int[] head)
{
if (head.Length == 0) return 0;
int[] tail = new int[head.Length - 1];
for (int i = 1; i < head.Length; i++)
{
tail [i-1] = head [i];
}
return head[0] + Sum (tail);
}
}
}
It could also be written like this:
public static int sum(int n){
int total;
if(n==1){
total =1;
}else{
total = sum(n-1)+n;
}
return total;
}
Actually, I think you don't need to check case else because
public static int sum(int number){
if(number > 0){
return number + sum(--number);
}
return number; // return 0 so that's why you don't need check else condition
}
To begin at the end, a recursive Sum method looks like this:
// version 3
public static int Sum(int startRange, int endRange)
{
if (endRange > startRange)
{
return endRange + Sum(startRange, endRange - 1);
}
if (endRange < startRange)
{
return startRange + Sum(endRange, startRange - 1);
}
return endRange;
}
Hardcoding the startRange to be 0 gives us:
// version 2
public static int Sum(int range)
{
if (range > 0)
{
return range + Sum(0, range - 1);
}
if (range < 0)
{
return Sum(range, -1);
}
return range;
}
...and if you want to limit the method to positive numbers only, there's no need for a sign:
// version 1
public static unsigned int Sum(unsigned int range)
{
if (range > 0)
{
return range + Sum(0, range - 1);
}
return range;
}
I hope this helps give more of an insight into summing number ranges via recursion.
static int Sum(int[] addends)
{
if (addends.Length == 1)
{
return addends[0];
}
else
{
int tailIndex = addends.Length - 1;
var subArray = addends[0..tailIndex];
return addends[tailIndex] + Sum(subArray);
}
}
Try this code:
def sumr(n):
if n==0:
return n
return n+sumr(n-1)

Resources