write an algorithm to find the maximum value - java

Example:
numbers are [1, 2, 3] and u have +, *
max value is 1+2*3
example [1, 1, 1] , ans is 1+1+1
I can think of a simple recursive algorithm:
private static double helper(double[] arr, int s, int e) {
System.out.println("s= " + s + " e= " + e);
//base case: if single elem, return that eleme
if (e==s) {
return arr[s];
} if (s+1==e) {
return Math.max(arr[s]+arr[e], arr[s]*arr[e]);
} else if (s>e) {
//this should never happen
throw new UnsupportedOperationException("invalid operation");
}
//int mid = s+ ((e-s)/2);
int mid=s;
double fMax = Double.MIN_VALUE;
for (mid=s;mid<e;mid++) {
//divide and conqr route
double lres = helperDQ(arr,s, mid);
double rres = helperDQ(arr,mid+1, e );
System.out.println("s= " + s + " e = " + e + " m = " + mid + " lres= " + lres + " rres= " + rres);
fMax = Math.max(fMax, Math.max(lres*rres, lres+rres));
}
return fMax;
}
private static double findMax(double[] arr) {
return helper(arr, 0, arr.length-1);
}
Is there a better way to do instead of this recursive way? We can prune the recursion by checking for s, e so we dont end up recursing same thing multiple times.
Can't think of an easy dynamic programming approach way.
Any suggestions?

This can actually be solved a lot easier, using some simple math. For any two numbers a and b, the following applies: unless either a = 1 or b = 1 is given, a * b >= a + b is given (assuming a >= 1 and b >= 1). This applies recursively to any set of numbers. Thus the maximum will always be achieved by
int maxNum(int[] nums){
int x = 0;
for(int n : nums)
if(n == 1)
x += n;
else
if(x == 0)
x = n;
else
x *= n;
return x;
}
If the set of numbers is order.

Related

transforming an iterative function to recursive in java

i want to transform this function to recursive form could anyone help me thx
that function is to solve this stuff
X=1+(1+2)*2+(1+2+3)*2^2+(1+2+3+4)*2^3+ . . . +(1+2+3+4+. . . +n)*2^(n-1)
public static int calcX(int n) {
int x=1;
int tmp;
for(int i = 1 ; i <= n-1;i++) {
tmp=0;
for(int j = 1 ; j <= i + 1;j++) {
tmp+=j;
}
x+=tmp*Math.pow(2, i);
}
return x;
}
my attempt im new to recursive stuff
public static int calcXrecu(int n,int tmp,int i,int j) {
int x=1;
if(i <= n-1) {
if(j <= i) {
calcXrecu(n,tmp+j,i,j+1);
}
else {
x = (int) (tmp*Math.pow(2, i));
}
}
else {
x=1;
}
return x;
}
You have a sequence of sums which themselves are sums.
The nth term can be derived from the (n-1)th term like this:
a(n) = a(n-1) + (1+2+3+....+n) * 2^(n-1) [1]
and this is the recursive formula because it produces each term via the previous term.
Now you need another formula (high school math) for the sum of 1+2+3+....+n:
1+2+3+....+n = n * (n + 1) / 2 [2]
Now use [2] in [1]:
a(n) = a(n-1) + n * (n + 1) * 2^(n-2) [3]
so you have a formula with which you can derive each term from the previous term and this is all you need for your recursive method:
public static int calcXrecu(int n) {
if (n == 1) return 1;
return calcXrecu(n - 1) + n * (n + 1) * (int) Math.pow(2, n - 2);
}
This line:
if (n == 1) return 1;
is the exit point of the recursion.
Note that Math.pow(2, n - 2) needs to be converted to int because it returns Double.
In addition to #forpas answer, I also want to provide a solution using corecursion by utilizing Stream.iterate. This is obviously not a recursive solution, but I think it is good to know alternatives as well. Note that I use a Pair to represent the tuple of (index, value).
public static int calcXcorecu(final int n) {
return Stream.iterate(
Pair.of(1, 1), p -> {
final int index = p.getLeft();
final int prev = p.getRight();
final int next = prev + index * (index + 1) * (int) Math.pow(2, index - 2);
return Pair.of(index + 1, next);
})
// only need the n-th element
.skip(n)
.limit(1)
.map(Pair::getRight)
.findFirst()
.get();
}

Recursive function not working as expected

