I'm a beginner to java... if statements followed by else if statements are evaluated in order until one that evaluates to true is found, and I've seen many examples of this. But in this program, both statements (the if and the else if) are evaluated. Why?
public int centeredAverage(int[] nums) {
int[] nums = {1, 1, 5, 5, 10, 8, 7};
int sum = 0;
int centered = 0;
int min = nums[0];
int max = nums[0];
int i = 0;
for (i = 0; i < nums.length; i++){
if (nums[i] < min){
min = nums[i];
} else if (nums[i] > max){
max = nums[i];
}
sum += nums[i];
centered = ((sum-max-min)/(nums.length-2));
}
return centered;
}
Because they're in a loop that changes i and so changes nums[i] and so changes what if's are true.
Your passing in array of doubles by reference called nums and the defining an array of the same name in the method which seems odd. Also your start index for your for loop should be 1
Im guessing this is the same problem from codingbat, next time copy and paste the problem desciption for others!
public int centeredAverage(int[] nums) {
Arrays.sort(nums); //sorts the array smallest to biggest
int total = 0;
//nums is already sorted, so the smallest value is at spot 0
//and the biggest value is at the end.
for(int a = 1; a < nums.length - 1; a++){ //avoid the first and last numbers
total += nums[a];
}
return total / (nums.length - 2); //need ( ) so we can substract 2 first
//Another way could simply sum all the elements then subtract from that sum
//the biggest and smallest numbers in the array, then divide by nums.length- 2, it is a
//little more complex, but allows a for : each loop.
}
But for you, well since you are a beginner, restate your strategy (algorithm), find the smallest and biggest numbers in the array, subtract that out of the sum of all elements in the array then divide that number by nums.length - 2, since we are ignoring 2 numbers.
Working of If statement followed by else-if is fine here. We are getting expected result here. Both the statements if and else-if are not executed. Only that statement is executed which comes TRUE as per logic.
Here we can identify the working of the program using "System.out.println". Code and console output is given below...
int[] nums = {1, 1, 5, 5, 10, 8, 7};
int sum = 0;
int centered = 0;
int min = nums[0];
int max = nums[0];
int i = 0;
for (i = 0; i < nums.length; i++)
{
if (nums[i] > min)
{
min = nums[i];
System.out.println("inside first if: " + i);
// taking value of i in SOP to get the iteration value
}
else if (nums[i] > max)
{
max = nums[i];
}
sum += nums[i];
centered = ((sum-max-min)/(nums.length-2));
System.out.println("inside else if: " + i);
// taking value of i in SOP to get the iteration value
}
System.out.println("centered value "
+ " " + centered);
You can make a good usage of SOP in every program to get the execution order.
Related
Question :-
In the question we have to find the pivot index of the given array. And as per the given definition(given in the question) it is that point in the index such that if we calculate the sum of numbers on it's left and right they both comes out to be equal.
Example
Input: nums = [1,7,3,6,5,6]
Output: 3
Explanation:
The pivot index is 3.
Left sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11
Right sum = nums[4] + nums[5] = 5 + 6 = 11
My Approach and logic I tried
I calculate the total sum of array and then used a for loop to iterate from backwards in the array(from right to left) each time subtracting that element from total sum and comparing it to another loop which is calculating sum from right side such that when they get equal return that index element.
But I can't find the error
Code for the same
import java.util.*;
public class webs{
public static void main(String[] args){
int arr[] = {1, 7, 3, 6, 5, 6};
System.out.println(Calc(arr));
}
static int Calc(int arr[]){
int sum = 0;
int lsum = 0;
//this loop is for sum
for(int i =0; i < arr.length; i++){
sum += arr[i];
}
//this loop is for calculating sum from reverse
for(int j= arr.length - 1; j > 0; j--){
lsum += arr[j];
sum -= arr[j];
if(lsum == sum){
return arr[j];
}
else{
return -1;
}
}
return 0;
}
}
Please specify the error in this.
The for loop, in method Calc will only execute, at most, one iteration since it contains an if-else where both the if returns a value and the else returns a value. If you run your code with a debugger, you will discover that.
When I copied your code to my Eclipse, it warned me that the j-- part of the for loop is dead code. In other words it will never be executed because of the if-else statement in the loop body.
If lsum does not equal sum then you need to continue with the next loop iteration. Hence you need to remove the else.
Also, method Calc needs to return an index and not an element. Hence rather than
return arr[j];
you should
return j;
If the for loop terminates, that means that you did not find a pivot point and so the method should return -1 (negative one) and not zero. Hence the last line of method Calc should be
return -1;
Also, since you are iterating the array backwards, lsum should initially contain the sum of all the array elements and sum should be zero. In fact you either need to reverse sum and lsum or iterate the array forwards instead of backwards.
When iterating the array backwards, the terminating condition should be
j >= 0
and not
j > 0
because then you don't iterate the first element in the array.
Lastly, you need to adjust the value of sum after you test whether sum equals lsum.
Here is my rewrite of your code, containing the changes that I have described, above. I added print statements so you can [partially] see what is happening but as I said before, you need to learn how to debug your code.
static int Calc(int arr[]){
int sum = 0;
int lsum = 0;
//this loop is for sum
for(int i =0; i < arr.length; i++){
lsum += arr[i];
}
//this loop is for calculating sum from reverse
for(int j= arr.length - 1; j >= 0; j--){
lsum -= arr[j];
System.out.printf("%d. lsum = %d , sum = %d%n", j, lsum, sum);
if(lsum == sum){
System.out.println("Returning: " + j);
return j;
}
sum += arr[j];
}
System.out.println("Returning: -1");
return -1;
}
When I call method Calc with the sample array from your question, the following is printed:
5. lsum = 22 , sum = 0
4. lsum = 17 , sum = 6
3. lsum = 11 , sum = 11
Returning: 3
I've been learning Java for a while and I've run into a problem I can't figure out. I am currently learning arrays and how to iterate through them using loops. I generally understand how the if statement and the for loop work, but in this case I don't understand the principle of this loop in combination with if statements. This is the example I'm talking about:
class MinMax {
public static void main(String[] args) {
int nums[] = new int[10];
int min, max;
nums[0] = 99;
nums[1] = -10;
nums[2] = 100123;
nums[3] = 18;
nums[4] = -978;
nums[5] = 5623;
nums[6] = 463;
nums[7] = -9;
nums[8] = 287;
nums[9] = 49;
min = max = nums[0];
for (int i = 1; i < 10 ; i++){
if (nums[i] < min) min = nums[i];
if (nums[i] > max) max = nums[i];
}
System.out.println("Largest and smallest value: " + min + " " + max);
}
}
I want to focus on this part:
min = max = nums[0];
for (int i = 1; i < 10 ; i++){
if (nums[i] < min) min = nums[i];
if (nums[i] > max) max = nums[i];
The only thing I understand from this is how this for loop works, but the instruction min = max = nums[0]; is unclear to me. Why are we assigning these values to each other? Probably because I don't understand this instruction I also can't understand the principle of if statements in this example.
Can someone explain it to me step by step please?
min = max = nums[0];
is simply a short way of writing
min = nums[0];
max = nums[0];
because the "value" of an assignment is equal to the value being assigned. Which means that max = nums[0] evaluates to the same value as nums[0]. So the line of code could be rewritten like this to make the meaning slightly more obvious:
min = (max = nums[0]);
And why this is done is simple: the "current minimum" and "current maximum" is often set to the first value of a non-empty list before the loop, because we know that the true minimum is at most as much as the value of the first element and the true maximum is at least as much as the value of the first element.
Why do we initially set min and max to the first value in the array when trying to find the minimum and maximum value?
You don't have to set min and max to the first value. It is simply a way to find the values more efficiently since they must be one of those values so simply assign the first one. So you just assume that they are both min and max and the proceed to start with the next value in the array and alter min and max accordingly.
min = max = nums[0];
for (int i = 1; i < 10 ; i++){
if (nums[i] < min) min = nums[i];
if (nums[i] > max) max = nums[i];
}
You could also do it like this.
min = Integer.MAX_VALUE;
max = Integer.MIN_VALUE;
for (int v : nums) {
if (v < min) {
min = v;
}
if (v > max) {
max = v;
}
}
In the above case, you are iterating over all the values so you can use the enhanced for loop. I also wrote it using curly braces for a single statement which, imo, is a good practice to help avoiding careless mistakes and inadvertently introducing bugs.
It is the teacher's way of combining different aspects to see if you can understand all concepts that have already been taught.
It would be clearer to be more explicit and I would certainly iterate on all items instead of skipping the first item:
min = 0; // default min to 0
max = 0; // default max to 0
// iterate on ALL items in the array, starting at 0 till last element
for (int i = 0; i < nums.length ; i++) {
if (nums[i] < min) min = nums[i];
if (nums[i] > max) max = nums[i];
}
I was looking over some basic questions that might be asked in an interview. Using basic for loops (No hash maps etc)I want to sum up all the matching elements in an array.For example, 6 matching elements will result in (Matched: 6) and a total of 36 in the example below.An example of this could be rolling dice, and the score is the total of all the dice that match.
public static void main(String[] args) {
int arr[] = {6,6,6,6,6,6};
int matched = 1;
int value = 0;
int total = 0;
for(int i=0;i<arr.length;i++){
for(int j=(i+1);j<arr.length;j++){
if(ar[i] == ar[j]){
matched++;
value = ar[i];
break;
}
}
total = (matched * value);
} // End for loop
System.out.println("Matched:"+(matched)+"");
System.out.println("Total:"+total);
}
But, if the array was for example...
int arr[] = {6,1,1,6,6,6};
The output I get will be (Matched:5) and an a total of 30.Can could I store the matching pair of 1's and add them to the total using as little basic code as possible?
Interpreting the question as "provide the total number of values that occur more than once and their sum", and taking into account that nothing "fancy" (sic) such as a map can be used:
int[] array = {6, 1, 1, 6, 6, 6};
int sum = 0;
int matches = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (i != j && array[i] == array[j]) {
sum += array[i];
matches++;
break;
}
}
}
System.out.println(matches); // 6
System.out.println(sum); // 26
If you are allowed to use arrays - if not too fancy - then you could use 3 loops:
The first finds minimum and maximum elements
The second determines the occurrence of each item
The third calculates the totals
In Java this would look like this:
public static void main(String[] args) {
int[] array = {6, 3, 3, 6, 6, 6, 4, 4, 20};
int min = array[0];
int max = array[0];
// Find min max
for (int i : array) {
if (i < min) {
min = i;
}
if (i > max) {
max = i;
}
}
// Use array to sum up all elements
int[] holderArray = new int[max - min + 1];
for (int i : array) {
holderArray[i - min]++;
}
// Calculate occurrence and sums
for(int i = 0; i < holderArray.length; i++) {
if(holderArray[i] > 0) {
System.out.printf("number: %2d; count: %2d; sum: %2d%n", i + min, holderArray[i], (i + min) * holderArray[i]);
}
}
}
This prints out:
number: 3; count: 2; sum: 6
number: 4; count: 2; sum: 8
number: 6; count: 4; sum: 24
number: 20; count: 1; sum: 20
I don't completely understand your question, but based from what I understood, you want to get the sum of all matched numbers if its greater than 1? In that case there is a O(n) solution that you could use.
Create an empty Map then iterate over the array, and if the current number is not within the map add it to the map with value 1, if the current element is already existing in the map then just increment it's value (val++), at the end you will have a map and for each key (each distinct number) you will have the number of matched numbers from the array as the value. All you need to do is iterate over the pairs of key,val multiply each key*val then sum up the multiplied values and you get your correct total. And if you need just the number of matched, you can in another variable sum up just the vals.
So for lets say array [1,1,5,1,5,2,2,5,1], your map will something like:
{1:4, 2:2, 5:3},
and your totals:
total matches: 9
total: 23
I hope this helps!
Here is a code fragment I just wrote. This method takes in an array of integers and creates a map of each unique integer and it's count in the list. In the second part of the method, the HashMap object countOfNumbersMap is iterated and the sum of each element is printed.
private void findSumOfMatchingNumbers(int array[]) {
HashMap<Integer, Integer> countOfNumbersMap = new HashMap<>();
// Setting up the map of unique integers and it's count
for (int i = 0 ; i < array.length ; i++) {
if (countOfNumbersMap.containsKey(array[i])) {
int currentCount = countOfNumbersMap.get(array[i]);
countOfNumbersMap.put(array[i], currentCount + 1);
} else {
countOfNumbersMap.put(array[i], 1);
}
}
for (Integer integer : countOfNumbersMap.keySet()) {
int sum = countOfNumbersMap.get(integer) * integer;
System.out.println(String.format("Number = %d, Sum = %d", integer, sum));
}
}
The worst case runtime of the program is O(n).
If the range of your integers is limited, the easiest way to do this would be to create a histogram (i.e. create an array, where under index i you store the number of occurrences of the number i).
From that, it's easy to find elements that occur more than once, and sum them up. This solution has a complexity of O(n+k), where k is the range of your integers.
Another solution is to sort the array,then the matching numbers will be next to each other, and it's easy to count them. This has O(nlogn) complexity.
If these methods are not allowed, here is a solution in O(n^2) that only uses for loops:
Sum up the whole array
With a double loop, find all elements that are unique, subtract them from the sum, and count their number.
The remaining sum is the sum of all elements occurring more than once, and the count of unique elements subtracted from the length of the array gives the number of matching element.
I'm reading Cormen's "Introduction to Algorithms".
For the linear algorithm for Max Sum Subarray problem I came up with my own solution. Didn't check existing one (Kadena's) before implementing.
Now I'm testing it with different test scenarios and always have better results than Kadena's. I don't believe in such a luck, but can't find what have I missed. Could you take a look whether it is a working solution?
public void findMaxSubarray(Number[] numbers) {
int maxSum = Integer.MIN_VALUE;
int left = 0;
int right = numbers.length - 1;
int i = 0;
int j = i + 1;
int sum = numbers[i].intValue();
while (i < numbers.length) {
if (maxSum < sum) {
maxSum = sum;
left = i;
right = j - 1;
}
if (j >= numbers.length)
return;
sum = sum + numbers[j].intValue();
if (sum <= 0) {
// ignoring "first" negative numbers. shift i to first non-negative
while (numbers[j].intValue() <= 0) {
if (maxSum < numbers[j].intValue()) {
maxSum = numbers[j].intValue();
left = j;
right = j;
}
if (++j >= numbers.length)
return;
}
i = ++j;
sum = 0;
}
j++;
}
System.out.println(String.format("Max subarray is %d, [%d; %d]", maxSum, left, right));
}
Update
The idea of code is to keep in track only one subarray, and adding to its' tail numbers, when numbers are that low that sum becomes negative - set beginning of array after the tail.
Additionally negative items in the beginning are being ignored. head of subarray is just shifted forward.
Everytime sum appears to be maximum - maxSum and limits are updated.
shift i() --to first non negative number
from j = i+1 up to N.length
sum + N[j]
if sum <= 0
i = j+1
if N[i] < 0
shift i()
sum = 0
I think your algorithm is basically sound, but it has two bugs that I can see:
On the input 1 -2 10 3, it will skip over the 10 and output 3. I think you can fix this by changing i = ++j; to i = j;.
In 2 different places you return if j goes past the end, which will cause no output to be produced at all! (This will happen if, e.g., a long list of negative numbers appears at the end of the list.)
Also I don't expect it to be faster (or slower, for that matter) than Kadane's. Summing two numbers is a fast operation, as fast as copying one variable to another, which is what you are doing when you shift the start of the subarray.
I've been playing around a bit with the algorithms for getting the largest sum with no two adjacent elements in an array but I was thinking:
If we have an array with n elements and we want to find the largest sum so that 3 elements never touch. That's to say if we have the array a = [2, 5, 3, 7, 8, 1] we can pick 2 and 5 but not 2, 5 and 3 because then we have 3 in a row. The larget sum with these rules for this array would be: 22 (2 and 5, 7 and 8. 2+5+7+8=22)
I'm not sure how I would implement this, any ideas?
Edit:
I've only come so far as to think about what might be good to do:
Let's just stick to the same array:
int[] a = {2, 5, 3, 7, 8, 1};
int{} b = new int[n}; //an array to store results in
int n = a.length;
// base case
b[1] = a[1];
// go through each element:
for(int i = 1; i < n; i++)
{
/* find each possible way of going to the next element
use Math.max to take the "better" option to store in the array b*/
}
return b[n]; // return the last (biggest) element.
This is just a thought I got in my head, hasn't reached longer than this.
Algorithm for Maximum sum such that no two elements are adjacent:
Loop for all elements in arr[] and maintain two sums incl and excl where incl = Max sum including the previous element and excl = Max sum excluding the previous element.
Max sum excluding the current element will be max(incl, excl) and max sum including the current element will be excl + current element (Note that only excl is considered because elements cannot be adjacent).
At the end of the loop return max of incl and excl.
Implementation:
#include<stdio.h>
/*Function to return max sum such that no two elements
are adjacent */
int FindMaxSum(int arr[], int n)
{
int incl = arr[0];
int excl = 0;
int excl_new;
int i;
for (i = 1; i < n; i++)
{
/* current max excluding i */
excl_new = (incl > excl)? incl: excl;
/* current max including i */
incl = excl + arr[i];
excl = excl_new;
}
/* return max of incl and excl */
return ((incl > excl)? incl : excl);
}
/* Driver program to test above function */
int main()
{
int arr[] = {5, 5, 10, 100, 10, 5};
printf("%d \n", FindMaxSum(arr, 6));
getchar();
return 0;
}
Time Complexity: O(n)
Space Complexity: O(1)
Edit 1:
If you understand the above code, we can easily do this problem by maintaining the count of already adjacent numbers for previous position.
Here is a working implementation to the required question
//We could assume we store optimal result upto i in array sum
//but we need only sum[i-3] to sum[i-1] to calculate sum[i]
//so in this code, I have instead maintained 3 ints
//So that space complexity to O(1) remains
#include<stdio.h>
int max(int a,int b)
{
if(a>b)
return 1;
else
return 0;
}
/*Function to return max sum such that no three elements
are adjacent */
int FindMaxSum(int arr[], int n)
{
int a1 = arr[0]+arr[1];//equivalent to sum[i-1]
int a2 =arr[0];//equivalent to sum[i-2]
int a3 = 0;//equivalent to sum [i-3]
int count=2;
int crr = 0;//current maximum, equivalent to sum[i]
int i;
int temp;
for (i = 2; i < n; i++)
{
if(count==2)//two elements were consecutive for sum[i-1]
{
temp=max(a2+arr[i],a1);
if(temp==1)
{
crr= a2+arr[i];
count = 1;
}
else
{
crr=a1;
count = 0;
}
//below is the case if we sould have rejected arr[i-2]
// to include arr[i-1],arr[i]
if(crr<(a3+arr[i-1]+arr[i]))
{
count=2;
crr=a3+arr[i-1]+arr[i];
}
}
else//case when we have count<2, obviously add the number
{
crr=a1+arr[i];
count++;
}
a3=a2;
a2=a1;
a1=crr;
}
return crr;
}
/* Driver program to test above function */
int main()
{
int arr[] = {2, 5, 3, 7, 8, 1};
printf("%d \n", FindMaxSum(arr, 6));
return 0;
}
Time Complexity: O(n)
Space Complexity: O(1)
adi's solution can be easily generalized to allow up to n adjacent elements to be included in the sum. The trick is to maintain an array of n + 1 elements, where the k-th element in the array (0 ≤ k ≤ n) gives the maximum sum assuming that the k previous inputs are included in the sum and the k+1-th isn't:
/**
* Find maximum sum of elements in the input array, with at most n adjacent
* elements included in the sum.
*/
public static int maxSum (int input[], int n) {
int sums[] = new int[n+1]; // new int[] fills the array with zeros
int max = 0;
for (int x: input) {
int newMax = max;
// update sums[k] for k > 0 by adding x to the old sums[k-1]
// (loop from top down to avoid overwriting sums[k-1] too soon)
for (int k = n; k > 0; k--) {
sums[k] = sums[k-1] + x;
if (sums[k] > newMax) newMax = sums[k];
}
sums[0] = max; // update sums[0] to best sum possible if x is excluded
max = newMax; // update maximum sum possible so far
}
return max;
}
Like adi's solution, this one also runs in linear time (to be exact, O(mn), where m is the length of the input and n is the maximum number of adjacent elements allowed in the sum) and uses a constant amount of memory independent of the input length (O(n)). In fact, it could even be easily modified to process input streams whose length is not known in advance.
I would imagine putting the array into a binary tree in that order. That way you can keep track of which element is next to each other. Then just simply do an if (node is not directly linked to each other) to sum the nodes which are not next to each other. You can potentially do it with recursion and return the maximum number, makes things easier to code. Hope it helps.
For a set with n entries, there are 2^n ways to partition it. So to generate all possible sets, just loop from 0:2^n-1 and pick the elements from the array with those entries set to 1 (bear with me; I'm getting to your question):
max = 0;
for (i = 0; i < 1<<n; ++i) {
sum = 0;
for (j = 0; j < n; ++j) {
if (i & (1<<j)) { sum += array[j]; }
}
if (sum > max) { /* store max and store i */ }
}
This will find the maximum way to sum the entries of an array. Now, the issue you want is that you don't want to allow all values of i - specifically those that contain 3 consecutive 1's. This can be done by testing if the number 7 (b111) is available at any bit-shift:
for (i = 0; i < 1<<n; ++i) {
for (j = 0; j < n-2; ++j) {
if ((i & (7 << j)) == (7 << j)) { /* skip this i */ }
}
...