# das kleinste Element von den Elementen des Array ,die größer gleich den Durchschnitt des  Array  ist



## bradig (24. Mrz 2016)

Mein Problem:beim Testen habe ich festgestellt,dass das Programm nicht immer das richtige Ergebnis liefert.(mit dem Array `{2,4,4,6,8,12,13}` bekomme ich 13  statt 8  )
Bitte um Hilfe.
die Aufgabe:
Gibt die kleinste Zahl des Arrays zurück, die größer oder gleich dem Durchschnitt der Werte des Arrays ist.
Beispiel:
Gegeben das Array `{0,1,2,3,4}`
Der Durchschnitt der Arrayelemente ist `10/5=2`
Die Arrayelemente 3 und 4 sind  größer oder gleich diesem Durchschnitt
3 ist die kleinste dieser Zahlen, also wird sie als Ergebnis zurückgegeben.


```
public class Average {

 final public static int lowestValueGreaterThanAverage(final int[] arr) {

  int min = 0;
  for (int i = 0; i < arr.length; i++) {
   for (int a: arr) {
    if (arr[i] >= average(arr) && arr[i] < a) {
     min = arr[i];
    }
   }
  }
  return min;
 }

 public static int average(final int[] arr) {
  int sum = 0;
  int r = 0;
  for (int a: arr) {
   sum = sum + a;
  }
  r = sum / arr.length;
  return r;
 }
}
```


----------



## kneitzel (24. Mrz 2016)

Also bitte code immer in Code-Tags setzen. Dann fallen mir folgende Probleme auf:
a) Wieso hast Du zwei verschachtelte Schleifen? Wenn Du den Durchschnitt hast, dann musst Du doch nur einmal durch das Array gehen!
b) Du musst dir einmal das min merken und immer nur damit vergleichen. min setzt du am Anfang einfach auf den größten Integer Wert, der möglich ist und schon hast Du als Prüfung doch nur: Wenn der Wert größer ist als der Durchschnitt und kleiner ist als das aktuelle Minimum, dann setze das Minimum auf den Wert.

Ansonsten noch eine Optimierung: Die Berechnung des Durchschnitts geht ja immer durch das ganze Array. Da sich aber während deiner Suche nach den kleinsten Wert der größer als der Durchschnitt ist sich ja nichts ändert am Array macht es Sinn, den Wert einmal zu bestimmen und nicht für jede Prüfung neu zu berechnen.


----------



## Viktim (24. Mrz 2016)

So müsste es eigentlich klappen:


```
public static void main(String[] args) {
    int[] array = { 6, 2, 9, 5, 2, 7};
    int arrayGesamtWert = 0;

    for (int i = 0; i < array.length; i++) {
      arrayGesamtWert = arrayGesamtWert + array[i];
    }

    int durchSchnittsWert = (arrayGesamtWert / array.length);
    int kleinsteZahlÜbermDurchschnitt = 999999999;
    for (int i = 0; i < array.length; i++) {
      if (array[i] == durchSchnittsWert) {
        kleinsteZahlÜbermDurchschnitt = array[i];
        break;
      }
      if (array[i] > durchSchnittsWert && array[i] < kleinsteZahlÜbermDurchschnitt) {
        kleinsteZahlÜbermDurchschnitt = array[i];
      }
    }

    System.out.println("Durchschnitt: "+ durchSchnittsWert
        + "\nKleinste Zahl überm Durchschnitt ist: " + kleinsteZahlÜbermDurchschnitt);

  }
```

Du musst hier nur noch dein Array entsprechend Anpassen


----------



## bradig (24. Mrz 2016)

Danke .ich habe es dank dir hinbekommen.
soll man auch hier die richtige Ergebnisse posten,wenn man es am Ende hinbekommen hat?


----------



## Viktim (24. Mrz 2016)

bradig hat gesagt.:


> soll man auch hier die richtige Ergebnisse posten,wenn man es am Ende hinbekommen hat?



Wenn du willst


----------