I am trying to write the code for recursive function which prints every power of 2 from 1 to N, N is the argument of power function.
Function : int powers(n)
Currently I wrote this code:
int powers(int n) //here n=128
{
if(n==2)
{
System.out.print(n);
}
else if (n>2)
{
System.out.print(n +", ");
return powers(n/2);
}
System.out.println("");
return 0;
}
Output : 128, 64, 32, 16, 8, 4, 2
Expected : 2, 4, 8, 16, 32, 64, 128
As the purpose of your function is printing the powers of 2, you do not need to return the value. Hence, you can rewrite your function as the following:
int powers(int N) //here N=128
{
if(N==2){
System.out.print(N + ", ");
}
else if (N >2)
{
powers(N/2);
System.out.print(N + ", ");
}
System.out.println("");
return 0;
}
Also to handle the last extra comma you can return the previous step string and print outside the function.
String powers(int N) //here N=128
{
if(N==2){
return (N + "");
}
String prev = powers(N/2);
return (prev + ", " + N);
}
I think this would be a more elegant way to achieve this. Improvements are supposed to be:
Use bit shifting when possible to gain some
performance.
Fix comma placement for all cases of input N
More elegant looking code
int powers(int N) //here N=128
{
if (N < 2) return 0;
powers(N >> 1); // Right shifting achieves division by 2 but a lot faster.
if (N > 3) System.out.print(", "); // Fixing comma placement for all cases of N.
System.out.print(N);
return 0;
}
Why are we making the assumption that the input N is already a power of 2? Besides, 2 ^ 0 = 1, should that be in the result as well?
public int power(int num) {
if (num <= 0)
return -1;
else if (num <= 1) {
System.out.print(1);
return 1;
} else if (num <= 2) {
System.out.print(1 + ", " + 2);
return 2;
} else {
int result = 2 * power(num / 2);
System.out.print(", " + result);
return result;
}
}
This works even if you give 131 as the input.

How to optimize/change a "searching" program Java

