Java - Recursion to find the 2 smallest nums in array - java

So I have this problem of finding the 2 smallest numbers in array but I have to use recursion (the recursion part is a part of this exercise).
I start thinking how to do it and 'the plan' that I trying to do is like this, first of all find the smallest in the array, then mark where I found it and then to split the array in to 2 groups and search in this 2 group an eventuality take the minimum from them..
this is the code that I got this far:
public static int MinRecu2(int[] a) {
if (a.length == 1)
return a[0];
int min = a[0];
int min2;
int mark = 0;
// Find first min
for (int i = 1; i < a.length; i++) {
if (a[i] < min) {
min = a[i];
mark = i;
}
}
int [] help1= new int [mark+1];
int [] help2= new int [a.length-mark];
help1=Arrays.copyOfRange(a, 0, mark);
help2=Arrays.copyOfRange(a, mark+1, a.length-1);
// Find second min
min2 = Math.min(MinRecu2(help1), MinRecu2(help2));
return min;
}
I know the code not working and that the 'recursion' I was trying to do is bad, but that how I was trying to make my thinking to code

This is an approach to your question.
public static int[] twoSmallest(int[] arr, int s, int e) {
int[] list;
if (e - s <= 3) { // maybe 2 or 3
list = new int[e - s];
for (int i = s; i < e; i++)
list[i - s] = arr[i];
} else {
int[] left = twoSmallest(arr, s, (s + e) / 2);
int[] right = twoSmallest(arr, (s + e) / 2, e);
list = new int[4];
list[0] = left[0];
list[1] = left[1];
list[2] = right[0];
list[3] = right[1];
}
Arrays.sort(list);
return new int[] {list[0], list[1]};
}
This function means find two smallest numbers in arr in [s, e). You can call like this:
int[] result = twoSmallest(arr, 0, arr.length);

private static int findMinFromArray(int[] iArray, int index, int min) {
if(index <= (iArray.length - 1)){
if(iArray[index] < min){
min = iArray[index];
}
System.out.println("Before: " + "Index = " + index + " | Min = " + min);
findMinFromArray(iArray, index + 1, min);
}
System.out.println("After: " + "Index = " + index + " | Min = " + min);
return min;
}
I'm not sure how to get the program to stop, rather than going back again like it's doing.This finds only smallest.

Related

Returning the different length to maximize profit when cuttting a rod

My program have to display in what different lengths to cut a rod in order to maximize profit.
This is my function for the rod cutting:
It takes as parameter an array lengths (1 to 8), an array profit (1,5,8,9,10,17,17,20), and the length of the rod.
public static void rodCut(int[] lengths, int[] profit, int len){
int lengthInput = lengths.length-1;
int[][] cuttingLength = new int[lengthInput + 1][len + 1];
int[] chosenElement = new int[lengthInput + 1];
int[][] maximum = new int[lengthInput + 1][len + 1];
int numA;
int numB=0;
int a = 1;
while(a <=lengthInput) {
int i=0;
while(i<=len) {
numA = maximum[a - 1][i];
if (i >= lengths[a]) {
numB = profit[a] + maximum[a - 1][i - lengths[a]];
}
maximum[a][i] = Math.max(numA,numB);
if(numA<numB) {
cuttingLength[a][i]=1;
}
else {
cuttingLength[a][i]=0;
}
i++;
numB=0;
}
a++;
}
//we represent the selected element with a 1, else, 0
int z = lengthInput;
int l = len;
while(z>0) {
if (cuttingLength[z][l] > 0){
chosenElement[z] = 1;
l = l - lengths[z];
}
else {
chosenElement[z] = 0;
}
z--;
}
//indicate which length it needs to be cut
int j=1;
String rods = "";
String tmp = "";
while(j<lengthInput+1) {
if (chosenElement[j] == 1) {
tmp+=lengths[j]+", ";
}
j++;
}
rods = tmp.substring(0,tmp.length()-2);
System.out.print("\nLengths to be cut: "+rods+"");
}
I am not getting the desired output when the length is large.
Suppose the length is 40.
The output should be : Lengths to be cut: 2,2,2,2,2,6,6,6,6,6
But i am getting: Lengths to be cut: 1,2,3,4,5,6,7,8

