Running several iterations in a while loop - java

I am trying to solve a problem of finding the smallest and second smallest element in an array.
I am thinking of putting two pointers on the 0th index of the array. Both the pointers move from left to right traversing the entire array. First pointer ptr1 determines the min element while the second pointer intends to determine the second min element. The first pointer works ok but the second pointer doesn't traverse. While loop exits only after 1 iteration of the second pointer.
Is it possible to have n pointers in a while loop & make them traverse
from left to right turn by turn?
Or I am doing something wrong.
Below is the code
int arr[] = {12,13,1,10,34,1};
int ptr1 = 0;
int ptr2 =0;
int min = Integer.MAX_VALUE;
int minSec = Integer.MAX_VALUE;
int arrLen=arr.length-1;
while(ptr1<arrLen && ptr2<arrLen){
if(arr[ptr1]<min){ // this if works great finds the min element
min=arr[ptr1];
ptr1++;
}else{
ptr1++;
}
//flow enters once & exits the while loop
if(ptr1==arrLen && arr[ptr2]<minSec && arr[ptr2]>min){
minSec=arr[ptr2];
ptr2++;
}else if(ptr1==arrLen){
ptr2++;
}
}
System.out.println("min: " + min + " second min: "+ minSec)
output: min: 1 second min: 12
the correct output should be min: 1 second min: 10
I am able to solve the problem with another approach, code below. I just need to know about the while loop approach.
for (int i = 0; i <= arrLen ; i ++)
{
/* If current element is smaller than first
then update both first and second */
if (arr[i] < min)
{
minSec = min;
min = arr[i];
}
/* If arr[i] is in between first and second
then update second */
else if (arr[i] < minSec && arr[i] != min)
minSec = arr[i];
}

Because ptr2 value is 0 until loop reach the end
if(ptr1==arrLen && arr[ptr2]<minSec && arr[ptr2]>min){
minSec=arr[ptr2];
ptr2++;
}
and enter into the if condition only ptr1==arrLen then you select the minSec value as minSec=arr[ptr2]. No point of putting this condition here.
So second if condition will be like
if(arr[ptr2]<minSec && arr[ptr2]>min){
minSec=arr[ptr2];
ptr2++;
}else{
ptr2++;
}

Your problem is that the first if statement still works even if you found the smallest number. So all over traversed elements are either greater as or equal to the smallest number. That means pointer 1 is incremented every "while step". In your second if statement you check if pointer 1 is equal to array length but this case is present in only one "while step".
PS: Just let java sort your array. The work is already done for you ;)

You do not need two pointers
int arr[] = {12,13,1,10,34,1};
final int arrLen=arr.length;
int min = Integer.MAX_VALUE;
int minSec = Integer.MAX_VALUE;
for (int e=0; e<arrLen; e++) {
final int v = arr[e];
if (v<minSec && v>min)
minSec = v;
if (v<min && v<minSec)
min = v;
}
if (min>minSec)
min = minSec;

The problem is in this while(ptr1<arrLen && ptr2<arrLen) statement coupled with moving the second pointer only when ptr1 is at length.
What happens is ptr1 is at arrLen so the second pointer iterates once, but because you use an && when ptr1<arrLen is evalued to be false the entire loop exits. Using an or will not fix this because you have other problems in the code that will cause an IndexOutOfBoundsError.

Related

Why won`t this simple function output anything if I don`t use a break statement?

