Cut the sticks: Hackerrank warmup challenge - java

I've been trying to solve the warmup challenges on Hackerrank. For this particular challenge - https://www.hackerrank.com/challenges/cut-the-sticks - I've written some code, and although it seems logically correct to me, I'm not getting the right answer.
My Code -
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int lengths[] = new int[n];
List<Integer> output = new LinkedList<Integer>();
for (int i = 0; i < n; i++)
lengths[i] = sc.nextInt();
sc.close();
Arrays.sort(lengths);
for (int i = 0; i < n; i++) {
if (lengths[i] == 0)
continue;
else {
output.add(n - i);
for (int j = i; j < n; j++) { // This loop isn't working like it should
lengths[j] -= lengths[i];
// System.out.print(lengths[j] + " "); // For debugging purposes
}
// System.out.println("");
}
}
for (int i = 0; i < output.size(); i++)
System.out.println(output.get(i));
}
}
For the following input -
6
5 4 4 2 8 2
The output I get is -
6
5
4
3
2
1
The correct output should be -
6
4
2
1
I tried to display the values of the lengths array throughout the runs of the for loop marked in the code (with a comment), and this is what i get for the same inputs as above -
0 2 4 4 5 8
0 4 4 5 8
0 4 5 8
0 5 8
0 8
0
6
5
4
3
2
1
I'm totally stumped as to why this would happen.

The problem is here:
lengths[j] -= lengths[i];
When i == j is true, this changes the value of lengths[i]. You need to save that value first.
final int v = lengths[i];
for (int j = i; j < n; j++) {
lengths[j] -= v;
}

Had solved it sometime back.
Here's a version of answer, using a do while loop
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int size = scan.nextInt();
int sticks [] = new int[size];
for (int i = 0; i < size; i++){
sticks[i] = scan.nextInt();
}
Arrays.sort(sticks);
do {
int count =0;
int leastLength = sticks[0];
for (int j=0; j < sticks.length; j++){
sticks[j] = sticks[j] - leastLength;
count++;
}
System.out.println(count);
List<Integer> resizeArray = new LinkedList<Integer>();
for ( int i=0; i< sticks.length; i++){
if (sticks[i] != 0){
resizeArray.add(sticks[i]);
}
}
int temp[] = new int[resizeArray.size()];
for (int i = 0; i < resizeArray.size(); i ++){
temp[i] = resizeArray.get(i);
}
sticks = temp;
} while (sticks.length > 0);
}

package com.omt.learn.algo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class CutTheSticks2 {
public static void main(String s[]) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
short N = Short.parseShort(br.readLine());
short[] A = new short[N];
N = 0;
for (String str : br.readLine().split(" ")) {
A[N++] = Short.parseShort(str);
}
Arrays.sort(A);
StringBuffer sb = new StringBuffer();
System.out.println(N);
for (int i = 1; i < N; i++) {
if (A[i - 1] != A[i]) {
sb.append((N - i) + "\n");
}
}
// OUTPUT
System.out.print(sb);
}
}

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int arr[] = new int[n];
for(int arr_i=0; arr_i < n; arr_i++){
arr[arr_i] = in.nextInt();
}
int count = 2;
int min=1000;
for(int arr_i=0;count !=1 ; arr_i++){ // read
count = 0;
for(int arr_j=0; arr_j < n; arr_j++)// find min
{ if(min >arr[arr_j] && arr[arr_j]!=0)
min=arr[arr_j];
}
for(int arr_k=0; arr_k < n; arr_k++)// sub
{
if(arr[arr_k]>=min)
{ count++;
arr[arr_k]= arr[arr_k] - min;
}
}
System.out.println(count);
}
}
}

This is a working solution in JavaScript. Took me a while to realize that the sort() in JavaScript performs a string comparison in alphabetical order.
function sortNumbers(a, b) {
return a - b;
}
function cutSticks(arr){
var smallestStick = 0;
arr = arr.sort(sortNumbers);
while(arr.length > 0) {
console.log(arr.length);
smallestStick = arr[0];
var newArray = [];
arr.forEach(function (val) {
var newValue = val - smallestStick;
if (newValue > 0) {
newArray.push(newValue);
}
});
arr = newArray;
}
}
function main() {
var n = parseInt(readLine());
arr = readLine().split(' ');
arr = arr.map(Number);
cutSticks(arr);
}
Hope it helps!

