4

I am trying to create a method which returns an int - the value of the largest integer in the sent array. The way I want this method to work, is to check the first and the last element of the array in a for-loop, and work their way to the middle. So i = first integer, k = last integer. When i = 0, k = n-1 (indexes), when i = 1, k = n-2 if you catch my drift. In every loop it needs to check if a[i]>a[k]. Then they switch places. Then I know that the largest number is in the leading half of the array, and then I want it to check that half, so ultimately the largest int is at index 0.

I tried like this:

public static int maxOfArray(int[] a)
{
    int length = a.length;

    if(length<1)
        throw new NoSuchElementException("Not at least one integer in array");

    while (length > 1)
    {
        int k = length;

        for(int i = 0; i < length/2; i++)
        {
            k--;

            if(a[i]<a[k])
            {
                int j = a[i];
                a[i] = a[k];
                a[k] = j;
            }
        }
        length /=2;
    }
    return a[0];
}

..but I don't really get it.. I'm having a hard time "picturing" what's happening here.. But it's not always working.. (though sometimes).

EDIT Also: The array {6,15,2,5,8,14,10,16,11,17,13,7,1,18,3,4,9,12}; will spit out 17 as the largest number. I realize I have to fix the odd-length bug, but I would like to solve this even-length array first..

Chimera
  • 5,884
  • 7
  • 49
  • 81
Sti
  • 8,275
  • 9
  • 62
  • 124
  • 11
    Can you elaborate on the reason why you are trying such a complex method where a linear scan does the trick? Is it HW? example from a book? interview? It might help us give you better focused answers. – amit Sep 11 '12 at 11:04
  • "[...] Then they switch places" - looks like the OP actually wants to *sort* the array in some bubble sort style. Please add the _quiz_ tag! – f_puras Sep 11 '12 at 11:08
  • @amit Well, yes. This is to a little school project. I can see many answers with other methods, but the request is to compare the first and the last, then switch places if the last is bigger - then continue towards the middle of the array. The biggest is not to be placed in index 0, just placed on the "left" side of the array, thus placing it on index 0 when the time comes.. – Sti Sep 11 '12 at 11:16
  • 1
    The largest would not always be in the leading half. Say you array is [1, 5, 3], then you first compare (1 > 3), then (5 > 5) and lastly (3 > 1). You now have [3, 5, 1] and you divide the length by 2 which gives you the array [3]. You lost the 5. Also, if you switch the comparison you don't have to scan the whole array, only half. Now you first move large numbers to the upper half, then back to the lower. – Roger Lindsjö Sep 11 '12 at 11:24
  • For easier debugging, output the array after each switch and each loop . – Roger Lindsjö Sep 11 '12 at 11:25
  • 2
    So `for(int i = 0; i < length; i++)` is wrong, you only need to iterate over the first half of the array: `for(int i = 0; i < length / 2; i++)`. Also check what happens if the array size is odd. – f_puras Sep 11 '12 at 11:26
  • @f_puras: This is an answer. post it (or with your premission I can add it to my answer). I believe this with addition to the odd-length issue I mentioned is pretty much the issue, unless I am missing something else :| – amit Sep 11 '12 at 11:38
  • @amit Please feel free to update your answer! It's all [CC BY-SA](http://stackoverflow.com/faq#editing) ;-) – f_puras Sep 11 '12 at 11:50

9 Answers9

7

A bug is when encountering length is odd.

In these cases, you "miss" the middle element.

Example: for input int[] arr = { 8, 1, 5, 4, 9, 4, 3, 7, 2 }; - the element 9 will be compared and checked against itself, but then you reduce the size of length, you exclude 9 from the array you are going to iterate next.

I believe it can be solved by reducing the problem to ceil(length/2) instead of length/2 (and handling special case of length==1)

The other issue as was mentioned in comments is: you need to iterate up to length/2 rather then up to length, otherwise you are overriding yourself.

Lastly - the sign is wrong.

if(a[i]>a[k])

should be

if(a[i]<a[k])

Remember - you are trying to swap the elements if the first is smaller the the second in order to push the larger elements to the head of your array.