HackerRank Task "Mini Max Sum" solution not passing 3 of the 13 test cases, can someone tell me what i'm doing wrong

This is for the "Mini Max Sum" problem on HackerRank, I can't see why it doesn't have a check mark on all of the test cases. Can someone tell me where my problem lies at. The question is:
Print two space-separated long integers denoting the respective minimum and maximum values that can be calculated by summing exactly four of the five integers. (The output can be greater than 32 bit integer.)
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long[] arr = new long[5];
long total = 0, max = 0, min = 0;
for(int arr_i=0; arr_i < 5; arr_i++){
arr[arr_i] = in.nextLong();
min = arr[0];
total += arr[arr_i];
if (arr[arr_i] > max)
max = arr[arr_i];
if (arr[arr_i] <= min)
min = arr[arr_i];
}
System.out.println((total - max) + " " + (total - min));
}
}
This also worked. Thanks!!
static void miniMaxSum(int[] arr) {
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
Collections.sort(list);
long x=0, y=0;
for(int j=0;j<(list.size()-1);j++){
x = x + list.get(j);
y = y + list.get(j+1);
}
System.out.println(x +" "+y);
}
The problem are the initial values of both min and max.
min is being reset to the first values inside the loop, so it will probably only work if the first or the last value is the minimum one;
max starts with zero, so if all values are negative, max will stay at zero (instead of one of the input values).
Hints: set min and max on the first iteration (i == 0) or, as suggested, use Integer.MAX_VALUE and Integer.MIN_VALUE respectively as initial value (actually long is not needed for min and max, neither is the array)
This is what worked for me in JavaScript:
var sum = 0;
var arry = [];
function miniMaxSum(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr.length; j++) {
if (arr[j] !== arr[i]) {
sum += arr[j];
}
}
arry.push(sum);
sum = 0;
}
var min = Math.min(...arry);
var max = Math.max(...arry);
console.log(min, max);
}
static void miniMaxSum(int[] arr) {
int temp = 0;
for (int i = 0; i < arr.length; i++)
{
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
long minSum = 0;
long maxSum = 0;
for(int i = 1; i< arr.length; i++){
maxSum = maxSum + arr[i];
}
for(int i = 0; i< arr.length-1; i++){
minSum = minSum + arr[i];
}
System.out.print(minSum+ " " +maxSum);
}
Worked for me on Python3!
def miniMaxSum(arr):
total = sum(arr)
low = total - min(arr)
high = total - max(arr)
print(high, low)
return
import math
import os
import random
import re
import sys
def miniMaxSum(arr):
arr.sort()
m = sum(arr)
max_num = m - arr[-1]
min_num = m - arr[0]
print(max_num, min_num)
if __name__ == '__main__':
arr = list(map(int, input().rstrip().split()))
miniMaxSum(arr)
This worked for me.
import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;
import java.util.stream.LongStream;
public class Solution {
// Complete the miniMaxSum function below.
static void miniMaxSum(int[] arr) {
long[] longs = Arrays.stream(arr).asLongStream().toArray();
Arrays.sort(longs);
long sum = LongStream.of(longs).sum();
long min = sum - longs[4];
long max = sum - longs[0];
System.out.println(min + " " + max);
}
private static final Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
int[] arr = new int[5];
String[] arrItems = scanner.nextLine().split(" ");
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
for (int i = 0; i < 5; i++) {
int arrItem = Integer.parseInt(arrItems[i]);
arr[i] = arrItem;
}
miniMaxSum(arr);
scanner.close();
}
}
Here's a hint in the question: minimum and maximum values that can be calculated by summing exactly four of the five integers.
Just sort the array first, assuming the array is not sorted. Take two for loop because we want to keep the complexity up to O(n) i.e. Linear.
from 1st index to n - 1. Assuming index starts from 0. This will give you sum of all the element except the smallest element which will be the largest sum.
from 0th index to n - 2. Assuming index starts from 0. This will give you sum of all the element except the largest element which will be the least sum.
Let's say, Our initial numbers are 1, 2, 3, 4 and 5.
We can calculate the following sums using four of the five integers:
If we sum everything except 1, our sum is 2 + 3 + 4 + 5 =14.
If we sum everything except 2, our sum is 1 + 3 + 4 + 5 =13.
If we sum everything except 3, our sum is 1 + 2 + 4 + 5 =12.
If we sum everything except 4, our sum is 1 + 2 + 3 + 5 =11.
If we sum everything except 5, our sum is 1 + 2 + 3 + 4 =10.
public static void minmaxsum(int[] ar1) {
long a, b, c, d, e;
a = (long) ar1[1] + (long) ar1[2] + (long) ar1[3] + (long) ar1[4];
System.out.println(a);
b = (long) ar1[0] + (long) ar1[2] + (long) ar1[3] + (long) ar1[4];
System.out.println(b);
c = (long) ar1[0] + (long) ar1[1] + (long) ar1[3] + (long) ar1[4];
System.out.println(c);
d = (long) ar1[0] + (long) ar1[1] + (long) ar1[2] + (long) ar1[4];
System.out.println(d);
e = (long) ar1[0] + (long) ar1[1] + (long) ar1[2] + (long) ar1[3];
System.out.println(e);
long[] df = new long[] { a, b, c, d, e };
long max = df[0];
for (int i = 0; i < df.length; i++) {
if (df[i] > max) {
max = df[i];
}
}
long min = df[0];
for (int i = 0; i < df.length; i++) {
if (df[i] < min) {
min = df[i];
}
}
System.out.println(min + " " + max);
}
This answer is in PYTHON language. I am a beginner and any improvements are welcome
n = input().split(" ")
n=list(n)
n1 = list(map(int,n))
n2 = list(map(int,n))
n1.sort()
n1.pop()
min =0
max=0
for i in n1:
min+=i
n2.sort()
n2.reverse()
n2.pop()
for j in n2:
max+=j
print(min, max)