Java Version. Passed all tests, but not sure if is best performance.
static int[] cutTheSticks(int[] arr) {
List<Integer> sticks = Arrays.stream(arr).boxed().collect(toList());
List<Integer> cuts = new ArrayList<>();
while (true) {
int min = sticks.stream().mapToInt(Integer::valueOf).min().getAsInt();
Iterator it2 = sticks.iterator();
int cuted = 0;
List<Integer> temp = new ArrayList<>();
while (it2.hasNext()) {
int v = (int) it2.next();
if (v == min) {
it2.remove();
cuted++;
} else {
int nv = v - min;
it2.remove();
temp.add(nv);
cuted++;
}
}
cuts.add(cuted);
sticks.addAll(temp);
if (sticks.isEmpty()) {
break;
}
}
return cuts.stream().mapToInt(Integer::valueOf).toArray();
}

Related

How to return the result if its value becomes exponentially large while formulating the no. of valid BST Permutations on the basis of number of nodes

Problem statement: You are given an Integer N. You have to determine the number of valid BST's that can be created by nodes numbered from 1 to N.
Example:
Input:-
N = 5
arr[] = {1,2,3,4,100}
Output:
1
2
5
14
25666077
My code is as follows:
CODE:
import java.io.*;
import java.util.*;
public class Main{
public static int numOfTrees(int N){
int[] t = new int[N+1];
t[0] = 1;
t[1] = 1;
for(int lvl=2;lvl<=N;lvl++){
for(int root=1;root<=lvl;root++){
t[lvl] = t[lvl] + t[lvl-root]*t[root-1];
}
}
return t[N];
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
int arr[] = new int[num];
for(int i=0;i<num;i++){
arr[i] = sc.nextInt();
}
for(int i=0;i<num;i++){
System.out.println(numOfTrees(arr[i]));
}
}
}
Now, when I enter 100 in arr[4] as per the sample I/P, the function returns a garbage value.
I tried typecasting it into Long object type but it didn't make any difference.
Please help me out folks by writing the entire program!
I rewrited your logic with BigDecimal.
I hope your calculations are correct. Please point to article so I can double check the algorithm.
import java.math.BigInteger;
import java.util.*;
class Main {
public static BigInteger numOfTrees(int N) {
BigInteger[] t = new BigInteger[N + 1];
for (int i = 0; i < t.length; i++) {
t[i] = BigInteger.ZERO;
}
t[0] = BigInteger.ONE;
t[1] = BigInteger.ONE;
for (int lvl = 2; lvl <= N; lvl++) {
for (int root = 1; root <= lvl; root++) {
t[lvl] = t[lvl].add(
t[lvl - root].multiply(t[root - 1])
);
}
}
return t[N];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
int arr[] = new int[num];
for (int i = 0; i < num; i++) {
arr[i] = sc.nextInt();
}
for (int i = 0; i < num; i++) {
System.out.println(numOfTrees(arr[i]));
}
}
}
I entered:
5
1
2
3
4
100
=========== Output is ================
1
2
5
14
896519947090131496687170070074100632420837521538745909320

CCC 2018 J4: NoSuchElementException Error (Java)