amit
  • 175,853
  • 27
  • 231
  • 333
  • Thank you, I now realize that an odd-length would damage this, however, I am testing my method with different arrays, some of them working, and the one (so far) that failed was an even-length array = {6,15,2,5,8,14,10,16,11,17,13,7,1,18,3,4,9,12} setting 17 at the index 0, even though 18 is larger. – Sti Sep 11 '12 at 11:32
  • 1
    @StianF: I believe f_puras's is also correct in his comment. You should iterate up to `length/2` in addition to what I mentioned here. – amit Sep 11 '12 at 11:36
  • 1
    @StianF: Here you go - the if condition sign is also wrong. I editted the answer to reflect it. – amit Sep 11 '12 at 11:56
  • Yes, I noticed that, forgot to change the question. That however, did not solve my problem.. I will update my question. – Sti Sep 11 '12 at 11:58
  • That is weird.. When I try the array {6,15,2,5,8,14,10,16,11,17,13,7,1,18,3,4,9,12};, and print it out after the method I get: 17,16,10,14,18,5,4,15,12,11,13,7,1,8,3,2,9,6.. – Sti Sep 11 '12 at 12:06
  • 1
    @StianF: Did you fix the odd array length issue? It may occure even for even length array, because you constantly divide the problem (For example length=18, the second iteration will have length=9) – amit Sep 11 '12 at 12:07
  • 1
    You can fix it by: `length = (int)Math.ceil((double)length/2);` for the modification of `length`. – amit Sep 11 '12 at 12:09
  • Thank you! That fixed it. Beating myself up for not realizing that an even array would possibly eventually become an odd array when dividing it. – Sti Sep 11 '12 at 12:27
3

but I don't really get it.. I'm having a hard time "picturing" what's happening here.. But it's not always working.. (though sometimes).

In that case you should use a debugger to step through the code to get a picture of what each line of code does.


What I would do is:

public static int maxOfArray(int[] a) {
    int max = a[0];
    for (int i : a)
        if (max < i)
            max = i;
    return max;
}

public static int findMaxTheHardWay(int[] array) {
    for (int length = array.length; length > 1; length = (length + 1) / 2) {
        for (int i = 0; i < length / 2; i++) {
            if (array[i] < array[length - i - 1])
                array[i] = array[length - i - 1]; // don't need to swap.
        }
    }
    return array[0];
}

