How can I modify the methods cutRod and bottomUpCutRod to hold lengths that are bigger than the array length. For example, currently p has length 11, how can I cut the rod of length 15, 20 , etc, having this same array. For example
p = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
if I call cutRod(p,10), I get 30, but it crashes of course in cutRod(p,15) or
cutRod(p,20). (same applies for bottomUpCutRod). Any ideas how to do this?. This is dynamic programming problem, my idea to implement bottomUpCutRod method is to traverse p and for each element calculate every permutation of itself and its neighbors and update if necessary the resulting array, r.
public class Main {
private static final double MINUS_INFINITY = Double.NEGATIVE_INFINITY;
public static void main(String[] args) {
// price array
double[] p = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
// test cutRod
cutRod(p,10);
// test bottomUpCutRod
bottomUpCutRod(p,10);
}//end of main
// an optimal cut for a rod of length n
// p is the price array
// use recursion
private static double cutRod(double[] p, int value) {
double[] r = new double[value+1];
double out = 0;
// initialize r to NEGATIVE_INFINITY;
for (int i = 1; i < r.length; i++)
r[i] = MINUS_INFINITY;
// call the helper method
out = helpCutRod(p,r.length-1,r);
// print r
System.out.println("Result ");
System.out.println("r[" + (r.length-1) + "] = " + r[r.length-1]);
return out;
}//end of method
// helpCutRod computes an optimal cut for a rod
// p is the price array and r[i] is the optimal cut for a rod of length i
// n is the length of the rod that is currently being computed
private static double helpCutRod(double[] p, int n, double[] r) {
double q = MINUS_INFINITY;
if (r[n] >= 0) // the whole r was computed
return r[n];
if (n == 0)
q = 0;
else {
for (int i = 1; i <= n; i++) {
q = RodCutting.max(q, p[i] + helpCutRod(p,n-i,r));
}
r[n] = q;
}
return q;
}
// use the bottom-up approach
// do NOT use recursion
private static double bottomUpCutRod(double[] p, int len) {
// r[i] is the optimal cut for a rod of length i
double[] r = new double[len+1];
r[0] = 0;
for (int j = 1; j < p.length; j++) {
// compute r[j]
double q = MINUS_INFINITY;
// r[j] is the maximum over i of p[i] + r[j-i]
// where 1<= i <= j
for (int i = 1; i <= j; i++)
q = max(q, p[i] + r[j-i]);
// update value of r[j]
r[j] = q;
}//end of for outer
// print r
System.out.println("The r array from the bottomUpCutRod:");
System.out.println("r[" + len + "] = " + r[len]);
return r[len] ;
}//end of method
public static double max(double a, double b){
if(a<=b){
return b;
}else{
return a;
}
}//end of max
}//end of class
If I understand the rod cutting problem correctly, your price array, p, tells the prices at which you can sell rod pieces of lenghts 0 through p.length - 1. So if the array length is 11, you know the prices of pieces up to length 10 even if you have an inital rod of length 15, 20 or 30. Since you don’t know the prices for lengths 11 and above, I assume you can safely set them to 0. I would then expect the algorithm to cut up your rod into pieces for which you know a positive price.
If all of this is correct, the solution is easy. To calculate, say, cutRod(p, 15), first do
p = Arrays.copyOf(p, 15 + 1);
This will copy p into a new array with indices 0 through 15, padded with zeores. Now run your methods. Similarly for other initial lengths, of course.
With this modification, your program prints for a rod length of 15:
Result
r[15] = 43.0
The r array from the bottomUpCutRod:
r[15] = 43.0
I assume it’s found pieces at 10, 3 and 2 yielding prices 30 + 8 + 5 = 43, but I haven’t checked.
EDIT: If the rod is very much longer than the price array, it is probably wasteful to have it calculate results with cuts longer than the maximum of the price array. So instead of the above quick fix, it is in fact possible to modify your methods to accept a shorter price array and a longer initial rod.
In the recursive helpCutRod(), change the for loop to:
for (int i = 1; i <= Math.min(n, p.length - 1); i++) {
This will make sure that only pieces for which we have prices will be considered.
For bottomUpCutRod(), two changes are needed:
The first for loop needs to run until j equals len:
for (int j = 1; j < r.length; j++) {
And again, the inner for loop should not pass the bounds of p:
for (int i = 1; i <= Math.min(j, p.length - 1); i++)
With these three modifications instead of the extension of the p array, the program prints the same results as above.
Related
I'm trying to get the N smallest numbers (given by the user) in an array without using methods like sort()... in the last step, I keep getting only the smallest values and 0 for the rest.. where's the problem?
//1- Scanner to take inputs
Scanner input = new Scanner(System.in);
//2- Take the array size as input and store it in "sizeOfArr" var
System.out.print("Enter the array size: ");
int sizeOfArr = input.nextInt();
//3- Assign the input as an array size
int array[] = new int[sizeOfArr];
//4- Looping on the array and update its values by inputs taken from the user
for(int i = 0; i < array.length; i++) {
System.out.print("Enter "+ (i+1) + "-st element: ");
array[i] = input.nextInt();
}
//5- Print out the array after convert it to String
System.out.println(Arrays.toString(array));
//6- Find the smallest element in the array and print it
int minVal = array[0];
for(int i = 0; i < array.length; i++) {
if (array[i] < minVal) {
minVal = array[i];
}
}
// System.out.println(minVal);
//7- Find the (n) smallest of number defined by the user
System.out.print("Enter the number of smallest numbers do you want: ");
int n = input.nextInt();
//8- new array to store n smallest numbers
int smallestNums[] = new int[n];
//9- trying to loop on the original array n times
int counter;
for(int i = 0; i < n ; i++) {
//10- trying to loop on the original array to store the smallest values in smallestNum[] array.
for(int j = 0; j < array.length; j++) {
smallestNums[i] = minVal;
}
if(smallestNums[i] == smallestNums[i]) {
break;
}
}
System.out.println(Arrays.toString(smallestNums));
Here is one way. Just do a partial sort with the outer loop limit equal to the number of items required. This is variant of the selection sort. This example, varies n in the outer list for demo purposes.
int[] array = { 10, 1, 5, 8, 7, 6, 3 };
for (int n = 1; n <= array.length; n++) {
int[] smallest = getNSmallest(n, array);
System.out.printf("smallest %2d = %s%n", n,
Arrays.toString(smallest));
}
prints
smallest 1 = [1]
smallest 2 = [1, 3]
smallest 3 = [1, 3, 5]
smallest 4 = [1, 3, 5, 6]
smallest 5 = [1, 3, 5, 6, 7]
smallest 6 = [1, 3, 5, 6, 7, 8]
smallest 7 = [1, 3, 5, 6, 7, 8, 10]
Here is the method. The first thing to do is copy the array so the
original is preserved. Then just do the sort and return array of smallest elements.
public static int[] getNSmallest(int n, int[] arr) {
int[] ar = Arrays.copyOf(arr, arr.length);
int[] smallest = new int[n];
for (int i = 0; i < n; i++) {
for (int k = i + 1; k < ar.length; k++) {
if (ar[i] > ar[k]) {
int t = ar[i];
ar[i] = ar[k];
ar[k] = t;
}
}
smallest[i] = ar[i];
}
return smallest;
}
For this task, you don't have to sort the whole array. Only a group of N elements has to be sorted. I.e. only a partial sorting is required.
Below, I've provided two implementations for this problem. The first utilizes only plane arrays and loops, the second makes use of the PriorytyQueue.
The first solution maintains a variable pos which denotes the position in the result array which isn't assigned yet. Note that the default value for an element of the int[] is 0. It's important to be able to distinguish between the default value and a zero-element from the given array. Hence we can't rely on the values and have to track the number of elements that are assigned.
Every element of the source array gets compared with all the elements of the result array that are already assigned. The new element will be added to the result array in two cases:
nested loop has reached an unoccupied position pos in the result array;
an element in the result array that is greater than the next element from the given array has been found.
In the first case, a new element gets assigned the position denoted by pos. In the second case, a new element has to be inserted
nested loop iterates over the given array at the current position i and all elements must be shifted to the right. That's what the method shiftElements() does.
The First solution - Arrays & Loops
public static int[] getSmallest(int[] arr, int limit) {
int[] result = new int[Math.min(limit, arr.length)];
int pos = 0;
for (int next: arr) {
for (int i = 0; i < Math.min(pos + 1, result.length); i++) {
if (i == pos) result[i] = next;
else if (result[i] > next) {
shiftElements(result, next, i, Math.min(pos + 1, result.length));
break;
}
}
pos++;
}
return result;
}
private static void shiftElements(int[] arr, int val, int start, int end) {
int move = arr[start];
arr[start] = val;
for (int i = start + 1; i < end; i++) {
int temp = arr[i];
arr[i] = move;
move = temp;
}
}
Maybe you'll be more comfortable with the first version, but if you are somehow familiar with the Collections framework, then it's a good time to get acquainted with PriorytyQueue. In the nutshell, this collection is backed by an array and maintains its element in the same order as they were added, but when an element is being deleted collection retrieves the smallest one according to the natural order or based on the Comparator, which can be provided while instantiating the PriorytyQueue. It uses a sorting algorithm that is called a heapsort which allows removing a single element in O(log N) time.
The Second solution - PriorytyQueue
public static int[] getSmallestWithPriorityQueue(int[] arr, int limit) {
Queue<Integer> queue = new PriorityQueue<>();
populateQueue(queue, arr);
int[] result = new int[Math.min(limit, arr.length)];
for (int i = 0; i < result.length; i++) {
result[i] = queue.remove();
}
return result;
}
private static void populateQueue(Queue<Integer> queue, int[] arr) {
for (int next: arr) {
queue.add(next);
}
}
main & utility-method to generate an array
public static void main(String[] args) {
int[] source = generateArr(100, 10);
System.out.println("source : " + Arrays.toString(source));
int[] result1 = getSmallest(source, 3);
System.out.println("result(Arrays & Loops) : " + Arrays.toString(result1));
int[] result2 = getSmallestWithPriorityQueue(source, 3);
System.out.println("result(PriorityQueue) : " + Arrays.toString(result2));
}
public static int[] generateArr(int maxVal, int limit) {
Random random = new Random();
return IntStream.generate(() -> random.nextInt(maxVal + 1))
.limit(limit)
.toArray();
}
output
source : [61, 67, 78, 53, 74, 51, 50, 83, 59, 21]
result(Arrays & Loops) : [21, 50, 51]
result(PriorityQueue) : [21, 50, 51]
Randomized select allows to find k-th ranked element in linear time on average.
It alters the input order, so practically, it makes sense to just sort and return k-th element of the sorted array. Especially if there are several such calls on the given input array.
New guy here trying 2D arrays. I have these codes but whenever I run it, the lowest value would always end up with 0 even if I input non-zero digits. Any idea how to fix this?
import javax.swing.JOptionPane;
public class TwoDArrayActivity {
public static void main(String[] args){
// declaration of array
int a[][] = new int[3][3];
int i = 0; // rows
int j = 0; // columns
String display = "";
int low = a[i][j];
for(i=0; i < a.length; i++) { // count the number of rows
for(j = 0; j < 3; j++) { // count the number of columns
a[i][j] = Integer.parseInt(JOptionPane.showInputDialog("Enter a Number to Array [" + i + "]" + "[" + j + "]"));
if(a[i][j] < low)
low = a[i][j];
display = display + a[i][j] + " ";
} // end of inner for
display = display + "\n"; //new line
} // end of outer for
JOptionPane.showMessageDialog(null,"Values in Array\n" + display + "Lowest value is " + low, "Values in Array", JOptionPane.INFORMATION_MESSAGE);
} // end of method
} // end of class
Replace :
int low = a[i][j];
with :
int low = Integer.MAX_VALUE;
// declaration of array
int a[][] = new int[3][3];
The issue is here, when you instantiate the array it automatically fills every emtry with 0, as this is the equivalent of the undefined value for an integer type. eg.
new int[3][3]
>> [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Therefore your low variable always has the value 0 and is never replaced by something lower
When you initialize an array implicitly in Java, the memory gets set to null, 0, 0L, 0.0f, false, or 0.0, etc, as appropriate for the datatype.
That means that your statement int low = a[i][j]; is setting low to an initial value of zero. All further comparisons will be against that, so your only chance to change that value is to enter a negative number, like -1.
You can add a test to your loop to initialize low with the first element of the loop you get:
if((i == 0 && j == 0) || a[i][j] < low)
Another option is to initialize low to the largest possible integer instead of implicit zero. In this simple example, that's probably the simplest approach to take:
int low = Integer.MAX_VALUE;
A third option is to add a boolean flag:
int low = ...;
boolean isFirst = true;
...
if(isFirst || a[i][j] < low)
...
isFirst = False;
You have to input negative numbers for it to change.
Otherwise, you can change it to
if(a[i][j] < low)
low = a[i][j];
but the name low wouldn't make sense anymore (it will be a "max").
I'm working on implementing a java method based on this correlation formula:
(f * g)[n] = ∑ f[n+m] * g[m],
the lower bound of the summation
is m = 0, and the upper bound is M - 1,
where f is an array of size N
and g is an array of size M.
(f * g)[n] is an array of size N - M + 1
So for example if we have these arrays:
f = {1, 2, 3, 4}, g = {10, 20}
The result is this array:
(f * g)[n] = {1(10) + 2(20), 2(10) + 3(20), 3(10) + 4(20)}
= **{50, 80, 110}**
What I need to do is convert this into Java code. I'm starting by trying to write the code for this example, and then later come up with a more general case. Unfortunately I'm stuck on some of the Java syntax. This is what I currently have:
public static void main(String[] args) {
double[] array1 = new double[] {1, 2, 3, 4, 5};
double[] array2 = new double[] {10, 20};
double[] array3 = new double[3];
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array2.length; j++) {
double pos = array1[i];
double multiply = pos * array2[j];
array3[i]= pos * multiply;
}
}
System.out.print(Arrays.toString(array3));
}
I'm fairly certain the problem is with
array3[i] = pos * multiply;
Essentially what I'm trying to do is to store the multiplication in array3's first index. Then as the loop goes on store it into the second and then third index. I know I'm doing it wrong, but I'm not sure how to approach it, and a third for loop seems confusing and impractical (and I'm not even sure if it would work). Thank you!
You're not setting the output array to the correct length, it needs to be calculated based on the two input lengths (per your N - M + 1) and not hard coded to three. [although I note that with your updated question that three was actually the correct number]
That is also the number of outer iterations you must make. Your out-of-bounds exception is being caused by your iteration from 0 .. N - 1 without taking M into account.
Your are also failing to actually perform any summation. You should set array3[i] to zero as the first operation inside the first loop [*] and then add the multiplication term inside the inner loop.
static double[] array_product(double[] a, double[] b) {
int n = a.length - b.length + 1;
double[] result = new double[n];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < b.length; ++j) {
result[i] += a[i + j] * b[j];
}
}
return result;
}
public static void main(String[] args) {
double[] array1 = new double[] {1, 2, 3, 4};
double[] array2 = new double[] {10, 20};
double[] result = array_product(array1, array2);
System.out.print(Arrays.toString(result));
}
[*] although the Java language spec guarantees that a new array is set to 0.0, it's not a bad idea to do it explicitly both for clarity of the code and in case the code is ported to a language which does not make that guarantee.
I'm trying to increment the following sequence in a for loop (Java):
1, 4, 9, 16, 25 etc the difference increasing by two each time. I tried using 'i+=3 + i' but I know that's wrong since it doesn't take into account that the variable i changes along the sequence.
Any help? Thanks
You could have an increment of i+=k and change k inside the loop in order to change the increment.
int k=1;
for (int i=1;i<1000;i+=k) {
k+=2;
}
If your i is changing, the simple logic is, use another variable that is declared outside the scope of the loop. This will make sure that it is not recreated everytime the loop runs.
int num = 1;
for(int i=1; i<maxValue; num+=2,i+=num){
//Use the value of `i` here, it will be as you wanted.
}
The sequence is to start with j=1 and k=4 and then derive next values of the series n times. The formula as follow:
Initial loop (i=0):
j = 1, k = 4;
Loop (i > 0 less than n):
Repeat below n times:
temp = k;
k = k + (k - j + 2);
j = temp;
print value of j being the series;
I assume that you take n as input from user and then generate the series nth times. Let's look at the following code example
int n = 10;
for(int i = 0, temp = 0, j = 1, k = 4; i < n; i++, temp = k, k += (k-j+2), j = temp) {
System.out.println(j);
}
Assuming that user inputs n = 10, the loop initializes i = 0 and continues until i < n is satisfied. It initializes j = 1 and k = 4 and then execute the body of the loop (printing j) followed by backing up the value of k, calculating new value for k and replacing the old value of j. The output for n = 10 is as follow:
1
4
9
16
25
36
49
64
81
100
Read Series number from the user and generate series based on given number.
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int ans;
for(int i = 1; i <= n; i++){
ans = i * i;
System.out.println(ans);
}
Problem H (Longest Natural Successors):
Two consecutive integers are natural successors if the second is the successor of the first in the sequence of natural numbers (1 and 2 are natural successors). Write a program that reads a number N followed by N integers, and then prints the length of the longest sequence of consecutive natural successors.
Example:
Input 7 2 3 5 6 7 9 10 Output 3 this is my code so far and i have no idea why it does not work
import java.util.Scanner;
public class Conse {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
int[] array = new int[x];
for (int i = 0; i < array.length; i++) {
array[i] = scan.nextInt();
}
System.out.println(array(array));
}
public static int array(int[] array) {
int count = 0, temp = 0;
for (int i = 0; i < array.length; i++) {
count = 0;
for (int j = i, k = i + 1; j < array.length - 1; j++, k++) {
if (Math.abs(array[j] - array[k]) == 1) {
count++;
} else {
if (temp <= count) {
temp = count;
}
break;
}
}
}
return temp + 1;
}
}
Why two loops? What about
public static int array(final int[] array) {
int lastNo = -100;
int maxConsecutiveNumbers = 0;
int currentConsecutiveNumbers = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == lastNo + 1) {
currentConsecutiveNumbers++;
maxConsecutiveNumbers = Math.max(maxConsecutiveNumbers,
currentConsecutiveNumbers);
} else {
currentConsecutiveNumbers = 1;
}
lastNo = array[i];
}
return Math.max(maxConsecutiveNumbers, currentConsecutiveNumbers);
}
This seems to work:
public static int longestConsecutive(int[] array) {
int longest = 0;
// For each possible start
for (int i = 0; i < array.length; i++) {
// Count consecutive.
for (int j = i + 1; j < array.length; j++) {
// This one consecutive to last?
if (Math.abs(array[j] - array[j - 1]) == 1) {
// Is it longer?
if (j - i > longest) {
// Yup! Remember it.
longest = j - i;
}
} else {
// Start again.
break;
}
}
}
return longest + 1;
}
public void test() {
int[] a = new int[]{7, 2, 3, 5, 6, 7, 9, 10};
System.out.println("Longest: " + Arrays.toString(a) + "=" + longestConsecutive(a));
}
prints
Longest: [7, 2, 3, 5, 6, 7, 9, 10]=3
Since your question has "Problem H" associated with it, I'm assuming you are just learning. Simpler is always better, so it usually pays to break it down into "what has to be done" before starting on a particular road by writing code that approaches the problem with "how can this be done."
In this case, you may be over-complicating things with arrays. A number is a natural successor if it is one greater than the previous number. If this is true, increment the count of the current sequence. If not, we're starting a new sequence. If the current sequence length is greater than the maximum sequence length we've seen, set the max sequence length to the current sequence length. No arrays needed - you only need to compare two numbers (current and last numbers read).
For example:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int maxSequenceLen = 0; // longest sequence ever
int curSequenceLen = 0; // when starting new sequence, reset to 1 (count the reset #)
int last = 0;
for(int i = 0; i < N; i++) {
int cur = scan.nextInt();
if ((last+1) == cur){
++curSequenceLen;
}
else{
curSequenceLen = 1;
}
if (curSequenceLen > maxSequenceLen){
maxSequenceLen = curSequenceLen;
}
last = cur;
}
System.out.println(maxSequenceLen);
Caveat: I'm answering this on a computer that does not have my Java development environment on it, so the code is untested.
I'm not sure I understand this question correctly. The answer's written here assumes that the the natural successors occur contiguously. But if this is not the same then the solution here might not give the correct answer.
Suppose instead of [7 2 3 5 6 7 9 10] the input was [7 2 6 3 7 5 6 9 10] then the answer becomes 2 while the natural successor [5 6 7] is present in the array.
If the input is not sorted we'll have to use a different approach. Like using HashSet
Load the entire array into a HashSet which removes duplicates.
Pick the first value from the HashSet and assigned it to start and end and remove it from the set.
Now decrements start and check if it is present in the HashSet and continue till a particular value for start is not present int the HashSetwhile removing the value being searched from the set.
Do the same for end except that you will have to increase the value of end for each iteration.
We now have to continuous range from start to end present in the set and whose range is current_Max = end - start + 1
In each iteration we keep track of this current_Max to arrive at the longest natural successor for the entire array.
And since HashSet supports Add, Remove, Update in O(1) time. This algorithm will run in O(n) time, where n is the length of the input array.
The code for this approach in C# can be found here