I have been running this algorithm in order to solve this CCC (Canadian Computing Contest) question. It runs fine and gives the correct output on IntelliJ but shows an NoSuchElementException in DMOJ and the CCC online grader.
Here is my code:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
solution(sc.nextInt());
}
public static void solution(int lines) {
Scanner sc = new Scanner(System.in);
int[][] sunflowers = new int[lines][lines];
int[][] temp = new int[lines][lines];
// Creating sunflowers array
for (int i = 0; i < lines; i++) {
for (int j = 0; j < lines; j++) {
sunflowers[i][j] = sc.nextInt();
}
}
boolean readyToSubmit = false;
int a = 0;
int b = 0;
while (readyToSubmit == false) {
b = 0;
a = 0;
readyToSubmit = true;
for (int g = 0; g < sunflowers.length - 1; g++) {
for (int h = 1; h < sunflowers[g].length; h++) {
if (sunflowers[g][h - 1] > sunflowers[g][h]) {
// Turn true if previous value smaller than current
readyToSubmit = false;
}
}
}
// If each column is in descending order
for (int d = 0; d < sunflowers.length; d++) {
for (int e = 1; e < sunflowers.length; e++) {
if (sunflowers[e - 1][d] > sunflowers[e][d]) {
readyToSubmit = false;
}
}
}
if (readyToSubmit == true) {
break;
}
// Rotating the Array w/ temp
for (int i = sunflowers.length - 1; i >= 0; i--) { // we want position to go right -> left
b = 0;
for (int j = 0; j < sunflowers[0].length; j++) { // We want columns to go up -> down
temp[a][b] = sunflowers[j][i];
b += 1;
}
a += 1;
}
for (int x = 0; x < lines; x++) {
for (int y = 0; y < lines; y++) {
sunflowers[x][y] = temp[x][y];
}
}
}
for (int s = 0; s < sunflowers.length; s++) {
for (int k = 0; k < sunflowers[s].length; k++) {
System.out.print(sunflowers[s][k] + " ");
}
System.out.println();
}
}
}
Input:
3
3 7 9
2 5 6
1 3 4
Output (in IntelliJ):
1 2 3
3 5 7
4 6 9
Output (on DMOJ):
IR (java.util.NoSuchElementException)
Output (on CCC Grader):
Exception in thread "main" java.util.NoSuchElementException
<251 more characters> // unfortunately, I am not able to see what the 251 characters are.
I am currently not sure on what causes this NoSuchElementException (since it doesn't tell me the line number on DMOJ nor the CCC grader). Any help would be greatly appreciated.
Note: This is found in the comment section, I just added it as answer to verify that this problem has been solved.
Remove this line Scanner sc = new Scanner(System.in); on the solution method. Then close sc after solution(sc.nextInt()); line on the main method. Refer to this [link]1
pass your scanner in the solution method. Change your solution method to accept a scanner, so the method signature will be public static void solution(int lines, Scanner sc) , then call it in your main method by solution(sc.nextInt(), sc);. Then after solution(sc.nextInt(), sc); close your scanner by using sc.close()

I want to run my code, but terminal tells index out of bounds. Probably, because of ArrayList methode get ot smth like this

I'm trying to run my code.
But terminal tells:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at CF455A.main(CF455A.java:25)
25th string is: game.remove(game.get(max+1));
My code:
import java.util.*;
import java.lang.*;
import java.io.*;
public class CF455A {
public static void main(String args[]) throws java.lang.Exception {
Scanner in = new Scanner (System.in);
int n = in.nextInt();
int max = 0;
ArrayList<Integer> game = new ArrayList<Integer>();
for(int i = 0; i < n; i++){
int t = in.nextInt();
game.add(i, t);
}
int counter = 0;
while(game.size()>0){
for(int j = 0; j < game.size(); j++){
if(max <= (int)game.get(j)){max=j;}
for(int i = 0; i < game.size(); i++){
counter = counter + (int)game.get(max);
game.remove(game.get(max));
game.remove(game.get(max+1));
game.remove(game.get(max-1));
}
}
}
System.out.print(counter);
in.close();
}
}
I think this happends because of ArrayList or methodes like game.get(); or game.remove();.
I just wanted to change a value of one of the elements of ArrayList
List item
According to logic :-
if i give input as :- 5 1 2 3 4 5
then first pass :-
game.size() = 5;
while condition true -> and tries to remove the item at index (1,0,-1).So it fails for (-1) IndexOutOfBounds.
Please do the null check as follows :-
import java.util.*;
import java.lang.*;
import java.io.*;
public class TestMemberOuter1 {
public static void main(String args[]) throws java.lang.Exception {
Scanner in = new Scanner (System.in);
int n = in.nextInt();
int max = 0;
ArrayList<Integer> game = new ArrayList<Integer>();
for(int i = 0; i < n; i++){
int t = in.nextInt();
game.add(i, t);
}
int counter = 0;
while(game.size()>0){
for(int j = 0; j < game.size(); j++){
if(max <= (int)game.get(j))
{
max=j;
}
for(int i = 0; i < game.size(); i++){
counter = counter + (int)game.get(max);
if(max < game.size() )
{
game.remove(game.get(max));
}
if(max+1 < game.size() )
{
game.remove(game.get(max+1));
}
if(max-1 > 0 )
{
game.remove(game.get(max-1));
}
}
}
}
System.out.print(counter);
in.close();
}
}

Counting array reference input and displaying count -- infinite loop

I am trying to display the occurrence of how many times an integer occurs in an array but I get an infinite loop/logic error. For instance, if the user enters: 2, 5, 6, 5, 4, 3, 23, 43, 2, 0 then it should display:
2 occurs 2 times
3 occurs 1 time
4 occurs 1 time
5 occurs 2 times
6 occurs 1 time
23 occurs 1 time
43 occurs 1 time
Any help would really be appreciated. Note: This is not an assignment or homework, It is a exercise question from intro to Java book by Y.D. Lang
import java.util.*;
public class CountNumbers {
public static void main(String[] args) {
System.out.println("Enter the integers between 1 and 100: ");
int[] arrayRefVar = createList();
int[] countNum = countNumbers(arrayRefVar);
displayCount(countNum, arrayRefVar);
}
public static int[] createList() {
Scanner Input = new Scanner(System.in);
int[] List = new int[100];
int i = 0;
while (List[i] != 0) {
List[i] = Input.nextInt();
i++;
}
return List;
}
public static int[] countNumbers(int[] List) {
int[] count = new int[100];
for (int i = 0; i < count.length; i++) {
count[i] = i;
}
int[] countNum = new int[List.length];
for (int i = 0; i < countNum.length; i++) {
countNum[i] = 0;
}
for (int i = 0; i < List.length; i++) {
for (int j = 0; j < count.length; j++) {
if (List[i] == count[j]) {
countNum[i]++;
}
}
}
return countNum;
}
public static void displayCount(int[] countList, int[] arrayRefVar) {
for (int i = 0; i < arrayRefVar.length; i++) {
System.out.println(arrayRefVar[i] + " occurs " + countList[i] + " " + checkPlural(arrayRefVar[i]));
}
}
public static String checkPlural(int n) {
if (n > 1) {
return "times";
} else {
return "time";
}
}
}
If your input should end in 0, then you should check whether the currently read int is zero or not.
while(i < List.length) {
List[i] = Input.nextInt();
if(List[i] == 0)
break ;
++i;
}
Since you are checking for the condition after incrementing i, you are not checking the current value.
Note : nextInt() method from the Scanner class can throw exceptions namely : InputMismatchException, NoSuchElementException and IllegalStateException. So either handle it in a try catch block or make the caller handle it by throwing the exception.
So I finally got it after countless tries, if anybody has any suggestions to make the code more efficient the input would be greatly appreciated. Here it is:
import java.util.Random;
public class CountSingleDigits {
public static void main (String[] args) {
int[] arrayRefVar = createList();
int[] counts = new int[10];
for (int i = 0; i < 10; i++) {
counts[i] = i;
}
int[] tempCounts = new int[10];
for (int i = 0; i < arrayRefVar.length; i++) {
for (int j = 0; j < 10; j++) {
if (arrayRefVar[i] == counts[j]) {
tempCounts[j]++;
}
}
}
for (int i = 0; i < 10; i++) {
System.out.println(counts[i] + " appears " + tempCounts[i] + " times ");
}
for (int i = 0; i < arrayRefVar.length; i++) {
if (i % 10 == 0) {
System.out.println();
}
System.out.print(arrayRefVar[i] + " ");
}
}
public static int[] createList() {
Random f = new Random();
int[] List = new int[100];
for (int i = 0; i < List.length; i++) {
List[i] = f.nextInt(9);
}
return List;
}
}
One issue is that your while loop for user input is never entered. You use 0 as the sentinel value to exit user input, however, when you initialize an array of integers, they are all 0 by default.
int[] List = new int[100];
int i = 0;
//problem: while loop never entered
while (List[i] != 0) {

ways to speed up the Full Counting Sort

I encountered a question on hackerrank.
https://www.hackerrank.com/challenges/countingsort4
My first attempt passed all the test cases except the last one, due to timeout.
After failed to come up with a more efficient algorithm, I improved the code by using StringBuilder instead of concatenating Strings directly. This brought the running time from more than 5 sec to 3.5 sec.
My question is that is there any other way that I can improve the running time?
Thanks.
The following is my code.
public class Solution {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
scanner.nextLine();
int[] oriNum = new int[N];
String[] oriStr = new String[N];
int[] count = new int[100];
int[] indices = new int[100];
int[] output = new int[N];
// save the originals and the count array
for (int i = 0; i < N; i++) {
oriNum[i] = scanner.nextInt();
oriStr[i] = scanner.nextLine().trim();
count[oriNum[i]]++;
}
// accumulate the count array
indices[0] = 0;
for (int i = 1; i < 100; i++) {
indices[i] = indices[i-1] + count[i-1];
}
// output order
for (int i = 0; i < N; i++) {
int num = oriNum[i];
output[indices[num]++] = i;
}
int bar = N/2;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < N; i++) {
int index = output[i];
if (index < bar)
sb.append("- ");
else
sb.append(oriStr[index]+ " ");
}
System.out.println(sb.toString());
}
}
You should try a plain buffered reader instead of Scanner. Scanner is surprisingly slow and I have participated in programming competitions where Scanner was the sole reason for "time limit exceeded".
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution
{
public static void main(String[] args)throws Exception
{
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
int n=Integer.parseInt(in.readLine());
int[] c=new int[100];
String[][] dt=new String[100][10300];
for(int i=0;i<n;i++)
{
String[] str=in.readLine().split(" ");
int val=Integer.parseInt(str[0]);
if(i<n/2)
dt[val][c[val]]="-";
else
dt[val][c[val]]=str[1];
c[val]++;
}
StringBuilder sb=new StringBuilder("");
for(int i=0;i<100;i++)
if(i<n)
for(int k=0;k<c[i];k++)
if(dt[i][k]!=null)
sb.append(dt[i][k]+" ");
else break;
System.out.println(sb.toString());
}
}
This was my approach to problem. (it is in c++).
void counting_sort(vector<int> &arr, int size, vector<vector<string> > foo, vector<int> first_half)
{
int max = *max_element(arr.begin(), arr.end());
int min = *min_element(arr.begin(), arr.end());
int range = max - min + 1;
int count[range] = {0};
// counting frequency of numbers in array
for (int i = 0; i < size; i++)
{
count[arr[i] - min]++;
}
// calculating cumulative sum
for (int i = 1; i < range; i++)
{
count[i] += count[i - 1];
}
vector<vector<string> > output(size);
// making the new sorted array
for (int i = size - 1; i >= 0; i--) // traversing from backward for stability
{
output[count[arr[i]-min] - 1] = foo[i];
count[arr[i]-min]--;
}
// copying the sorted array in original array
int j=0;
for (int i = 0; i < size; i++)
{
if(stoi(output[i][0]) == first_half[j])
{
cout << "- ";
j++;
}
else
{
cout << output[i][1] << ' ';
}
}
}
// Complete the countSort function below.
void countSort(vector<vector<string>> arr) {
vector<int> num;
vector<int> first_half;
for(int i=0; (unsigned)i<arr.size(); i++)
{
num.push_back(stoi(arr[i][0]));
if(i < ((unsigned)arr.size()/2))
{
first_half.push_back(stoi(arr[i][0]));
}
}
sort(first_half.begin(), first_half.end());
counting_sort(num, num.size(), arr, first_half);
}

Categories

Resources