public static void main(String... args) {
    Random rand = new Random(1);
    for (int i = 1; i <= 1000; i++) {
        int[] a = new int[i];
        for (int j = 0; j < i; j++) a[j] = rand.nextInt();
        int max = maxOfArray(a);
        int max2 = findMaxTheHardWay(a);
        if (max != max2)
            throw new AssertionError(i + ": " + max + " != " + max2);
    }
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
3

This is rather a crazy way to solve the problem, but I'll play along.

The problem is in the inner loop.

  • You start out with i = 0 and k = length - 1.
  • If a[i] > a[k] you swap them.
  • ...
  • You end up with k = 0 and i = length - 1
  • If a[i] > a[k] you swap them.

If you look at that carefully you will notice that if we swapped the elements in the first swap, we will also swap them in the last swap; i.e. we will UNDO the effects of the first swap. And the same applies pair-wise through the entire array slice.

See?

What you need to do is to stop the inner loop half way ... and then take account of the case where length is odd.


By the way, the reason I called this "rather crazy", because the obvious and simple way is much faster: O(N) versus O(NlogN)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thanks! However, theres still something wrong.. May be something else from my stupid code, but I have now stopped the loop half way `i – Sti Sep 11 '12 at 11:46
  • Yea, if you are shuffling large numbers to the left you gave got the sign of your comparison the wrong way around. – Stephen C Sep 11 '12 at 12:02
  • If you still can't figure out what the problem in your code is, try adding traceprints or running it using a debugger. – Stephen C Sep 11 '12 at 12:37
  • We figured it out. amit was right. The problem was that I didn't take account of the odd-length arrays. I stupidly chose not to do it, because I got the wrong output when using an even-length array, but as the length of that array was `18`, it would have an odd-length `9` in the second turn. Btw, how do I figure out the 0(NlogN) stuff? And what is it called in english? – Sti Sep 11 '12 at 12:59
  • 1
    @Stainf - In english, it is called "complexity analysis", and that is "Big O" or "Landau" notation. Wait until they teach it to you, or look it up on Wikipedia :-) – Stephen C Sep 11 '12 at 23:52
1
int a[] = {1,7,3};   
List<Integer> list = Arrays.asList(a);  
Integer largest = Collections.max(list);

This will give you Largest number in Array.

Azuu
  • 836
  • 2
  • 16
  • 32
1

Here is a solution that fits the specifications that you want (unlike many other here, humm, humm):

    final Integer[] input = {1, 2, 6, 32, 4, 44 ,12, 42, 3, 7, 17, 22, 57, 23, 102, 103 };

    int half = (input.length / 2);
    int mod = input.length % 2;
    while (half >= 0) {
        for (int i = 0, j = (half * 2) + mod - 1; i <= half && j >= half; i++, j--) {
            if (input[i] < input[j]) {
                final int tmp = input[i];
                input[i] = input[j];
                input[j] = tmp;
            }
        }
        if (half == 0) break;
        half = half / 2;
        mod = half % 2;
    }
    //Here, input[0] = the biggest number in the original input.

Edit: Added mod, so it works if the last element is the largest..

Tobb
  • 11,850
  • 6
  • 52
  • 77
1

I think your code is working, you just have to ceil the length / 2 in case of odd array but my tests return proper result:

package org.devince.largestinteger;

import java.util.NoSuchElementException;

public class LargestInteger {
    final static int[] input = {1, 2, 6, 32, 4, 44 ,12, 42, 3, 7, 17, 22, 57, 23, 102, 103 };
//  final static int[] input = { 8, 1, 5, 4, 9, 4, 3, 7, 2 };
//  final static int[] input = {1,3,7};

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(String.valueOf(maxOfArray(input)));
    }

    public static int maxOfArray(int[] a)
    {
        int length = a.length;

        if(length<1)
            throw new NoSuchElementException("Not at least one integer in array");

        while (length > 1)
        {
            int k = length;

            for(int i = 0; i < length; i++)
            {
                k--;

                if(a[i]>a[k])
                {
                    int j = a[i];
                    a[i] = a[k];
                    a[k] = j;
                }
            }
            length = (int) Math.ceil(length / 2f);
        }
        return a[0];
    }

}
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
Vince
  • 1,036
  • 1
  • 10
  • 17
0

Why not just store the first value of the array to a variable max.

After that just loop through the array starting from second position till the last , in the loop just check if the current value is greater than max or not.If it is greater just assign max that value.

Return max and you have the largest number.

public int FindLargest()
{
    int[] num = { 1, 2, 5, 12, 13, 56, 16, 4 };
    int max = num[0];

    for (int i = 1; i <num.length; i++)
    {
        if (num[i] > max)
        {
            max = num[i];
        }
    }

    return max;
}
Baz
  • 36,440
  • 11
  • 68
  • 94
Priyank Patel
  • 6,898
  • 11
  • 58
  • 88
  • (1) it does not answer the OPs question. `The way I want this method to work, is to....` (2) it is not java (`Length` field). C# I suspect – amit Sep 11 '12 at 11:14
  • @amit Ok it doesnot answer OPs question but provides an alternative that works.Why not? – Priyank Patel Sep 11 '12 at 11:16
  • @amit `num.length` is perfectly right, check [Java Arrays](http://stackoverflow.com/questions/5950155) for an SO example. – f_puras Sep 11 '12 at 11:20
  • @f_puras It was `num.Length` when this comment was added ;) – Baz Sep 11 '12 at 11:20
  • @freebird `num.length` is correct, `num.Length` is incorrect. Why change it back? – Baz Sep 11 '12 at 11:24
0

As the same u can approach like also,

int length = a.length;
   while (length > 1)
    {
        int k = length;
        for(int i = 0; i < length; i++)
        { 
            for(int y = k-1; y >= i; y--) 
            {         
                if(a[i]<a[y])
                {
                    int j = a[i];
                    a[i] = a[y];
                    a[y] = j;               
                }
            }       
        }
        length /=2;
    }
Sivaraman
  • 61
  • 7
0
         final int validSampleRates[] = new int[]{
                    5644800, 2822400, 352800, 192000, 176400, 96000,
                    88200, 50400, 50000, 4800,47250, 44100, 44056, 37800, 32000, 22050, 16000, 11025, 4800, 8000};
          ArrayList <Integer> YourArray = new ArrayList <Integer> ():
 for (int smaple : validSampleRates){

                    YourArray.add(smaple);
                }
            Integer largest = Collections.max(YourArray);
            System.out.println("Largest   " + String.valueOf(largest));

The best way is to use Array that extends List Collection as ArrayList

Fatih Şennik
  • 73
  • 1
  • 9