I have written some java code to determine the sum of what three cubes give you a given number. (Sorry I'm really not sure how to explain what it does, the code is rather simple though.) And the problem is, when searching for numbers between -100 and 100 the code runs very quick. But when searching a bigger area, (thousands or ten-thousands etc) It starts to run very slow, even when looking for small numbers. What I am asking are for ways to optimize it, and maybe ways to have it search more systematically, starting at small integers and working its way up to bigger ones, rather than how it does it now which is to pick random ones and check them with the answer.
Here is the code:
public class test{
public static void main(String[] args)
{
int want = -69;
double test;
boolean found = false;
int answer;
while(found == false)
{
int max = 100;
int min = max / 2;
int a = (int) (Math.random()*max - min);
int b = (int) (Math.random()*max - min);
int c = (int) (Math.random()*max - min);
test = Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3);
answer = (int) test;
if(answer == want) {
found = true;
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
}
}
}
}
This is generally not an easy problem. A more systematic way of doing this would be to test every possible combination of a,b and c within a given range of values for a,b and c. Like this:
public class Main{
static boolean foundSolution = false;
public static void main(String []args){
int limit = 10;
boolean[][][] alreadyChecked = new boolean[limit*2+1][limit*2+1][limit*2+1];
foundSolution = false;
printCubesOfNum(-69,limit,0,0,0,alreadyChecked);
}
public static void printCubesOfNum(int answer,int limit, int a, int b, int c,boolean[][][] alreadyChecked) {
if(!foundSolution && !alreadyChecked[a+limit][b+limit][c+limit] && a < limit && a > -limit && b < limit && b > -limit && c < limit && c > -limit) {
alreadyChecked[a+limit][b+limit][c+limit] = true;
int test = (int)Math.pow(a, 3) + (int)Math.pow(b, 3) + (int)Math.pow(c, 3);
if(test == answer) {
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
foundSolution = true;
}else{
printCubesOfNum(answer,limit,a+1,b,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b+1,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b,c+1,alreadyChecked);
printCubesOfNum(answer,limit,a-1,b,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b-1,c,alreadyChecked);
printCubesOfNum(answer,limit,a,b,c-1,alreadyChecked);
}
}
}
}
Note that this code stops after it found a solution. There can be multiple solutions and there can also be no solutions.
You can check out a similar question on mathoverflow here.
What I am asking are for […] maybe ways to have it search more systematically, starting at small integers and working its way up to bigger ones, […]
Instead of a while-loop, you might consider using nested for-loops:
for (int a = min; a < max; ++a) {
for (int b = min; b < max; ++b) {
for (int c = min; c < max; ++c) {
int answer = (int) (Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3));
if (answer == want) {
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
return;
}
}
}
}
But you don't actually need to try each possible value for c; rather, you know that c3 = want − a3 − b3; so you can just calculate that directly, and see if it works out:
for (int a = min; a < max; ++a) {
for (int b = min; b < max; ++b) {
// Note: the '0.1' is to be robust if there's some roundoff error:
int c = (int) (0.1 + Math.pow(want - Math.pow(a, 3) - Math.pow(b, 3), 1.0/3.0));
int answer = (int) (Math.pow(a, 3) + Math.pow(b, 3) + Math.pow(c, 3));
if (answer == want && c >= min && c <= max) {
System.out.println(a + " " + b + " " + c);
System.out.println(answer);
return;
}
}
}
And for that matter, the symmetry of the problem (the commutative law of addition) means that we only need to try values of b that are at least equal to a:
for (int b = a; b < max; ++b) {
Another optimization is to avoid Math.pow(..., 3), which is generally much less efficient than ... * ... * ... (because Math.pow has to support non-integer exponents, so it works by taking a logarithm and an exponentiation):
int c = (int) (0.1 + Math.pow(want - a * a * a - b * b * b, 1.0/3.0));
int answer = a * a * a + b * b * b + c * c * c;
Yet another optimization is to restrict the range of b, in the inner for-loop, to only include values that would put c in the range of [min, max): we know that if b is too small, then c would have to be too big, and vice versa:
int minB = (int) (0.1 + Math.pow(want - a * a * a - max * max * max, 1.0/3.0));
if (minB < a) {
minB = a;
}
int maxB = (int) (0.1 + Math.pow(want - a * a * a - min * min * min, 1.0/3.0)) + 1;
if (maxB > max) {
maxB = max;
}
for (int b = minB; b < maxB; ++b) {
Of course, these sorts of optimizations can only take you so far. If you want to search a large range of integers, that will necessary take a lot of time. But the above should still be a massive improvement over what you have now.

Hailstone recursion not working in Java

I am trying to write a simple Java program to compute a hailstone sequence using recursion. A hailstone sequence is basically: take a given integer n - if even, the next integer in the sequence is n/2, if odd, the next integer in sequence is n * 3 + 1. I'm trying to return a string with each number separated by a comma, but my algorithm isn't working. Can someone explain why? Thanks!
public static String recursion (int n) {
String s = "";
if (n != 1) {
if (n % 2 == 0) return s + String.valueOf(recursion(n / 2)) + ", ";
else return s + String.valueOf(recursion((3 * n) + 1)) + ", ";
}
else return s + String.valueOf(1);
}
public static void main(String[] args) {
System.out.println(recursion(435));
}
the problem is, you don't print the actual number n. Change your code to:
public static String recursion (int n) {
//set s to the number n
String s = "" + n;
if (n != 1) {
//change position of the separator
if (n % 2 == 0) return s + ", " + recursion(n / 2);
//change position of the separator
else return s + ", " + recursion((3 * n) + 1);
}
else return s;
}
EDIT:
btw. you don't need String.valueOf(), since the result is already a String

Listing the total sum of all possible sums in a set with constraints

I am keen to find out the following:
Given a set with N elements, my friend and I are playing a game.I always make the first move.
We can only remove either the first or the last element with 50% chance each.We take alternate turns in the game.If only one element remains,we can remove it for sure.What is the expected sum that I can collect?
For example:N=2 {10,20} Possible sets that I can collect are {10},{20}.
So expected sum is 0.5*10+0.5*20=15.
My approach:
Since probability of getting a possible sum is equal in all cases,we only need to compute the sum of all possible sums and then multiply it by (0.5)^N/2.
I tried to use recursion to compute the required sum:
f(i,j)-computes the sum between i and j recursively
f(i,j)=2*a[i]+func(i,j-2)+func(i+1,j-1)+func(i+1,j-1)+func(i+2,j)+2*a[j]);
Initial call f(1,N)
But the approach doesn't seem to work. What should I do?
Complete function is below:
class CandidateCode {
static long v[][] = new long[1003][1003];
public static long func(int a[], int i, int j) {
if (i == j)
return v[i][j] = a[i];
if (v[i][j] != 0)
return v[i][j];
else {
if (i > j - 2 && i + 1 > j - 1 && i + 2 > j)
return (v[i][j] += 2 * a[i] + 2 * a[j]);
else
return (v[i][j] += 2 * a[i] + func(a, i, j - 2) + func(a, i + 1, j - 1) + func(a, i + 1, j - 1)
+ func(a, i + 2, j) + 2 * a[j]);
}
}
public static void main(String args[]) {
int n;
int a[] = { 0, 6, 4, 2, 8 };
n = a.length - 1;
System.out.println(func(a, 1, 4) / Math.pow(2, n / 2));
}
}
This problem can be solved by applying dynamic programming.
First, we have the state of the game is (player ,start, end) ,which indicates the current player, and the range of values that's available in the original set. At the beginning, we start at player 0 and start is 0, end is N - 1.
Denote that the first player is 0 and the second player is 1, we have the expected value of player 0:
if(player == 0){
double result = 0.5*( set[start] + f(1, start + 1,end) ) + 0.5*(set[end] + f(1,start, end - 1));
}else{
double result = 0.5*( f(0, start + 1,end) ) + 0.5*(f(0,start, end - 1));
}
So for each state, we can store all calculated state in a dp[player][start][end] table, which reduce the time complexity to O(2*N*N) with N is number of value in set.
Pseudo code:
double expectedValue(int player, int start, int end, int[]set){
if(start == end)
if(player == 0)
return set[start];
return 0;
if(already calculated this state)
return dp[player][start][end];
double result= 0;
if(player == 0){
result = 0.5*( set[start] + f(1, start + 1,end) ) + 0.5*(set[end] + f(1,start, end - 1));
}else{
result = 0.5*( f(0, start + 1,end) ) + 0.5*(f(0,start, end - 1));
}
return dp[player][start][end] = result;
}

Categories