Smallest sum of triplet products where the middle element is removed using Dynamic Programming

I have given a sequence of N numbers (4 ≤ N ≤ 150). One index i (0 < i < N) is picked and multiplied with the left and the right number, in other words with i-1 and i+1. Then the i-th number is removed. This is done until the sequence has only two numbers left over. The goal is to find the smallest sum of these products which obviously depends on the order in which the indices are picked.
E.g. for the sequence 44, 45, 5, 39, 15, 22, 10 the smallest sum would be 17775
using the indices in the following order: 1->3->4->5->2 which is the sum:
44*45*5 + 5*39*15 + 5*15*22 + 5*22*10 + 44*5*10 = 9900 + 2925 + 1650 + 1100 + 2200 = 17775
I have found a solution using a recursive function:
public static int smallestSum(List<Integer> values) {
if (values.size() == 3)
return values.get(0) * values.get(1) * values.get(2);
else {
int ret = Integer.MAX_VALUE;
for (int i = 1; i < values.size() - 1; i++) {
List<Integer> copy = new ArrayList<Integer>(values);
copy.remove(i);
int val = smallestSum(copy) + values.get(i - 1) * values.get(i) * values.get(i + 1);
if (val < ret) ret = val;
}
return ret;
}
}
However, this solution is only feasible for small N but not for a bigger amount of numbers. What I am looking for is a way to do this using an iterative Dynamic Programming approach.
The optimal substructure needed for a DP is that, given the identity of the last element removed, the elimination strategy for the elements to the left is independent of the elimination strategy for the elements to the right. Here's a new recursive function (smallestSumA, together with the version from the question and a test harness comparing the two) incorporating this observation:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Foo {
public static void main(String[] args) {
Random r = new Random();
for (int i = 0; i < 10000; i++) {
List<Integer> values = new ArrayList<Integer>();
for (int n = 3 + r.nextInt(8); n > 0; n--) {
values.add(r.nextInt(100));
}
int a = smallestSumA(values, 0, values.size() - 1);
int q = smallestSumQ(values);
if (q != a) {
System.err.println("oops");
System.err.println(q);
System.err.println(a);
System.err.println(values);
}
}
}
public static int smallestSumA(List<Integer> values, int first, int last) {
if (first + 2 > last)
return 0;
int ret = Integer.MAX_VALUE;
for (int i = first + 1; i <= last - 1; i++) {
int val = (smallestSumA(values, first, i)
+ values.get(first) * values.get(i) * values.get(last) + smallestSumA(values, i, last));
if (val < ret)
ret = val;
}
return ret;
}
public static int smallestSumQ(List<Integer> values) {
if (values.size() == 3)
return values.get(0) * values.get(1) * values.get(2);
else {
int ret = Integer.MAX_VALUE;
for (int i = 1; i < values.size() - 1; i++) {
List<Integer> copy = new ArrayList<Integer>(values);
copy.remove(i);
int val = smallestSumQ(copy) + values.get(i - 1) * values.get(i) * values.get(i + 1);
if (val < ret)
ret = val;
}
return ret;
}
}
}
Invoke as smallestSum(values, 0, values.size() - 1).
To get the DP, observe that there are only N choose 2 different settings for first and last, and memoize. The running time is O(N^3).
If anyone is interested in a DP solution, based on David Eisenstat's recursive solution, here is an iterative one using DP (for many big numbers it's useful to replace int's with long's):
public static int smallestSum(List<Integer> values) {
int[][] table = new int[values.size()][values.size()];
for (int i = 2; i < values.size(); i++) {
for (int j = 0; j + i < values.size(); j++) {
int ret = Integer.MAX_VALUE;
for (int k = j + 1; k <= j + i - 1; k++) {
int val = table[j][k] + values.get(j) * values.get(k) * values.get(j + i) + table[k][j + i];
if (val < ret) ret = val;
}
table[j][j + i] = ret;
}
}
return table[0][values.size() - 1];
}

