|
Java [43] – Zadania do tablic jednowymiarowych Autor: Grzegorz, napisał dnia: 3 stycznia, 2018 Dodatkowe zadania, niektóre wraz z rozwiązaniami do części ćwiczeń kursu poświęconej tablicom jednowymiarowym (wersja uaktualniona z nowym zadaniem).
Zadania i rozwiązania
Zadanie 1 – odwracanie tablicy
Jest to klasyczny problem dotyczący tablic.
- Stwórz tablicę 10-elementową, wypełnioną liczbami.
- Odwróć kolejność liczb w tablicy.
- Wydrukuj zawartość tablicy.
Zanim przejdziesz do wskazówek, spróbuj sam rozwiązać zadanie.
Kliknij aby zobaczyć wskazówki
Wskazówki
Ogólna idea odwracania zawartości tablicy test taka: ostatni element zamienia się miejscami z pierwszym, następnie przedostatni z drugim itd. aż dojdziemy do środka tablicy. Tu proces się zatrzymuje, gdybyśmy poszli dalej odwrócilibyśmy to co już odwrócone, a przecież nie o to chodzi.
Jednak w zamianie wartości tkwi pewien problem. Jeśli po prostu skopiowalibyśmy wartość z komórki ostatniej do pierwszej, to od razu stracilibyśmy wartość z komórki pierwszej. Uprzednio trzeba więc umieścić tą wartość w zmiennej tymczasowej, z której następnie ją pobierzemy aby umieścić w ostatniej komórce.
Zamiana więc będzie przebiegała w trzech krokach:
- Skopiowanie wartości z komórki pierwszej do zmiennej.
- Skopiowanie wartości z komórki ostatniej do pierwszej.
- Skopiowanie wartości ze zmiennej do komórki ostatniej.
Dla „wzrokowców” dodatkowo obrazek ilustrujący ten proces:
Później proces się powtarza dla komórki drugiej i przedostatniej itd…
Tu trafiamy na kolejny problem. Łatwo jest uzyskać indeks komórki pierwszej, drugiej, trzeciej itd., będzie to po prostu wartość i z klasycznej pętli for . Ale jak uzyskać indeksy kolejnych komórek od końca?
Magiczna formuła będzie wyglądała tak: tablica.length-1-i . Zastanów się dlaczego. Szczegółowe wyjaśnienie w kodzie.
Kod
Kliknij aby zobaczyć rozwiązanie
class OdwracanieTablicy {
public static void main(String[] args) {
int[] tablica = {1,2,3,4,5,6,7};
// zmienna "tymczasowa" która będzie tymczasowo przechowywać wartości
int tmp;
int l = tablica.length;
System.out.print("Przed odwróceniem: ");
for (int i: tablica) System.out.print(i+" ");
// petla od 0 do l/2 ponieważ zamieniamy raz element
// ostatni z pierwszym, przedostatni z drugim itd,
// aż dojdziemy do środka tablicy.
for (int i = 0; i < l/2; i++) {
// kopiowanie wartości z tablicy do zmiennej
tmp = tablica[i];
// kopiowanie wartości do kolejnych komórek z miejsca l-1-i bo:
// l: (długość tablicy)
// -1: bo ostatni indeks w tablicy jest
// o 1 mniejszy niż nr. ostatniego indeksu
// -i: przesuwamy się o 1 od końca do środka
tablica[i]=tablica[l-1-i];
// kopiowanie wartości ze zmiennej "tymczasowej" do komórki
// z której pobrano wartość i skopiowano o do komórki o indeksie i
tablica[l-1-i]=tmp;
}
System.out.print("nPo odwróceniu: ");
for (int i: tablica) System.out.print(i+" ");
}
}
Zadanie 2 – obliczanie wariancji
Tym razem obliczymy wariancję dla zestawu liczb, które mogą być np. pomiarami.
- Stwórz tablicę 1-wymiarową, wypełnioną liczbami typu double.
- Oblicz i wydrukuj wariancję dla tego zestawu liczb.
Wzór na wariancję wygląda tak:
Gdzie:
- s2 – wariancja
- xi – kolejny pomiar
- xs – średnia z pomiarów
- N – liczba pomiarów
Zanim przejdziesz do wskazówek, spróbuj sam rozwiązać zadanie.
Kliknij aby zobaczyć wskazówki
Wskazówki
Kolejne pomiary, to właśnie kolejne liczby w naszej tablicy.
Jak widać potrzebna będzie najpierw średnia z pomiarów, a do jej policzenia musimy mieć sumę wszystkich elementów. Można to zrobić przy użyciu pętli iterującej po tablicy, jak robiliśmy to poprzednio. Sumę dzielimy przez liczbę elementów w tablicy, otrzymując średnią.
Następnie trzeba obliczyć sumę kwadratów różnicy xi-xs . Na razie nie poznaliśmy jeszcze niezwykle pomocnego w obliczeniach pakietu Math, więc do uzyskania drugiej potęgi użyjemy po prostu mnożenia.
Ponieważ będziemy odejmować średnią od kolejnych pomiarów, znów zastosujemy pętlę.
Reszta jest trywialna.
Kod
Kliknij aby zobaczyć rozwiązanie
class Wariancja {
public static void main(String[] args) {
double[] tablica = {1.0,2.0,2.5,4.0,3.7,3.5,2.3,2.5,3.6};
double suma=0.0;
double srednia=0.0;
double sumaRoznic=0.0;
int N = tablica.length;
double wariancja;
// Obliczanie sumy elementów w tablicy
for (int i = 0; i < N; i++) {
suma+=tablica[i];
}
System.out.println("Suma: "+suma);
// Obliczanie średniej wartości w tablicy
srednia = suma/N;
System.out.println("Średnia: "+srednia);
// Obliczanie sumy kwadratów różnic wartości i średniej
for (int i = 0; i < N; i++) {
sumaRoznic+=(tablica[i]-srednia)*(tablica[i]-srednia);
}
System.out.println("Suma różnic: "+sumaRoznic);
// Obliczanie wariancji
wariancja = sumaRoznic/(N-1);
System.out.println("Wariancja: "+wariancja);
}
}
Zadanie 3 – Wartości unikalne w tablicy
Utwórz tablicę z liczbami całkowitymi, niektóre z nich powinny się powtarzać a następnie:
- Wypisz liczby, które się nie powtarzają
- Utwórz tablicę z wszystkimi liczbami, które wystepują w tablicy ale każda z nich powinna wystepować tylko tylko raz. Np: na podstawie tablicy [0, 2, 4, 2, 6, 7, 4, 3, 12, 6] utwóż tablicę [0, 2, 4, 6, 7, 3, 12].
Kolejność liczb jest obojętna.
Kliknij aby zobaczyć rozwiązanie
import java.util.Arrays;
public class Unikalne {
public static void main(String[] args) {
// Tworzenie tablicy
int[] tablica = {0, 2, 4, 2, 6, 7, 4, 3, 12, 6};
// Wydruk zawartości tablicy
System.out.println("Tablica: " + Arrays.toString(tablica));
// Szukanie wartości, które pojawiają się tylko raz
System.out.println("Wartości, które występują tylko raz:");
// Przeglądanie po lolei wszystkich elementów w tablicy
for (int i = 0; i < tablica.length; i++) {
// znacznik unikalności
boolean uniq = true;
// porównujemy dany element z wszystkimi innymi...
for (int j = 0; j < tablica.length; j++) {
// ... oprócz siebie samego
if (i != j) {
// jeśli element jest taki sam jak inny element
// to znacznik = false, czyli element nie jest unikalny
if (tablica[i] == tablica[j]) {
uniq = false;
}
}
}
// Jeśli znacznik się nie zmienił to znaczy, że element jest unikalny
if (uniq) {
System.out.println(tablica[i]);
}
}
// Tablica z liczbami występującymi w tablicy
// Metoda 1 - z sortowaniem
// Sortowanie, zob. https://ggoralski.pl/?p=1641
// Najpierw tworzę kopię tablicy, będę ją sortował
// Nie jest to konieczne, ale tu chce zachować oryginał tablicy
// do dalszych przykładów
int[] tablicaPosortowana = tablica.clone();
int mini;
int tmp;
for (int i = 0; i < tablica.length; i++) {
mini = i;
for (int j = i; j < tablica.length; j++) {
if (tablicaPosortowana[j] < tablicaPosortowana[mini]) {
mini = j;
}
}
tmp = tablicaPosortowana[i];
tablicaPosortowana[i] = tablicaPosortowana[mini];
tablicaPosortowana[mini] = tmp;
}
System.out.println("Tablica posortowana: " + Arrays.toString(tablica));
// tworzymy tablicę tymczasową o długości takiej jak wyjściowa, do której
// będziemy wpisywać liczby
int[] tabTmp = new int[tablica.length];
// Zmienna przechowująca liczbę różnych liczb
int ileLiczb = 0;
// Wpisujemy pierwszą wartość z tablicy tablica
tabTmp[0] = tablicaPosortowana[0];
// jedna liczba już jest
ileLiczb++;
for (int i = 1; i < tablica.length; i++) {
// Jeśli kolejna liczba nie jest taka sama jak poprzednia
// w posortowanej tablicy to znaczy, że wystepuje pierwszy raz
if (tablicaPosortowana[i] != tablicaPosortowana[i - 1]) {
// indeks piewszej wolnej komórki jest taki jak ileLiczb
tabTmp[ileLiczb] = tablicaPosortowana[i];
ileLiczb++;
}
}
System.out.println("Tablica tabTmp " + Arrays.toString(tabTmp));
// Tablica tabTmp posiada za dużo komórek, dlatego tworzymy nową tablicę o długości
// takiej jak ileLiczb i tyle liczb kopiujemy do niej
// zob. https://ggoralski.pl/?p=1641
int[] liczby = Arrays.copyOf(tabTmp, ileLiczb);
System.out.println("liczby: " + Arrays.toString(liczby));
// Metoda 2 - z zaznaczaniem duplikatów
// Tworzymy tablicę boolean o długości takiej jak tablica, będziemy
// w niej zaznaczyć duplikaty liczb przez ustawianie true przy odpowiednich indeksach
boolean[] duplikaty = new boolean[tablica.length];
// Zmienna przechowująca liczbę różnych liczb,
// w tym przypadku na początku to liczba wszystkich liczb
int ileLiczb2 = tablica.length;
for (int i = 0; i < tablica.length; i++) {
// nie ma sensu sprawdzać miejsc, w których znajdują się duplikaty
if (!duplikaty[i]) {
for (int j = i + 1; j < tablica.length; j++) {
// Duplikat
if (tablica[i] == tablica[j]) {
duplikaty[j] = true;
// Skoro duplikat to liczbaLiczb się zmniejsza o 1
ileLiczb2--;
}
}
}
}
System.out.println("Duplikaty: " + Arrays.toString(duplikaty));
// Teraz tworzę tablicę z liczbami
int[] liczby2 = new int[ileLiczb2];
int j = 0; // licznik dla liczby2
// Sprawdzam po kolei duplikaty
for (int i = 0; i < tablica.length; i++) {
// Umieszczam w liczby2 wartości, ale tylko te, którym odpowiadają
// wartości false z tablicy duplikaty
if (!duplikaty[i]) {
liczby2[j] = tablica[i];
j++;
}
}
System.out.println("liczby2: " + Arrays.toString(liczby2));
}
}
Related
|
Zadanie 1
import java.util.Arrays;
import java.util.Random;
public class ArrayOne {
public static void main(String[] args) {
int [] tabOne = new int [10];
for (int i = 0; i < tabOne.length; i++){
Random randomNumber = new Random();
int randomNumberOfArray = randomNumber.nextInt(100) + 1;
tabOne [i] = randomNumberOfArray;
}
System.out.println("The array witch randoms number is: " + Arrays.toString(tabOne));
int [] tabTwo = new int [tabOne.length];
for (int i = 0; i<tabTwo.length; i++){
tabTwo[i] = tabOne[tabOne.length – 1 – i];
}
System.out.println("The reverse order numbers in tabOne: " + Arrays.toString(tabTwo));
}
}
Zadanie 2
import java.util.Arrays;
import java.util.Scanner;
import static java.lang.Math.pow;
public class ArrayTwo {
public static void main(String[] args) {
System.out.println(„Enter the size of the board. \nChoose number from 5 to 10”);
int arraySize;
do {
Scanner yourNumber = new Scanner(System.in);
arraySize = yourNumber.nextInt();
if (5 <= arraySize && arraySize <=10) System.out.println("You seted array size as " + arraySize + ".");
else System.out.println("Wrong! Choose number from 5 to 10!");
} while (arraySize 10);
double [] tab = new double [arraySize];
for (int i = 0; i< tab.length; i++) {
tab [i] = Math.random();
}
System.out.println("Array with random double numbers: " + Arrays.toString(tab));
double arithmeticAverago;
double sumOfArrayElements = 0;
for (int i = 0; i<tab.length; i++){
sumOfArrayElements += tab [i];
}
arithmeticAverago = (sumOfArrayElements/tab.length);
System.out.println("The arithmetic average of array elements is: " + arithmeticAverago);
double sumOfSubstraction = 0;
for (int i = 0; i<tab.length; i++){
sumOfSubstraction += pow((tab[i] – arithmeticAverago),2);
}
double variance = (sumOfSubstraction)/(tab.length – 1);
System.out.println("The variance of numbers in array is: " + variance);
}
}
Cześć,
Mam pytanie odnośnie warunku w wierszu 096: if (!duplikaty[i])
Czy jest on konieczny? Ten zapis oznacza: „jeżeli wartość elementu 'i’ tablicy jest fałszywa” czy, że ten element nie ma przypisanej wartości?
Będę wdzięczny za rozjaśnienie.
Mam na myśli rozwiązanie zadania 3.
Tablica duplikaty[], jest domyślnie wypełniona wartościami false (zob. http://ggoralski.pl/?p=1631).
W tym fragmencie kodu, do kolejnych elementów tablicy tablica[] są przyrównywane następne elementy tej tablicy. Jeśli któryś z tych kolejnych jest taki sam (taka sama liczba), to w miejscu, w którym on występuje (w danym indeksie) zmieniamy domyślną wartość false na true, czyli zaznaczamy, że w tym miejscu (w tablica[]) znajduje się duplikat. Skoro już wiemy, że jest to duplikat, nie ma sensu go sprawdzać.
Zapis !duplikaty[i] oznacza: „nie true” czyli kod wykona się, jeśli w danym miejscu tablicy duplikaty[] znajduje się wartość false.
Grzegorz, dziękuję za wyjaśnienie. Zastanawiał mnie głównie fakt, że jeżeli tablica duplikaty nie była wcześniej używana, a w tej pętli for licznik 'i’ będzie cały czas zwiększany to każdy ze sprawdzanych elementów będzie na początku false, więc sprawdzenie warunku !duplikaty[i] będzie za każdym razem miało wartość true. Rozumiem, że to jest zabezpieczenie, ale czy w tym przypadku jest konieczne?
Może coś przeoczyłem lub nie uwzględniłem czegoś?
To może po kolei:
Na początku tablice wyglądają tak:
tablica: [0, 2, 4, 2, 6, 7, 4, 3, 12, 6]
duplikaty: [F, F, F, F, F, F, F, F, F, F]
Sprawdzamy pierwszy element w tablica[].
0 jest porównywane do wszystkich następnych elementów (w pętli wewnętrznej)
Nie ma on duplikatu, więc nic się nie zmienia.
Teraz porównujemy z następnymi element drugi, o wartości 2. Czwarty element (indeks 3) też wynosi 2 więc w tablicy duplikaty zmienia się wartość pod indeksem 3 z F na T (true). Tak sobie zanaczyliśmy, że element pod indeksem 3 jest duplikatem.
Następnie testowany jest element trzeci (indeks 2, wartość 4), ten znów ma duplikat pod indeksem 6, więc tu też zmienia się wartoćc w tablicy duplikaty[]. Teraz wygląda ona tak:
[F, F, F, T, F, F, T, F, F, F]
Kolej na sprawdzenie elementu czwartego (indeks 3). To był znaleziony duplikat dla drugiego elementu tablicy, co zaznaczyliśmy w tablicy duplikaty[].
Skoro wiemy, że nie jest to wartość unikalna, i że inne te same wartości już zostały zaznaczone (jeśli były) w tablicy duplikaty, to nie ma sensu sprawdzać tej wartości czy nie jest duplikatem (bo wiemy, że jest). Po to jest ten warunek.
Gdyby go ominąć, kod (na oko) też by działał, ale wykonywałby niepotrzebne operacje, co oczywiście przy tak małej tablicy i tak byłoby nie od zauważenia.
Swoją droga warto samemu poeksperymentiować i sprawdzić „co się stanie jeśli zmienię ten fragment kodu”, tak się można sporo nauczyć :-)
Faktycznie przeoczyłem to, że później j jest indeksem elementu tablicy. Dzięki za poświęcony czas! :)
Testowałem usuwając ten warunek i wyniki były identyczne. A przez to, że na początku się zafixowałem nie mogłem już dostrzec reszty.jeszcze raz dzięki!