## kneitzel (24. Mrz 2016)

Deine Lösung wäre schon interessant. Ist aber natürlich keine Pflicht. Nur bitte als Code, also im Editor oben auf das Einfügen Icon klicken und Code auswählen. Dann kannst Du auch noch Java als Sprache wählen wenn Du willst.


----------



## bradig (24. Mrz 2016)

```
public class Average {

 final public static int lowestValueGreaterThanAverage(final int[] arr) {
  int min = maximum(arr);
  for (int i = 0; i < arr.length; i++) {
   if (arr[i] >= average(arr) && arr[i] < min) {
    min = arr[i];
   }
  }
  return min;
 }

 public static int average(final int[] arr) {
  int sum = 0;
  int r = 0;
  for (int a: arr) {
   sum = sum + a;
  }
  r = sum / arr.length;
  return r;
 }
 public static int maximum(final int[] arr) {
  int max = 0.0;
  for (int a: arr) {
   if (a >= max) {
    max = a;
   }
  }
  return max;
 }
}
```


----------



## kneitzel (24. Mrz 2016)

Gefällt mir sehr gut, nur ein paar Kleinigkeiten würde ich anders machen:


```
final public static int lowestValueGreaterThanAverage(final int[] arr) {
        int min = Integer.MAX_VALUE; // No need to iterate through array with maximum(arr);
        int average = average(arr); // Only executed one time now!
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] >= average && arr[i] < min) {
                min = arr[i];
            }
        }
        return min;
    }

    public static int average(final int[] arr) {
        int sum = 0;
        int r = 0;
        for (int a: arr) {
            sum = sum + a;
        }
        r = sum / arr.length;
        return r;
    }
  
    public static int maximum(final int[] arr) {
        int max = 0; // Just 0 - 0.0 is a double!
        for (int a: arr) {
            if (a >= max) {
                max = a;
            }
        }
        return max;
    }
```

Sind nur paar Kleinigkeiten, aber evtl. willst Du die ja noch abändern.
Und generell würde ich bei Funktionen immer ein Verb mit benutzen, also getMaximum, getAverage, getXYZ, doSomething, ... Aber das habe ich im Code nicht angepasst, da die Namen ja evtl. vorgegeben waren.


----------



## Xyz1 (24. Mrz 2016)

Muss wirklich 2-mal über das Array/Liste gelaufen werden?


----------



## Joose (24. Mrz 2016)

Ich glaub ja  Das erste Mal um den Durchschnitt zu berechnen und beim zweiten Mal werden dann die einzelnen Elemente mit dem Durchschnitt verglichen.
Wenn du natürlich ähnlich verständlichen Code mit nur einen Durchlauf kennst, dann her damit.


----------



## Flown (24. Mrz 2016)

Witzige Aufgabenstellung. Lösung ist schon gepostet, wie man das per Hand macht. Wollte einfach mal mein Verusch mit ein paar Collection/Stream API calls zusammenfassen:

```
/**
 * Computes the least value greater or equal to the average of the given
 * array.
 * 
 * @param arr
 *          the array of values
 * @return the least element greater than or equal to the average
 * @throws NullPointerException
 *           if the given array is {@code null}
 * @throws NoSuchElementException
 *           if the given array is empty (i.e. {@code arr.length == 0})
 */
public static int getLowestAboveOrEqualsAverage(int[] arr) {
  Objects.requireNonNull(arr);
  if (arr.length == 0) {
    throw new NoSuchElementException();
  }
  NavigableSet<Integer> set = new TreeSet<>();
  int sum = Arrays.stream(arr).peek(set::add).sum();
  return set.ceiling(sum / arr.length);
}
```


----------



## Xyz1 (24. Mrz 2016)

Wow! Also danke euch für die Antworten... Zuerst hab ich einfach gelesen: ALLE, die größer gleich des Durchschnitts sind. Aber so macht es sinn.

Dann noch etwas:
http://stackoverflow.com/questions/...on-then-sort-it-or-add-to-a-sorted-collection
http://stackoverflow.com/questions/23329234/which-is-better-on-log-n-or-on2