Printing an array from lowest to highest without sorting

I want to start off by saying I am not very experienced and I am sorry if this has been answered. I have been trying to find an answer for a while and have not been able to.
I am working on a project where the user inputs numbers into an array. These numbers represent temperatures for different days. The days are obviously the position in the array. I need to find a way to print the temperatures from least to greatest without sorting the array.
So if the user entered [56, 45, 67, 41, 59, 70] that means that it was 56 degrees at position 0 (day 1), 67 degrees at position 2 (day 3). I need to keep the position of the array the same so the days remain with the temps when it prints out.
Edit: I have attached the code I have on my project so far. The HighestOrdered method is the method I dont know what to do or where to start. For the HighestOrdered method as I said above I need to have it print out the temps with the day (the position in the array) and I am not sure how to do that.
This is the code I have so far:
public class Weather {
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] high = new int[30];
int [] low = new int[30];
Init (high);
Init(low);
LoadData(high,low);
Report(high, low);
FindAvg(high,low);
Lowest(high, low);
Highest(high,low);
}
public static void Init(int A[])
{
for(int i = 0; i < A.length; i++)
{
A[i] = 510;
}
}
public static void Report(int[] H, int[] L)
{
System.out.println("Day High Low");
for(int i = 0; i < H.length; i++)
{
System.out.println(i + " " + H[i] + " " + L[i]);
}
}
public static void LoadData(int[] H, int[] L)
{
int day = 0;
while(day < 30)
{
try {
int high = Integer.parseInt(JOptionPane.showInputDialog("please enter the high"));
H[day] = high;
} catch (NumberFormatException e) {
}
try {
int low = Integer.parseInt(JOptionPane.showInputDialog(" Please enter the low"));
L[day] = low;
} catch (NumberFormatException e) {
}
day++;
}
}
public static void FindAvg(int[] H, int[] L){
int sumHigh = 0;
int avgHigh;
int sumLow = 0;
int avgLow;
for(int i : H)
sumHigh += i;
avgHigh = sumHigh/H.length;
for(int i : L)
sumLow += i;
avgLow = sumLow/L.length;
System.out.println("The average for the high is: " + avgHigh);
System.out.println("The average for the low is: " + avgLow);
}
public static void Highest(int[] H, int[] L)
{
int highestHigh = -1000;
int dayHigh = 0;
int highestLow = -1000;
int dayLow = 0;
for(int i = 0; i < H.length; i++)
{
if(H[i] > highestHigh && H[i] != 510)
{
highestHigh = H[i];
dayHigh = i;
}
}
System.out.println("\n" + "The highest high is: " + highestHigh + " degrees." + "\n" +
"This temperature was recorded on day: " + dayHigh);
for(int i = 0; i < L.length; i++)
{
if(L[i] > highestLow && L[i] != 510)
{
highestLow = L[i];
dayLow = i;
}
}
System.out.println("\n" + "The highest low is: " + highestLow + " degrees." + "\n" +
"This temperature was recorded on day: " + dayLow);
}
public static void Lowest(int[] H, int[] L)
{
int lowestHigh = 1000;
int dayHigh = 0;
int lowestLow = 1000;
int dayLow = 0;
for(int i = 0; i < H.length; i++)
{
if(H[i] < lowestHigh)
{
lowestHigh = H[i];
dayHigh = i;
}
}
System.out.println("\n" + "The lowest high is: " + lowestHigh + " degrees." + "\n" +
"This temperature was recorded on day: " + dayHigh);
for(int i = 0; i < L.length; i++)
{
if(L[i] < lowestLow)
{
lowestLow = L[i];
dayLow = i;
}
}
System.out.println("\n" + "The lowest low is: " + lowestLow + " degrees." + "\n" +
"This temperature was recorded on day: " + dayLow);
}
public void HighestOrdered(int[] H)
{
}
}
Here's a start.
From your array, create a sorted Map, say
Map<Integer,Integer> mymap = new TreeMap<Integer,Integer>.
You will use temp for the key and the day for the value. e.g., from your example data,
myMap.put(56,1);
myMap.put(45,2);
(Note - in the real code you'd iterate over the array to put the values.)
Then you can iterate over the keys and values (or the entries) in myMap.
Here is a small example to show how this can be done. Only the auxiliary index array is sorted, the original temp array is not changed.
public static void main(String[] args) {
final int [] temp = {56, 45, 67, 41, 59, 70};
Integer [] index = new Integer[temp.length];
for (int i = 0; i < index.length; i++) {
index[i] = i;
}
Arrays.sort(index, new Comparator<Integer>() {
#Override
public int compare(Integer a, Integer b) {
return temp[a] - temp[b];
}
});
for (Integer i : index) {
System.out.printf("temp %d on day %d%n", temp[i], i);
}
}
This gives the output:
temp 41 on day 3
temp 45 on day 1
temp 56 on day 0
temp 59 on day 4
temp 67 on day 2
temp 70 on day 5
Instead of your current array, you can create an object array with each object having two elements: the day and the corresponding temperature.
Sort this array by the temperature value and then print it.

Maximum subsequence sum in an array with no 3 consecutive number

I have to find the maximum sum in an array such that no 3 consecutive number together
for eg
3 4 5 1 2
should return me 11. (4+5+2)
I am getting out as 9.
I am using dynamic programming since I want the running time to be O(N)
The idea is s array will store the max sum and s1 array will store the length of input seen to keep track of consecuent numbers
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
public class ex {
public static int maxSubArraySum(int a[], int size)
{
int s[]= new int[size+1];
s[0]=0;
int s1[]= new int[size+1];
s1[0]=0;
for (i = 1; i <= size; i++)
{
s1[i]= 1+s1[i-1];
if(s1[i]<3) {
int k=Math.max(s[i-1], a[i-1]+s[i-1]);
s[i]=k;
}
else {
s[i]=Math.max(a[i-1], a[i-1]+a[i]);
s1[i]=0;
}
}
return s[s.length-1];
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc= new Scanner(System.in);
int size=sc.nextInt();
int a[]=new int[size];
for(int i=0;i<size;i++) {
a[i]=sc.nextInt();
}
System.out.println(maxSubArraySum(a, a.length));
}
}
I think your code requires a slight tweak, below are the changes you need to make
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
public class ex
{
public static int maxSubArraySum(int a[], int size)
{
int s[] = new int[size+2];
//they will form your base cases
s[0] = 0;
s[1] = a[0];
s[2] = a[0] + a[1];
for(int i = 2; i < size; i++)
{
s[i+1] = Math.max(a[i] + s[i-1], a[i] + a[i-1] + s[i-2]);
s[i+1] = Math.max(s[i+1], s[i]);
}
return s[size];
}
public static void main(String[] args)
{
Scanner sc= new Scanner(System.in);
int size=sc.nextInt();
int a[]=new int[size];
for(int i=0;i<size;i++)
{
a[i]=sc.nextInt();
}
System.out.println(maxSubArraySum(a, a.length));
}
}
Hope this helps.
Consider the array starts from index 0...n-1 i.e a[0...n-1],
we create array table[n+1] and table[i] means maximum sum from 1 to i without no three continuous numbers. While computing table[i], we have to choose whether to select i th element or not.
So, three cases are there
Case 1: Since, we can't select three consecutive numbers, but can select two consecutive numbers and skipping third one.
Case 2: select i th element and skip (i-1) th element.
Case 3: If we doesn't select i th element
So, based on above discussion c++ code is given below:
int max_sum_no_three_consecutive(int a[], int n)
{
int table[n+1];
table[0] = 0;
table[1] = a[0];
table[2] = a[1];
for (int i = 3; i <= n; i++) table[i] = max_3(table[i-1], table[i-2] + a[i-1], a[i-1] + a[i-2] + table[i-3]);
return table[n];
}
It's an old post but thought of answering the question.
for(int i = 0; i < input.length; i++) {
if(0 == i) {
sum[i] = input[0];
} else if(1 == i) {
sum[i] = input[0] + input[1];
} else if(2 == i){
sum[i] = getMaxOf3(sum[i - 1], sum[i-2] + input[i], input[i] + input[i - 1]);
} else {
sum[i] = getMaxOf3(sum[i - 1], sum[i - 2] + input[i], sum[i - 3] + input[i] + input[i - 1]);
}
}
int getMaxOf3(int x,
int y,
int z) {
return Math.max(Math.max(x, y), z);
}
Explanation:
Consider the array: {3, 4, 5, 1, 2}
we need to first have some default values for the result array.
sum[0] = array[0];
sum[1] = array[0] + array[1];
sum[2] = maximum of either (arr[0] + arr[1]) or (arr[1] + ar[2]) or (arr[0] + arr[2])
We calculated 3 sums,as we will be using these for furthur sum calculations.
sum[3] = max(sum[2], sum[1] + arr[3], sum[0] + arr[3] + arr[2]);
This reduces to,
sum[i] = max(sum[i - 1], sum[i - 2] + arr[i], sum[i - 3] + arr[i] + arr[i - 1]);

Categories

Resources