HackerRank Challenge : Find total number of days Plants die

Question:

Problem Statement

There are N plants in a garden. Each of these plants has been added
with some amount of pesticide. After each day, if any plant has more
pesticide than the plant at its left, being weaker than the left one,
it dies. You are given the initial values of the pesticide in each
plant. Print the number of days after which no plant dies, i.e. the
time after which there are no plants with more pesticide content than
the plant to their left.

Input Format

The input consists of an integer N. The next line consists of N
integers describing the array P where P[i] denotes the amount of
pesticide in plant i.

Constraints

1 ≤ N ≤ 100000
0 ≤ P[i] ≤ 109

Output Format

Output a single value equal to the number of days after which no
plants die.

Sample Input

7 6 5 8 4 7 10 9

Sample Output

2

Explanation

Initially all plants are alive.
Plants = {(6,1), (5,2), (8,3), (4,4),
(7,5), (10,6), (9,7)}.
Plants[k] = (i,j) => jth plant has pesticide
amount = i.
After the 1st day, 4 plants remain as plants 3, 5, and 6
die.
Plants = {(6,1), (5,2), (4,4), (9,7)}.
After the 2nd day, 3
plants survive as plant 7 dies.
Plants = {(6,1), (5,2), (4,4)}.
After
the 3rd day, 3 plants survive and no more plants die.
Plants =
{(6,1), (5,2), (4,4)}.
After the 2nd day the plants stop dying.

Challenge Link : HackerRank : Poisonous Plant

My Submission : HackerRank Submission Link

Failed Test Case 1 : Input Output

Failed Test Case 2 : Input Output

My Code so Far :

total = int(raw_input())
plants = map(int,raw_input().split())
num_deaths = 1
day = 0
while num_deaths > 0:
    num_deaths = 0
    temp_plants = []
    day += 1
    for i in range(1, len(plants)):
        if plants[i] > plants[i - 1]:
            num_deaths += 1
            continue
        else:
            temp_plants.append(plants[i])
    plants = temp_plants
print(day - 1)

It still fails a few test cases. Any suggestions/advice ?

Asked By: darthShadow

||

Answers:

Look at your Temp_plants array, you initialize it with []. However, Since you are iterating from index 1, The plant from index 0 is always excluded, so you have to initialize with [plant[0]], since the leftmost plant is always included.

Example: 1 5 4 3 2

Actual Process

  • 1 5 4 3 2
  • 1 4 3 2
  • 1 3 2
  • 1 2
  • 1

Answer=4

Your Code

  • 1 5 4 3 2
  • 4 3 2 [Note that the leftmost 1 is excluded]

Answer=1

Here’s a working code which produces correct outputs, but is rather slow. It is correct but is O(n^2) which times out some testcases. This is basically the same as your algo.

n= input()
plant=map(int,raw_input().split())
count=0

# At each iteration the following loop updates the plant  
# list by removing weak plants and count counts no. of steps
# temp temporarily stores surviving plants

while(True):
    temp=[plant[0]]
    for i in range(1,len(plant)):
        if plant[i]<=plant[i-1]:    
             temp.append(plant[i])

# If temp and plants have same len, then no plant has
# been removed, so, the process ended.
    if(len(temp)==len(plant)):    break

    plant=temp
    count+=1

print count

I’m thinking of a faster dynamic approach that should work, but haven’t yet made it work.

Answered By: Rohcana

I would go with an approach where we recursively look at all the elements to the right of the minimum element.

The base case would be if the elements to the right of the min element were sorted!

Answered By: Scrooge

Here is an approach for O(n) complexity, this is quite similar to the span finding problems:

class Stack():
    def __init__(self):
        self.items=[]
    def push(self, item):
        self.items.append(item)
    def pop(self):
        return self.items.pop()
    def isEmpty(self):
        return self.items==[]
    def peek(self):
        return self.items[-1]
    def __str__(self):
        return str(self.items)

if __name__=="__main__":
    arr = [1, 3, 5, 2, 7, 6, 4, 2, 1]
    l_a = len(arr)
    stack = Stack()
    e_span = [None]*l_a
    for i in range(l_a):
        elem = arr[i]
        x = None
        max_span = 0
        while not stack.isEmpty() and elem<=arr[stack.peek()]:
            x = stack.pop()
            max_span = max(e_span[x], max_span)
        if stack.isEmpty():
            e_span[i]=0
        elif x is None:
            e_span[i]=1
        else:
            span = max_span+1
            e_span[i]=span
        stack.push(i)
    print max(e_span)
Answered By: DarthSpeedious

passed python version, basically modified the code of @DarthSpeedious and add some comments
# Enter your code here. Read input from STDIN. Print output to STDOUT

raw_input()

arr = map(int, raw_input().strip().split())

stack = []
days = [0 for i in range(len(arr))]
max_span = 0

for i in range(len(arr)):
    x = None
    max_span = 0 # max_span is only meaningful when the current element smaller than the stack top, so it will get reset for each element.
    while stack != [] and arr[stack[-1]] >= arr[i]:
        x = stack.pop()
        max_span = max(max_span, days[x])

    # if it is the first element, days[i] = 0
    if not stack:
        days[i] = 0
    # if it is the element do not trigger any pop, which means it is greater than its own left(since each element will
    # be pushed to the stack anyway), so the days[i] = 1
    elif not x:
        days[i] = 1
    # if it triggered the pop, which means the arr[i] will wait all the poped element die, then it will die the next day, so days[i] should be the current max_span + 1
    else:
        days[i] = max_span + 1
    stack.append(i)

print max(days)
Answered By: user1754197