> That means n^2 grows faster, so n log(n) is smaller (better), when n is high enough.



Das heißt, Flown's Algo ist schneller, wenn es soundsoviele Inhalte gibt.

Bis dann 

Edit: Sorry, ich hab mich mit der Komplexität vertan. Bin heute zu müde.


----------



## bradig (25. Mrz 2016)

```
public class Average {

final public static int lowestValueGreaterThanAverage(final int[] arr) {
  int min = Integer.MAX_VALUE;
int aver=average(arr) ;
  for (int i = 0; i < arr.length; i++) {
   if (arr[i] >= aver && arr[i] < min) {
    min = arr[i];
   }
  }
  return min;
}

public static int average(final int[] arr) {
  int sum = 0;
  int r = 0;
  for (int a: arr) {
   sum = sum + a;
  }
  r = sum / arr.length;
  return r;
}

}
```


----------



## bradig (25. Mrz 2016)

Mit MAX_VALUE brauche ich nicht extra eine Funktion schreiben,die das maximum berechnen.
Danke an euch allen.
hier kann man echt viele Sachen  lernen.
 Daum hoch für dieses Forum.


----------



## Flown (26. Mrz 2016)

Gestern nicht mehr dazu gekommen. Man kann ein paar Sachen noch verbessern:

```
/**
* Gibt das kleinste Element größer oder gleich dem arithmetischen Mittelwert
* zurück.
*
* @param arr
*          angegebene Zahlenfolge
* @return kleinste Element größer oder gleich dem arithmetischen Mittelwert
* @throws NullPointerException
*           wenn {@code arr == null} ist
* @throws NoSuchElementException
*           wenn {@code arr} leer ist
*/
final public static int lowestValueGreaterThanAverage(final int[] arr) {
  if (arr == null) {
    throw new NullPointerException();
  }
  if (arr.length == 0) {
    throw new NoSuchElementException();
  }
  int aver = average(arr);
  int min = Integer.MAX_VALUE;
  for (int element : arr) {
    if (aver == element) {
      return aver;
    } else if (aver < element && element < min) {
      min = element;
    }
  }
  return min;
}

/**
* Berechnet das ganzzahligen arithmetischen Mittelwert.
*
* @param arr
*          angegebene Zahlenfolge
* @return das arithmetische Mittel oder {@code 0} falls {@code arr} leer ist
*      
* @throws NullPointerException
*           wenn {@code arr == null} ist
*/
public static int average(final int[] arr) {
  if (arr == null) {
    throw new NullPointerException();
  }
  if (arr.length == 0) {
    return 0;
  }
  int sum = 0;
  for (int a : arr) {
    sum = sum + a;
  }
  return sum / arr.length;
}
```
Ein paar Checks sollten schon eingebaut sein für die Corner-Cases. Darüber hinaus kann man ein shortcircuit Verhalten einbauen, d.h. kleiner als der Durschnitt geht nicht und man kann gleich das Element zurückgeben.
Man kann auch nur ein Element finden, wenn das Array nicht leer ist.
Achja und ein paar JavaDoc-Worte währen auch nicht schlecht.


----------



## kneitzel (26. Mrz 2016)

Also Dein Code dürfte einen Fehler enthalten.
Du prüfst erst ob das erste Element = dem Durchschnitt ist. Kann man machen, ok.
Dann setzt Du min = arr[0]. Das ist falsch, denn arr[0] kann ja auch kleiner als der Durschschnitt sein.

Wenn man also { 1, 2, 5, 6 } nimmt, dann gibst Du die 1 zurück, da Du ja min am Anfang auf 1 setzt und dann gibt es kein Element mehr, das Größer als der Durchschnitt ist und kleiner als min.


----------



## Flown (26. Mrz 2016)

@kneitzel Ahja du hast natürlich recht, dann sollte man wirklich mit `Integer.MAX_VALUE` arbeiten (Code geändert).


----------