Function here is , implemented to find the largest number in an array .. if I don't put a break statement after while , it won't print out anything . I need someone to explain me how this code works .
What I was thinking is that ,
1- we go into first loop , and then the second loop..
2- we have the first and second elements compared in the while loop .
3- if condition is true , int largest is set to the large value..
4- and then we go back to the outer for loop again .
Isn't this true ? aren't we going back to the outer for loop after while statement is issued once ? If I don't put a break , while condition is true , the program won't come out of the loop , is that so ?
I`m testing the code in main , by calling this function and passing in an integer array . I forgot to mention this before . Sorry .
Thank you .
public int returnMax(int[] nums) {
int largest = 0;
for (int i = 0; i < nums.length; i++) {
for (int j = 1; j < nums.length; j++) {
while (nums[j] > nums[i]) {
largest = nums[j];
break;
}
}
}
return largest;
}
if nums[j] is larger than nums[i] it goes into your while loop.
In your while loop you never change any variable except for largest. Largest is never used except for returning a value. This causes an infinite loop because the next iteration your while expression is the still the same.
The program can't leave the while statement, because the condition is never changes and is always true (once it's true). You should replace the while with an if.
if (nums[j] > nums[i]) {
largest = nums[j];
System.out.println(largest);
}
Also you out commented System.out.println(largest);, so it will never be called
The first time your code gets to the while loop, j = 1 and i = 0, which means that j is greater than i. These numbers don't change inside this loop. Thus, the loop will never end and the code won't proceed.
You don't need 3 loops for this simple operation. Try the below.
public static int returnMax(int[] nums) {
int largest = nums[0];
for (int i = 1; i < nums.length; i++) {
if (largest < nums[i]) {
largest = nums[i];
}
}
return largest;
}
Kind Regards

Algorithm to check to output largest value in array or display if empty

I am trying to practice algorithms before i start my undergrad in computer science and i am struggling really bad to write algorithms. I understand them once i've been taught them and break them down but when I am trying to do my own, it fails miserable. I am trying a exercise question in a programming textbook, where i have an array and i have to output the largest value or if the array is empty, i have to display -1.
This was the best i can come up with but it still falls way short. Any pointers on what exactly I'm doing wrong.
for(i = 0;i < array.length-1;i++)
if(array[i] == 0){
empty = true;
n = -1;
System.out.println(n);
}else{
largest = array[0];
if(array[i] > largest){
largest = array[i];
System.out.println(array[i]);
}
}
I see that -1 displayed 10 times but i have found no solution for this and if the array is full, it provides me one then one value.
If you're struggling with algorithms, it helps sometimes not to look at them as algorithms but real-world problems.
Say you are in a shop buying cheese and your task is to pick a pack of cheese which has the latest expiration date. Now imagine the situation: standing at the cheese section looking for the best yummy cheese...
First, you look if there is any. If not, return empty handed.
If there are some packs, go through them looking for the best. You've got probably only one hand free, holding the basket in the other one, so...
Initially, pick the first cheese
Then go through the packs one by one. If you find cheese better than you have in your hand, put the one you're holding down and take the better one.
Now, let's put this to a programing language:
int[] cheeseExpirations = new int[] { ... };
if (cheeseExpirations.length == 0) {
System.out.println(-1); // no cheese :(
} else {
int myCheese = cheeseExpirations[0]; // take the first pack; better a sparrow in the hand than a pigeon on the roof...
for (int i = 0; i < cheeseExpirations.length; i++) { // idiomatic array iteration
int currentCheese = cheeseExpirations[i];
if (currentCheese > myCheese ) { // found a better one
myCheese = currentCheese; // just take it
}
}
System.out.println(bestCheese);
}
Is it clearer now? Like Richard Feynman said, using your imagination and examples is important:
I had a scheme, which I still use today when somebody is explaining something that I'm trying to understand: I keep making up examples.
For instance, the mathematicians would come in with a terrific theorem, and they're all excited. As they're telling me the conditions of the theorem, I construct something which fits all the conditions. You know, you have a set (one ball)-- disjoint (two balls). Then the balls turn colors, grow hairs, or whatever, in my head as they put more conditions on.
Finally they state the theorem, which is some dumb thing about the ball which isn't true for my hairy green ball thing, so I say "False!" [and] point out my counterexample.
You are checking the length of the array in each loop. This means it won't be checked unless the array has some object, which is just what we don't want.
But, in fact, you are not checking the array length:
if(array[i] == 0) tests if the item of array at index i is 0. To test the length of the array, you have to do if (array.length > 0). Remember you have to do this before the for loop, so it would be something like this:
if(array[i] == 0){
empty = true;
n = -1;
System.out.println(n);
}
for(i = 0;i < array.length-1;i++)
largest = array[0];
if(array[i] > largest){
largest = array[i];
System.out.println(array[i]);
}
}
But, in each loop you are reassigning largest to the first array element, which breaks the algorithm. So you must move that line before the for loop.
if(array[i] == 0){
empty = true;
n = -1;
System.out.println(n);
}
largest = array[0];
for(i = 0;i < array.length-1;i++)
if(array[i] > largest){
largest = array[i];
System.out.println(array[i]);
}
}
A few things:
if(array[i] == 0)
does not check if the array is empty, it checks if the value stored at index i of the array is equal to zero. You probably want something like:
if(array != null && array.length == 0) {
return -1;
}
before the for loop executes.
The rest of your code looks close. The print statement inside of the else clause is unnecessary. You just need to return the value of largest after the for loop executes.
This code is rather strange in general. Why do you consider an array empty as soon as you reach an element that is 0? And why do you continue search, if the array is empty? Last but not least: why do you ignore the last element in the array?
There are plenty of solutions for this that are a lot simpler:
Without any java-api:
if(array.length == 0)
return -1;
int max = Integer.MIN_VALUE;
for(int i = 0 ; i < array.length ; i++)
if(max < array[i])
max = array[i];
return max;
A lazy solution using Arrays.sort() (not exactly elegant, but short)
Arrays.sort(array);
return array[array.length - 1];
Using java8:
return Arrays.stream(array).min((a , b) -> new Integer(a).compareTo(b)).orElse(-1);
Lets take a look at your code
for(i = 0;i < array.length-1;i++)//You will never reach the last number
if(array[i] == 0){//Here you check if the first item equals zero. Gives error if there is no first item.
empty = true;//why do you need this, you never use it.
n = -1;
System.out.println(n);
}else{
largest = array[0];//Why setting largest, do dont know if it is actually bigger
if(array[i] > largest){
largest = array[i];
System.out.println(array[i]);
}
}
Improved version:
largest = -1;//set it by default
for(i = 0;i < array.length;i++)//if length is 10 iMax = 9, which is the tenth item.
if(array[i]>largest){//if larger set the new value
largest = array[i];
}
}
System.out.println(largest);//print the largest number.
if(array.length == 0){
empty = true;
n = -1;
System.out.println(n);
}else{
largest = array[0];
for(i = 1; i < array.length; i++)
if(array[i] > largest){
largest = array[i];
}
System.out.println(largest);
}
First what i did is check if the array is empty. If it is then skip the else and output the -1. If the array is not empty set the largest to the first element and then loop through all other elements. Noticed I changed i = 1 because element 0 is already the largest. Also I removed the -1 to the array length because i will stop 1 before the length (which will be the last index of final element). Finally I moved the print of the largest value outside of the if statement and for loop so that it only gets printed once at the very end.
First check if the array is empty
if(array != null && array.length == 0) {
If it is print -1
System.out.println(-1 + "");
}
Now you are ready to go through the array. But before you do create a variable that will keep track of the largest value. I set it to the first element in the array (since we know that it has at least one element since we already determined that it isn't empty)
else {
int largest = array[0];
Then, loop through the array
for(i = 0;i < array.length-1;i++) {
Get every element one at a time using i to access the ith element
int current = array[i];
Then compare it to the largest. If it's greater than the largest so far, save it as the largest.
if (current>largest) {
current = largest;
}
Keep doing that until finished looping through the array
}
Then print out the largest
System.out.println(largest + "");
}

Error when testing for the max value of a table?

I have an error when I try to run a loop that will test the max value of a table.
The table is tabl with a length of c.
int a=0;
int b=0;
while (a<=c) {
int d = tabl[a];
int e = tabl[a+1];
if(d < e)
b = e;
else
b = d;
a++;
}
It's pretty easy, it starts with comparing tabl[0] and tabl[1], and saves the bigger one, and then keeps going until a = c which is the length of the table and then finishes the loop saving the biggest value of the table in b.
But when I run this I get an java.lang.ArrayIndexOutOfBoundsException error code, can anyone help please? thanks!
When you reach a = c - 1 in your loop, your code is looking for the value of tabl[c-1]and tabl[c]. However, since your table is of length c, this causes an java.lang.ArrayIndexOutOfBoundsException. Beware that in Java, arrays are 0-indexed, that is to say, the first element is at index 0 and the last at index (length - 1).
You could write something like that, using a for-each construct :
int max = 0;
for (int element : tabl) {
if (element > max) {
max = element;
}
}
or a simple for loop
int max = 0;
for (int i = 0; i < tabl.length; i++) {
int element = tabl[i];
if (element > max) {
max = element;
}
}
The problem is you are going one past the end of the array. Arrays are zero indexed, so the item at c is going to be IndexOutOfBounds.
Also because you are accessing a + 1, this means that on the loop when a = c - 2, a + 1 will access the last element of the array.
Try:
int a=0;
int b=0;
while (a < c - 1){
int d = tabl[a];
int e = tabl[a+1];
if(d<e) { b=e;} else { b=d; }
a++;
}
NB: The change is to say a < c - 1 rather than a <= c to ensure that a is never = c when indexing into the array.
You're going out of the bounds of your array when trying to reach tabl[a+1] when a equals c
Your whole algorithm doesn't really make sense: you don't have to compare the current index's value to the next one to find out the max of the array, but rather the current value to the previous maximum value you found out.
A common way to find the maximum value of an array is that one:
int max = table[0];
for(int i = 1; i < c; i++)
if(table[i] > max)
max = table[i];
This way, max will contain the highest value of the array (though the code will throw an Exception if the table is empty).
Please, indent your code better, and use more meaningful variable names (people understand max better than b)

Sub-Array Max Sum

I'm looking over an assignment that I finished a few days ago and realized I'm not supposed to use constants. The assignment is the well-known "find the largest sum of a sub-array of integers both positive and negative recursively using a divide and conquer approach" problem. My algorithm works, but a part of it uses a constant in order to figure out the largest sum of sub-arrays that include the middle of the array.
Here's the relevant code:
lfSum = Integer.MIN_VALUE;
sum = 0;
// Sum from left to mid
for (int i = mid; i >= LF; i--) {
sum += array[i];
if (sum > lfSum) {
lfSum = sum;
if (lfSum > lfMax) {
lfMax = lfSum;
}
}
}
rtSum = Integer.MIN_VALUE;
sum = 0;
// Sum from mid to right
for (int j = mid+1; j <= RT; j++) {
sum += array[j];
if (sum > rtSum) {
rtSum = sum;
if (rtSum > rtMax) {
rtMax = rtSum;
}
}
}
// Largest sum spanning whole array
midMax = lfSum + rtSum; // midMax = leftMid + midRight;
What this does is it loops through each half of the entire array and checks to see if the sum is larger than the smallest integer possible in case the entire array is negative. If it is, it sets that side's max sum to sum's value. If that value is larger than what one of the recursive calls returned (lfMax or rtMax), set the respective side's recursive value to it.
Like I said earlier, this works perfectly well, but I'm not supposed to be using "Integer.MIN_VALUE". Is there another way around this? Obviously I could initialize lfSum/rtSum to the numerical value of Integer.MIN_VALUE, but I'd like to know if there are any other options.
I've tried removing rtSum/lfSum and just comparing sum to the recursive values, and initializing lfSum/rtSum to 0, but both did not work correctly. Thanks for taking the time to read this!
You can initialize lfSum as null:
Integer lfSum = null;
And modify the if condition like this:
if (lfSum == null || (lfSum != null && sum > lfSum.intValue())) {
lfSum = sum;
if (lfSum > lfMax) {
lfMax = lfSum;
}
}
Similar strategy applies to rtSum.

Add 0 and 1 is alternate array cells in java

I have any array with value 0,0,0,0,0,0,0,0,1,1,1
Now my required output should be like each zero will be in odd index and 1 will be in even and if 0 left after that it should be copied after 1 and viceversa.
Means the output will be 0,1,0,1,0,1,0,0,0,0,0....
But the above operation must be done in a single pass of array
So I created an array with same size ,
then I started traversing the main array and one's 0 is encoutered I put a counter to set the value in odd index and viceversa
In the end when the index crossed the length of new array created , I started adding the 0 into the new cell in even mode from backward.
What can be the other better solution.
You don't need an extra array for this. You can do it in-place. Just keep two pointers, one which stops after every odd step and one which finds the 1s. When the second pointer encounters a 1 just swap it with the first pointer, increment the first pointer. Do this for the length of the array.
Lets try inplace in one pass
Keep one pointer at the beginning of the array and one at the end of the array.
I am assuming that number of zeroes is greater than number of ones
int begin = 0, end = length - 1;
while (begin < end){
if (A[begin] == 0 && A[end] == 1){
if (begin % 2 != 0){
int tmp = A[end];
A[end] = A[begin];
A[begin] = temp;
end--;
}
begin++;
}
else
break;
}
Remember, above solution won't work for cases when number of ones is greater than number of zeroes
#include<stdio.h>
main()
{
int arr[]={1,0,0,1,0,1,1,1,0,1};
int n=10;
int odd,one,tmp;
odd=one=0;
while(true)
{
while(odd<n && arr[odd])
odd+=2;
while(one<n && (((one<=odd)&&(one%2==0)) || !arr[one]))
one++;
if(odd<n && one<n)
{
arr[one]=arr[one]^arr[odd];
arr[odd]=arr[one]^arr[odd];
arr[one]=arr[one]^arr[odd];
}
else
break;
}
for(int i=0;i<n;i++)
printf("%d ",arr[i]);
}

Categories