This is my java O(n) approach :

This passes all test cases except 5 testcases leading to a score of 57.50

import java.util.Scanner;
public class PoisonousPlants {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] inputs = new int[n];
        int[] answer = new int[n];
        for (int i = 0; i < n; i++) {
            inputs[i] = sc.nextInt();
        }
        int min = inputs[0];
        for (int i = 1; i < inputs.length; i++) {
            min = Math.min(inputs[i], min);
            if (inputs[i] > inputs[i - 1]) {
                answer[i] = answer[i] + 1;
            } else {
                if (inputs[i] == min) answer[i] = 0;
                else answer[i] = answer[i - 1] + 1;
            }
        }
        int max = -1;
        for (int i = 0; i < answer.length; i++) {
            max = Math.max(max, answer[i]);
        }
        System.out.println(max);
    }
}
Answered By: Bharat

Here’s an easy solution to it!! It passed 26 testcases out of 30.

// Complete the poisonousPlants function below.
  long int poisonousPlants(vector<long int> p) {
  long int j,i,n,c=0,changes=0,m=p.size(),minn;

  for(i=1;i<m;i++)
  {
   if(p[i]>p[i-1])
   {
    changes=1;
    j=i+1;
    minn=p[i];
    while(j<m  && p[j]>p[i-1])
    {
        if(p[j]>p[j-1] && p[j]>minn)
        {
            ++j;
        }
        else if(p[j]>minn)
        {
            minn=min(p[j],minn);  
            ++j; 
        }
        else
        {
            minn=min(p[j],minn);
            ++changes;
            ++j;
        }
    }
    c=max(c,changes);
    }
  }
 return c;
 }

C++

Hackerrank

Answered By: Smita Prakash
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

class StackNode {
    int index;
    int element;

    StackNode(int index, int element) {
        this.index = index;
        this.element = element;
    }

    @Override
    public String toString() {
        return "StackNode [index=" + index + ", element=" + element + "]";
    }
}

public class Solution {

    // Complete the poisonousPlants function below.
    static int poisonousPlants(int[] p) {
        int days = 0;
        List<StackNode> list = new LinkedList<>();
        Stack<StackNode> st = new Stack<>();
        for (int i = 0; i < p.length; i++) {
            list.add(new StackNode(i, p[i]));
        }

        while (true) {
            for (int i = 0; i < list.size() - 1; i++) {
                if (list.get(i + 1).element > list.get(i).element) {
                    st.push(list.get(i + 1));
                }
            }
            if (st.isEmpty())
                break;
            else {
                days++;
                while (!st.isEmpty()) {
                    list.remove(st.pop());
                }
            }
}
        return days;

    }
}
Answered By: AnchalHanda
**I Solve this problem using java**

import java.util.Stack;

public class poison_plants {

    static Stack<Integer>st1= new Stack<>();
    static Stack<Integer>st2= new Stack<>();
    static int count=0;
    public static void main(String[] args) {

    st1.push(6);
    st1.push(5);
    st1.push(8);
    st1.push(4);
    st1.push(7);
    st1.push(10);
    st1.push(9);
    
    
        
    System.out.println(plants());
    }
    private static int plants() {
         
        int checkValue=1;
        int currentvalue,preValue;
        int plantDies=0;
        
        
        while(checkValue!=0) {
        
    
            currentvalue=st1.pop();
            if(st1.size()==1) {
                break;
            }
            preValue=st1.pop();
            
            if(currentvalue<preValue) {
                st1.push(preValue);
                plantDies=1;
                st2.push(currentvalue);

            }else {
                st2.push(currentvalue);
                st1.push(preValue);
            }
        }
        
        if(plantDies!=0) {
            while(!st2.isEmpty()) {
                st1.push(st2.pop());
            }
            checkValue++;
            plants();
        }
    
        return checkValue;
    }

}
Answered By: eagerprince
static boolean isDescending(int[] p) {
    for (int i = 0; i < p.length - 1; i++) {
        if (p[i] < p[i + 1]) {
            return false;
        }
    }
    return true;
}


static int poisonousPlants(int[] p) {
    if (p == null || p.length == 1 || Arrays.stream(p).distinct().count() == 1 || isDescending(p)) {
        return 0;
    }
    int maxDaysAlive = 0;
    Stack<List<Integer>> stack = new Stack<>();
    for (int i = 0; i < p.length; i++) {
        int item = p[i];
        int daysAlive = 0;
        while (!stack.isEmpty() && item <= stack.peek().get(0)) {
            daysAlive = Math.max(daysAlive, stack.pop().get(1));
        }
        daysAlive = stack.isEmpty() ? 0 :  daysAlive + 1;
        maxDaysAlive = Math.max(maxDaysAlive, daysAlive);
        stack.push(Arrays.asList(item, daysAlive));
    }

    return maxDaysAlive;
}
Answered By: Luke Samad
// You are using Java
import java.util.*;
class Main
{
    public static void main(String[] args)
    {
        Scanner input=new Scanner(System.in);
        int n=input.nextInt();
        int arr[]=new int[n];
        int a[]=new int[n];
        for(int i=0;i<n;i++)
        {
            arr[i]=input.nextInt();
        }
        int os=0;
        int s=n;
        int day=0;
        int c=1;
        while(os!=s)
        {
            for(int j=1;j<s;j++)
            {
                if(arr[j]<=arr[j-1])
                {
                    arr[c]=arr[j];
                    c++;
                }
            }
            os=s;
            s=c;
            c=1;
            day++;
        }
        System.out.print(day-1);
    }
}
Answered By: Hari Prasath V
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.