Ćwiczenia do Modułu 1: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Daria (dyskusja | edycje)
Koszty i wskazowki
Daria (dyskusja | edycje)
Nie podano opisu zmian
 
(Nie pokazano 13 pośrednich wersji utworzonych przez tego samego użytkownika)
Linia 27: Linia 27:
'''Rozwiązanie 1'''  
'''Rozwiązanie 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' FlagaPolska1(N,A);
  '''program''' FlagaPolska1(N:integer; A:array[1..N] of integer);
//Tablica A jest wypełniona zerami i jedynkami
  '''const''' bialy = 0;
  '''const''' bialy = 0;
       czerwony = 1;
       czerwony = 1;
Linia 54: Linia 55:
'''Rozwiązanie 2'''  
'''Rozwiązanie 2'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' FlagaPolska2(N,A);
  '''program''' FlagaPolska2(N:integer; A:array[1..N] of integer);
//Tablica A jest wypełniona zerami i jedynkami
  '''const''' bialy = 0;
  '''const''' bialy = 0;
       czerwony = 1;
       czerwony = 1;
Linia 63: Linia 65:
     '''if''' Kol(c)=czerwony '''then''' c:=c+1
     '''if''' Kol(c)=czerwony '''then''' c:=c+1
     '''else''' '''begin'''
     '''else''' '''begin'''
       '''while''' Kol(b)=biały '''and''' (c<b) '''do''' b:=b-1;
       '''while''' Kol(b)=biały '''and''' (c<b) '''do''' b:=b-1; //pętla po białych od końca tablicy
       '''if''' b<c '''then''' '''begin'''
       '''if''' c<b '''then''' '''begin'''
         Z(c,b);
         Z(c,b);
         b:=b-1;
         b:=b-1;
Linia 86: Linia 88:
'''Rozwiązanie 3'''  
'''Rozwiązanie 3'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' FlagaPolska3(N,A);
  '''program''' FlagaPolska3(N:integer; A:array[1..N] of integer);
//Tablica A jest wypełniona zerami i jedynkami
  '''const''' bialy = 0;
  '''const''' bialy = 0;
       czerwony = 1;
       czerwony = 1;
Linia 130: Linia 133:
'''Rozwiązanie 4'''  
'''Rozwiązanie 4'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' FlagaPolska4(N,A);
  '''program''' FlagaPolska4(N:integer; A:array[1..N] of integer);
//Tablica A jest wypełniona zerami i jedynkami
  '''const''' bialy = 0;
  '''const''' bialy = 0;
       czerwony = 1;
       czerwony = 1;
Linia 169: Linia 173:
'''Wskazówka 1'''  
'''Wskazówka 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
Rozwiązanie dla flagi trójkolorowej jest uogólnieniem rozwiązania dla flagi dwukolorowej. Rozwiązanie 1 poniżej jest kombinacją rozwiązań 3 i 4 z zadania 1; zaś Rozwiązanie 2 poniżej jest bezpośrednim uogólnieniem  rozwiązania 4 z zadania 1. Jeśli chodzi o liczbę zamian to lepsze wydaje się Rozwiązanie 1, gdyż od razu na dobre miejsca trafiają elementy ujemne i dodatnie.
Rozwiązanie dla flagi trójkolorowej jest uogólnieniem rozwiązania dla flagi dwukolorowej. Rozwiązanie 1 poniżej jest kombinacją rozwiązań 3 i 4 z zadania 1; zaś Rozwiązanie 2 poniżej jest bezpośrednim uogólnieniem  rozwiązania 4 z zadania 1. Jeśli chodzi o liczbę zamian to lepsze wydaje się Rozwiązanie 1, gdyż od razu na dobre (ostateczne) miejsca trafiają elementy ujemne i dodatnie.
</div>
</div>
</div>
</div>
Linia 175: Linia 179:
'''Rozwiązanie 1'''  
'''Rozwiązanie 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' FlagaHolenderska(N,A);
  '''program''' FlagaTrójkolorowa(N:integer; A:array[1..N] of integer);
  '''var''' m,r,w,pom : integer;
  '''var''' m,r,w,pom : integer;
  '''begin'''
  '''begin'''
   m:=1; r:=1; w:=N;
   m:=1; r:=1; w:=N;
   '''while''' r <= w '''do'''  
   '''while''' r <= w '''do'''  
     '''if''' A[r]=0 '''then''' r:=r+1   //przedluzam segment liczb dodatnich
     '''if''' A[r]=0 '''then''' r:=r+1 //przedłużamy segment liczb dodatnich
     '''else'''  
     '''else'''  
       '''if''' A[r]<0 '''then''' '''begin''' //zamieniam wartosci w A[r] i A[m]
       '''if''' A[r]<0 '''then''' '''begin'''
         pom:=A[r]; A[r]:=A[m]; A[m]:=pom;   //po zamianie A[r]=0, A[m] < 0 wiec
         pom:=A[r]; A[r]:=A[m]; A[m]:=pom; //zamieniamy wartości w A[r] i A[m], po zamianie A[r]=0 i A[m] < 0
         m:=m+1;       //zwiekszam oba indeksy r i m
         m:=m+1; //więc zwiększamy oba indeksy r i m
         r:=r+1;
         r:=r+1;
       '''end'''
       '''end'''
       '''else''' '''begin'''
       '''else''' '''begin'''
         pom:=A[r]; A[r]:=A[w]; A[w]:=pom;   //zamieniam wartosci w A[r] i A[w]
         pom:=A[r]; A[r]:=A[w]; A[w]:=pom; //zamieniamy wartości w A[r] i A[w]
         w:=w-1;     //po zamianie A[w]>0,  
         w:=w-1; //po zamianie A[w]>0, ale o A[r] nic nie wiemy
       '''end''';     //ale o A[r] nic nie wiem
       '''end''';      
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt czasowy'': liniowy względem N
Linia 200: Linia 204:
'''Rozwiązanie 2'''  
'''Rozwiązanie 2'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' FlagaHolenderska(N,A);
  '''program''' FlagaTrójkolorowa(N:integer; A:array[1..N] of integer);
  '''var''' m,r,w,pom : integer;
  '''var''' m,r,w,pom : integer;
  '''begin'''
  '''begin'''
   m:=1; r:=1; w:=1;
   m:=1; r:=1; w:=1;
   '''while''' w <= N '''do'''  
   '''while''' w <= N '''do'''  
     '''if''' A[w]>0 '''then''' w:=w+1 //przedluzam segment liczb dodatnich
     '''if''' A[w]>0 '''then''' w:=w+1 //przedłużamy segment liczb dodatnich
     '''else'''  
     '''else'''  
       '''if''' A[w]=0 '''then''' '''begin'''
       '''if''' A[w]=0 '''then''' '''begin'''
         pom:=A[r]; A[r]:=A[w]; A[w]:=pom; //zamieniam wartosci w A[r] i A[w], /po zamianie A[r]=0, A[w] >0  
         pom:=A[r]; A[r]:=A[w]; A[w]:=pom; //zamieniamy wartości w A[r] i A[w], po zamianie A[r]=0, A[w] >0  
         w:=w+1; //wiec zwiekszam oba indeksy r i w
         w:=w+1; //więc zwiększamy oba indeksy r i w
         r:=r+1;
         r:=r+1;
       '''end'''
       '''end'''
       '''else''' '''begin''' //zamieniam cyklicznie A[m], A[r] i A[w]
       '''else''' '''begin''' //zamieniamy cyklicznie A[m], A[r] i A[w]
         pom:=A[m]; A[m]:=A[w]; A[w]:=A[r]; A[r]:=pom;  
         pom:=A[m]; A[m]:=A[w]; A[w]:=A[r]; A[r]:=pom;  
         m:=m+1;
         m:=m+1;
Linia 226: Linia 230:


== Zadanie 3 (Najdłuższe plateau) ==
== Zadanie 3 (Najdłuższe plateau) ==
Napisz program znajdujący w zadanej tablicy A typu array[1..N] of integer, N > 1,  długość
Napisz program znajdujący w zadanej tablicy A typu array[1..N] of integer, N > 0,  długość najdłuższego stałego segmentu (spójnego fragmentu tablicy).
najdłuższego stałego segmentu (spójnego fragmentu tablicy).
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
 
'''Wskazówka 1'''
<div class="mw-collapsible-content" style="display:none">
Zadanie to można rozwiązać używając dwóch pętli; zewnętrznej (po możliwych początkach segmentu) i wewnętrznej (w której szukamy końca segmentu stałego).
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''  
'''Rozwiązanie 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' NajdluzszePlateau1(N,A);
  '''program''' NajdłuższePlateau1(N:integer; A:array[1..N] of integer);
  '''var''' p,w,k,maks: integer;
  '''var''' l,p,w,maks: integer;
  '''begin'''
  '''begin'''
   p:=1; w:=A[p]; maks:=1;  
   l:=1; w:=A[l]; maks:=1;  
   '''while''' p < N '''do''' '''begin'''
   '''while''' l < N '''do''' '''begin'''
     k:=p+1; koniec:=false;
     p:=l+1; koniec:=false;
     '''while''' (k <= N) '''and''' ('''not''' koniec) '''do'''
     '''while''' (p <= N) '''and''' ('''not''' koniec) '''do''' //dopóki jesteśmy w tablicy i poruszamy się wewnątrz segmentu stałego
       '''if''' A[k]=w '''then''' k:=k+1
       '''if''' A[p]=w '''then''' p:=p+1
       '''else''' koniec:=true;
       '''else''' koniec:=true;
     maks:=max(maks, k-p);
     maks:=max(maks, p-l); //poprawiamy maks
     p:=k;
     l:=p;
     '''if''' p <= N '''then''' w:=A[p];
     '''if''' l <= N '''then''' w:=A[l]; //ustawiamy nowy początek segmentu
   '''end''';
   '''end''';
   '''end'''.
   '''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 2'''
<div class="mw-collapsible-content" style="display:none">
Dokładnie to samo rozwiązanie można zapisać używając jednej pętli.
</div>
</div>
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 2'''  
'''Rozwiązanie 2'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' NajdluzszePlateau2(N,A);
  '''program''' NajdłuższePlateau2(N:integer; A:array[1..N] of integer);
  '''var''' w,k,dl,maks: integer;
  '''var''' w,p,dl,maks: integer;
  '''begin'''
  '''begin'''
   w:=A[1]; dl:=1; k:=2; maks:=1;  
   w:=A[1]; dl:=1; p:=2; maks:=1;  
   '''while''' k <= N '''do''' '''begin'''
   '''for''' p:=2 '''to''' N '''do''' '''begin'''
     '''if''' A[k]=w '''then''' dl:=dl+1
     '''if''' A[p]=w '''then''' dl:=dl+1
     '''else''' '''begin'''
     '''else''' '''begin'''
       maks:=max(maks, dl);
       maks:=max(maks, dl);
       dl:=1;
       dl:=1;
     '''end''';
     '''end''';
    k:=k+1;
   '''end''';
   '''end''';
   maks:=max(maks, dl);
   maks:=max(maks, dl);
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Pytanko 1'''
<div class="mw-collapsible-content" style="display:none">
Czy przedostatnia linia programu w Rozwiązaniu 2 jest potrzebna? Co by było gdyby jej nie było ?
</div>
</div>
===Inna wersja zadania===
A co było gdyby tablica była posortowana ?
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 3'''
<div class="mw-collapsible-content" style="display:none">
Podczas przechodzenia tablicy indeksem i od lewej do prawej, zmiana maks - dotychczas odnalezionej wartości najdłuższego plateau - zachodzi tylko wtedy gdy A[i] wydłuża ostatnie plateau do długości maks+1. Ponieważ tablica jest posortowana to wystarczy porównywać wartości A[i] i A[i-maks]. 
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 3'''
<div class="mw-collapsible-content" style="display:none">
'''program''' NajdłuższePlateau3(N:integer; A:array[1..N] of integer);
'''var''' i,maks: integer;
'''begin'''
  maks:=1;
  '''for''' i:=2 '''to''' N '''do'''
    '''if''' A[i]=A[i-maks] '''then''' maks:=maks+1;
'''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>


== Zadanie 4 (Segment o maksymalnej sumie) ==
== Zadanie 4 (Segment o maksymalnej sumie) ==
Napisz program znajdujący w zadanej tablicy A typu array[1..N] of integer, N > 1,  
Napisz program znajdujący w zadanej tablicy A typu array[1..N] of integer, N > 0, maksymalną sumę segmentu (spójnego fragmentu tablicy). Przyjmujemy, że segment pusty ma sumę 0.
maksymalną sumę segmentu (spójnego fragmentu tablicy). Przyjmujemy, że segment pusty ma sumę 0.
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1''' 
<div class="mw-collapsible-content" style="display:none">
Najprostsze rozwiązanie to dla wszystkich możliwych segmentów policzyć ich sumę.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''
<div class="mw-collapsible-content" style="display:none">
'''program''' SegmentOMaksymalnejSumie1(N:integer; A:array[1..N] of integer);
'''var''' l,p,j,suma,maks: integer;
'''begin'''
  maks:=0;
  '''for''' l:=1 '''to''' N '''do''' '''begin''' //wybieramy początek segmentu
    '''for''' p:=l '''to''' N '''do''' '''begin''' //wybieramy koniec
      suma:=0;
      '''for j:=l '''to''' p '''do''' suma:=suma+A[j]; //liczymy sumę
      maks:=max(maks,suma);
    '''end''';
  '''end''';
'''end'''.
''Koszt czasowy'': sześcienny względem N


''Koszt pamięciowy'': stały
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1'''  <div class="mw-collapsible-content" style="display:none">Najprostsze rozwiązanie ma złożoność  kwadratową.</div>
'''Wskazówka 2'''   
<div class="mw-collapsible-content" style="display:none">
W powyższym rozwiązaniu sumę pewnych segmantów liczy się wiele razy. Lepiej, dla danego początku l obliczać po kolei sumy coraz dłuższych segmentów zaczynających sie w l.
</div>
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''  
'''Rozwiązanie 2'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' NajdluzszePlateau2(N,A);
  '''program''' SegmentOMaksymalnejSumie2(N:integer; A:array[1..N] of integer);
  '''var''' p,k,suma, maks: integer;
  '''var''' l,p,suma, maks: integer;
  '''begin'''
  '''begin'''
   maks:=0;
   maks:=0;
   '''for''' p:=1 '''to''' N '''do''' '''begin'''
   '''for''' l:=1 '''to''' N '''do''' '''begin'''
     suma:=0;
     suma:=0;
     '''for''' k:=p '''to''' N '''do''' '''begin'''
     '''for''' p:=l '''to''' N '''do''' '''begin'''
       suma:=suma+A[k];  
       suma:=suma+A[p];  
       maks:=max(maks,suma);
       maks:=max(maks,suma);
     '''end''';
     '''end''';
   '''end''';
   '''end''';
  '''end'''.
  '''end'''.
''Koszt czasowy'': kwadratowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 3'''  <div class="mw-collapsible-content" style="display:none">
Niech Pref(i) oznacza sumę elemetów tablicy od 1 do i włącznie. Suma segmentu od l do p to oczywiście Pref(p) - Pref(l-1). Maksymalną sumę segmentu kończącego się w p uzyskamy odejmując od Pref(p) minimalne Pref(i) gdzie i przebiega [1..p].
</div>
</div>
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 3'''
<div class="mw-collapsible-content" style="display:none">
'''program'''  SegmentOMaksymalnejSumie3(N:integer; A:array[1..N] of integer);
'''var''' mini_pref,biez_pref,maks,i: integer;
'''begin'''
  maks:=0;
  mini_pref:=0
  biez_pref:=0;
  '''for''' i:=1 '''to''' N '''do''' '''begin'''
    biez_pref:=biez_pref+A[i]);
    mini_pref:=min(mini_pref,biez_pref);
    maks:=max(maks, biez_pref-mini_pref);
  '''end''';
'''end'''.
''Koszt czasowy'': liniowy względem N


''Koszt pamięciowy'': stały
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 4'''  <div class="mw-collapsible-content" style="display:none">
Poniższe rozwiązanie opiera się na spostrzeżeniu, że jeśli suma pewnego segmentu o początku w l i końcu w p jest ujemna, lub nawet równa zero, to nie ma sensu tego segmantu przedłużać. Co więcej wszystkie segmenty o początkach pomiędzy l i p będą podsegmentami tego dotychczas rozpatrywanego, więc nie ma sensu ich rozważać przy poszukiwaniu segmantu o maksymalnej sumie. Jedyną sensowną możliwością jest rozpatrywanie segmentów które zaczynają się od p+1. 
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 2''' <div class="mw-collapsible-content" style="display:none">Optymalne rozwiązanie ma liniową złożoność.</div>
'''Rozwiązanie 4'''  
<div class="mw-collapsible-content" style="display:none">
'''program'''  SegmentOMaksymalnejSumie4(N:integer; A:array[1..N] of integer);
'''var''' l,p,i,biez,maks: integer;
'''begin'''
  l:=1;
  p:=2;
  suma:=A[l]; 
  maks:=max(0,suma);
  while p <= N '''do'''
    '''if''' suma+A[p] <= 0 '''then''' '''begin'''
      l:=p+1;
      suma:=A[l];
      p:=l+1;
      maks:=max(0,suma);
    '''else''' '''begin'''
      suma:=suma+A[p];
      maks:max(0,suma);
      p:=p+1;
    '''end''';
'''end'''.
Ponieważ jest to rozwiązanie działające w czasie liniowym od N (p zwiększa się w każdym obrocie pętli) a wszystkich segmentów jest kwadratowo wiele, powstaje wątpliwość czy przypadkiem nie omijamy
segmentu a maksymalnej sumie. To trzeba by udowodnić. Temat ten będzie poruszany w module o niezmiennikach i logice Hoare'a.
 
''Koszt czasowy'': liniowy względem N
 
''Koszt pamięciowy'': stały
</div>
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 2'''  
'''Rozwiązanie 5'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' NajdluzszePlateau2(N,A);
Poniżej znajduje się inaczej (zwięźlej) zapisane Rozwiązanie 4. W tym rozwiązaniu nie odwołujemy się bezpośrednio do początku i końca aktualnego segmentu, a tylko do jego sumy (biez).
  '''program''' SegmentOMaksymalnejSumie5(N:integer; A:array[1..N] of integer);
  '''var''' i,biez,maks: integer;
  '''var''' i,biez,maks: integer;
  '''begin'''
  '''begin'''
Linia 310: Linia 444:
   '''end''';
   '''end''';
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>


== Zadanie 5 (Część wspólna zbiorów) ==
== Zadanie 5 (Część wspólna zbiorów) ==
Dane są dwie tablice A i B typu array[1..N] of integer, N > 1. Obie są
Dane są dwie tablice A i B typu array[1..N] of integer, N > 0. Obie są
posortowane rosnąco. Należy traktując A i B jako reprezentacje dwu
posortowane rosnąco. Należy traktując A i B jako reprezentacje dwu
zbiorów wypisać (operacją write) cześć wspólną tych zbiorów.
zbiorów wypisać (operacją write) cześć wspólną tych zbiorów.
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1'''  <div class="mw-collapsible-content" style="display:none">
Będziemy przesuwać się po tablicach od prawej do lewej indeksami ia i ib. Za każdym obrotem pętli przesuwamy ten indeks pod którym jest miejsza wartość, lub oba gdy mają takie same wartości. 
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''
'''Rozwiązanie 1'''
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' CescWspolna(N,A,B);
  '''program''' CzęśćWspólna(N:integer; A,B:array[1..N] of integer);
//Tablice A i B są posortowane rosnąco
  '''var''' ia,ib: integer;
  '''var''' ia,ib: integer;
  '''begin'''
  '''begin'''
Linia 335: Linia 477:
       '''end''';
       '''end''';
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>


== Zadanie 6 (Suma zbiorów) ==
== Zadanie 6 (Suma zbiorów) ==
Dane są dwie tablice A i B typu array[1..N] of integer, N > 1. Obie są
Dane są dwie tablice A i B typu array[1..N] of integer, N > 0. Obie są
posortowane rosnąco. Należy traktując A i B jako reprezentacje dwu
posortowane rosnąco. Należy traktując A i B jako reprezentacje dwu
zbiorów wypisać (operacją write) sumę tych zbiorów.
zbiorów wypisać (operacją write) sumę tych zbiorów.
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1'''  <div class="mw-collapsible-content" style="display:none">
Dopóki istnieją elementy w obu tablicach przesuwamy się tak jak przy obliczaniu części wspólnej, potem obługujemy końcówki tablic.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''  
'''Rozwiązanie 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' Suma(N,A,B);
  '''program''' Suma(N:integer; A,B:array[1..N] of integer);
//Tablice A i B są posortowane rosnąco
  '''var''' ia,ib: integer;
  '''var''' ia,ib: integer;
  '''begin'''
  '''begin'''
   ia:=1; ib:=1;  
   ia:=1; ib:=1;  
   '''while''' (ia <= N) '''and''' (ib <= N) '''do'''  
   '''while''' (ia <= N) '''and''' (ib <= N) '''do''' //dopóki są elementy w obu tablicach
     '''if''' A[ia] < B[ib] '''then''' '''begin'''
     '''if''' A[ia] < B[ib] '''then''' '''begin'''
       write(A{ia], ' ');
       write(A{ia], ' ');
Linia 365: Linia 515:
         ib:=ib+1;
         ib:=ib+1;
       '''end''';
       '''end''';
   '''while''' ia <= N '''do''' write(A{ia], ' ');
   '''while''' ia <= N '''do''' write(A{ia], ' '); //obsługa końcówki A
   '''while''' ib <= N '''do''' write(B{ib], ' ');
   '''while''' ib <= N '''do''' write(B{ib], ' '); //obsługa końcówki B
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Pytanko 1'''
<div class="mw-collapsible-content" style="display:none">
Z dwóch pętli while obsługujących końcówki tablic A i B w Rozwiązaniu 1 wykona się co najwyżej jedna. W jakich sytuacjach nie wykona się żadna z nich ?
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 2'''  <div class="mw-collapsible-content" style="display:none">
Można próbować modyfikować rozwiązanie zadania o części wspólnej, tak by oddać analogię między sumą i częścią wspólną zbiorów. Prowadziłoby to do warunku (ia <= N) or (ib <= N) w głównej pętli while.  Trzeba jednak na nowo zdefiniować co to znaczy że pod danym indeksem jest mniejsza wartość niż pod innym indeksem, w sytuacji gdy jeden z tych indeksów może być większy od N.
</div>
</div>
</div>
</div>
Linia 373: Linia 537:
'''Rozwiązanie 2'''  
'''Rozwiązanie 2'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' Suma(N,A,B);
  '''program''' Suma(N:integer; A,B:array[1..N] of integer);
//Tablice A i B są posortowane rosnąco
  '''var''' ia,ib: integer;
  '''var''' ia,ib: integer;
  '''function mniejsze(ia, ib: integer):boolean;
  '''function''' mniejsze(ia,ib: integer):boolean; //funkcja porównująca wartości w ia i ib
  '''begin'''
  '''begin'''
   mniejsze:=false;
   mniejsze:=false;
Linia 382: Linia 547:
     '''if''' A[ia] < B[ib] '''then''' mniejsze:=true
     '''if''' A[ia] < B[ib] '''then''' mniejsze:=true
  '''end''';     
  '''end''';     
  '''begin'''
  '''begin''' //główny program
   ia:=1;  
   ia:=1;  
   ib:=1;  
   ib:=1;  
Linia 401: Linia 566:
       '''end''';
       '''end''';
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>


== Zadanie 7 (Podciąg) ==
== Zadanie 7 (Podciąg) ==
Dane są dwie tablice A typu array[1..N] of integer i B typu array[1..M] of integer, N, M > 1. Napisz program sprawdzający, czy A jest podciągiem B (tzn. czy istnieje funkcja f, rosnąca, z 1..N w 1..M, t. ze A[i]=B[f(i)]).
Dane są dwie tablice A typu array[1..N] of integer i B typu array[1..M] of integer, N, M > 0. Napisz program sprawdzający, czy A jest podciągiem B (tzn. czy istnieje funkcja f, rosnąca, z 1..N w 1..M, t. ze A[i]=B[f(i)]).
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1'''  <div class="mw-collapsible-content" style="display:none">
Każdy element tablcy A musi odnależć swoją kopię w tablicy B. Przechodząc tablicę A od lewej do prawej i szukamy odpowiednika A[i] w części B, która jeszcze nie została odwiedzona. 
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''  
'''Rozwiązanie 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' Podciag(N,A,M,B);
  '''program''' Podciąg(N,M:integer; A:array[1..N] of integer; B:array[1..M] of integer);
  '''var''' ia,ib: integer;
  '''var''' ia,ib: integer;
     istnieje: boolean;
     istnieje: boolean;
  '''begin'''
  '''begin'''
   '''if''' N > M '''then''' istnieje:=false
   '''if''' N > M '''then''' istnieje:=false //bo funkcja f miała być rosnąca
   '''else''' '''begin'''
   '''else''' '''begin'''
     ia:=1;ib:=1;
     ia:=1;ib:=1;
Linia 423: Linia 596:
       '''end''';
       '''end''';
     istnieje:=(ia>N);
     istnieje:=(ia>N);
    '''if''' istnieje '''then''' write('Tablica A jest podciągiem tablicy B);
   '''end''';
   '''end''';
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N+M
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>
Linia 430: Linia 607:
== Zadanie 8 (Odwracanie tablicy) ==
== Zadanie 8 (Odwracanie tablicy) ==
Dana tablica A typu array[0..N-1] of integer, N > 1. Napisz program odwracający kolejność elementów w A.
Dana tablica A typu array[0..N-1] of integer, N > 1. Napisz program odwracający kolejność elementów w A.
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1'''  <div class="mw-collapsible-content" style="display:none">
Należy zamienić element 0 z N-1, 2 z N-2 itd.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''
<div class="mw-collapsible-content" style="display:none">
'''program''' Odwracanie1(N:integer; A:array[0..N-1] of integer);
'''var''' l,pom: integer;
'''begin'''
  l:=0;
  '''while''' l < (N div 2) '''do''' '''begin'''
    pom:=A[l];
    A[p]:=A[N-1-l];
    A[N-1-l]:=pom;
    l:=l+1;
  '''end''';
'''end'''.
''Koszt czasowy'': liniowy względem N


''Koszt pamięciowy'': stały
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 2'''  <div class="mw-collapsible-content" style="display:none">
To samo co w Rozwiązaniu 1 można zrobić używjąc dwóch indeksów l i p na oznaczenie elemnetów z lewej i prawej strony tablicy. W ten sposób na pewno nie pomylimy się wyliczając element z którym ma się zamienić l (czy to N-1-l, N-l, N-(l+1) itp.) i warunek w while.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''  
'''Rozwiązanie 2'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' Odwracanie(N,A);
  '''program''' Odwracanie2(N:integer; A:array[0..N-1] of integer);
  '''var''' p,k,pom: integer;
  '''var''' l,p,pom: integer;
  '''begin'''
  '''begin'''
   p:=0; k:=N-1;
   l:=0; p:=N-1;
   '''while''' p < k '''do''' '''begin'''
   '''while''' l < p '''do''' '''begin'''
     pom:=A[p];
     pom:=A[l];
     A[p]:=A[k];
     A[l]:=A[p];
     A[k]:=pom;
     A[p]:=pom;
     p:=p+1;
     l:=l+1;
     k:=k-1;
     p:=p-1;
   '''end''';
   '''end''';
  '''end'''.
  '''end'''.
Można też odwracać jedynie część tablicy. Zapiszmy to w formie procedury
''Koszt czasowy'': liniowy względem N
  '''procedure''' Odwroc(var A: array[0..N-1] of integer, p,k:integer);
 
''Koszt pamięciowy'': stały
 
Można też odwracać jedynie część tablicy, pomiędzy indeksami l i p. Zapiszmy to w formie procedury
  '''procedure''' OdwracanieTablicy(var A: array[0..N-1] of integer; l,p:integer);
  '''var''' pom: integer;
  '''var''' pom: integer;
  '''begin'''
  '''begin'''
   '''while''' p < k '''do''' '''begin'''
   '''while''' l < p '''do''' '''begin'''
     pom:=A[p];
     pom:=A[l];
     A[p]:=A[k];
     A[l]:=A[p];
     A[k]:=pom;
     A[p]:=pom;
     p:=p+1;
     l:=l+1;
     k:=k-1;
     p:=p-1;
   '''end''';
   '''end''';
  '''end'''.  
  '''end'''.  
Linia 472: Linia 682:
'''Rozwiązanie 1'''  
'''Rozwiązanie 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' Przesun1(N,A,k);
  '''program''' Przesuń1(N,k:integer; A:array[1..N] of integer);
  '''var''' i: integer;
  '''var''' i: integer;
   P: array[0..N-1] of integer;
   P: array[0..N-1] of integer;
Linia 479: Linia 689:
   '''for'' i:=0 '''to''' N-1 '''do''' A[i]:=P[i];
   '''for'' i:=0 '''to''' N-1 '''do''' A[i]:=P[i];
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': liniowy względem N
</div>
</div>
</div>
</div>
Linia 484: Linia 697:
'''Wskazówka 2'''   
'''Wskazówka 2'''   
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
Można też skorzystać z rozkladu permutacji na cykle. Długość każdego takiego cyklu wynosi nww(N,k) a na dodatek pierwsze nwd(N,k) elementów tablicy należy do różnych cykli. Dodatkowym kosztem jest oczywiście obliczenie nww i nwd.  
Można też skorzystać z rozkladu permutacji na cykle. Długość każdego takiego cyklu wynosi N/nwd(N,k) a na dodatek pierwsze nwd(N,k) elementów tablicy należy do różnych cykli. Dodatkowym kosztem jest oczywiście obliczenie nwd.  
</div>
</div>
</div>
</div>
Linia 490: Linia 703:
'''Rozwiązanie 2'''  
'''Rozwiązanie 2'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' Przesun2(N,A,k);
  '''program''' Przesuń2(N,k:integer; A:array[1..N] of integer);
  '''var''' w,d: integer;
// k > 1
  '''var''' dl_cyklu,ile_cykli: integer;
  '''begin'''
  '''begin'''
   w:=nww(N,k);
   ile_cykli:=nwd(N,k);
   d:=nwd(N,k);
   dl_cyklu:=N/nwd(N,k);
   '''for''' i:=0 '''to''' d-1 '''do''' '''begin'''
   '''for''' i:=0 '''to''' ile_cykli-1 '''do''' '''begin'''
     akt:=A[i];  
     akt:=A[i];       //na akt zapamiętujemy wartość do przesunięcia
     nast:=(i+k) '''mod''' N;
     nast:=(i+k) '''mod''' N;                 //obliczamy dla niej nowe miejsce nast
     '''for''' j:=1 '''to''' w '''do''' '''begin'''
     '''for''' j:=1 '''to''' dl_cyklu '''do''' '''begin'''
       pom:=A[nast];
       pom:=A[nast];       //wstawiamy akt na A[nast]
       A[nast]:=akt;
       A[nast]:=akt;
       akt:=pom;
       akt:=pom;                       //to co tam było będzie nowym akt
       nast:=(nast+k) '''mod''' N;
       nast:=(nast+k) '''mod''' N;           //obliczamy nowe nast
     '''end''';
     '''end''';
   '''end''';
   '''end''';
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N + [[koszt nwd]]
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>
Linia 517: Linia 734:
'''Rozwiązanie 3'''  
'''Rozwiązanie 3'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' Przesun3(N,A,k);
  '''program''' Przesun3(N,k:integer; A:array[1..N] of integer);
// k > 1
  '''begin'''
  '''begin'''
   Odwroc(A,0,N-k-1);
   OdwracanieTablicy(A,0,N-k-1);
   Odwroc(A,N-k,N-1);
   OdwracanieTablicy(A,N-k,N-1);
   Odwroc(A,0,N-1);
   OdwracanieTablicy(A,0,N-1);
  '''end'''.
  '''end'''.
Procedura Odwroc pochodzi z zadania 8.
Procedura OdwracanieTablicy pochodzi z Zadania 8. Poprawność tego rozwiązania można uzasadnić poniższym rysunekiem. W pierwszej linii jest aryginalna tablica, a w kolejnych tablica po kolejnych wywolaniach procedury OdwracanieTablicy.
  a(0)    a(1)    ...        ...    a(N-k-1) a(N-k)    ...        a(N-1)
a(N-k-1) a(N-k-2)  ...        ...    a(0)    a(N-k)    ...        a(N-1)
a(N-k-1) a(N-k-2)  ...        ...    a(0)    a(N-1)    ...        a(N-k)
  a(N-k)  a(N-k+1)  ... a(N-1) a(0)    ...    ...      a(N-k-2)  a(N-k-1)
 
''Koszt czasowy'': liniowy względem N
 
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>


== Zadanie 10 (Następna permutacja) ==
== Zadanie 10 (Następna permutacja) ==
Tablica A typu array[1..N] of integer zawiera pewną permutację liczb 1.. N. Napisz program wpisujący do A następną leksykograficznie permutację. Zakładamy, że permutacja w A nie jest ostatnia leksykograficznie.
Tablica A typu array[1..N] of integer, N > 0,  zawiera pewną permutację liczb 1.. N. Napisz program wpisujący do A następną leksykograficznie [[permutację]]. Zakładamy, że permutacja w A nie jest ostatnia leksykograficznie.
 
'''Przykład''' Dla N=3 kolejne permutacje w [[porządku leksykograficznym]] wyglądają nastepująco:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1''' 
<div class="mw-collapsible-content" style="display:none">
Zastanów się która część talicy pozostanie taka sama w następnej permutacji.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''   
'''Rozwiązanie 1'''   
<div class="mw-collapsible-content" style="display:none">  
<div class="mw-collapsible-content" style="display:none">  
  '''program''' Nastepna_permutacja(N,A);
  '''program''' NastępnaPermutacja(N:integer; A:array[1..N] of integer);
//Permutacja zapisana w A nie jest ostatnia leksykograficznie
  '''var''' i,k,pom: integer;
  '''var''' i,k,pom: integer;
  '''begin'''
  '''begin'''
Linia 543: Linia 784:
     A[i]:=A[k];
     A[i]:=A[k];
     A[k]:=pom;
     A[k]:=pom;
     Odwroc(A,i,N);
     OdwracanieTablicy(A,i,N);
   '''end''';
   '''end''';
  '''end'''.
  '''end'''.
Procedura OdwracanieTablicy pochodzi z Zadania 8.
Najpierw szukamy od tyłu pierwszego elementu, takiego że A[i] < A[i+1] (tu korzystamy z założenia że to nie ostatnia permutacja), potem szukamy na prawo od i najmniejszego większego od niego elementu k (uwaga: dużo wygodniej to robić od prawej strony!), potem zamieniamy te elementy i odwracamy kolejność elementów na prawo od i.


Najpierw szukamy od tyłu pierwszego elementu, takiego że A[i] < A[i+1] (tu korzystamy z zalożenia że to nie ostatnia permutacja), potem szukamy na prawo od i najmniejszego większego od niego elementu k (uwaga: dużo wygodniej to robic od prawej strony!), potem zamieniamy te elementy i odwracamy kolejność elementów na prawo od i.
''Koszt czasowy'': liniowy względem N
 
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>


== Zadanie 11 (Segment o zadanej sumie)  ==
== Zadanie 11 (Segment o danej sumie)  ==
Tablica A typu array[1..N] of integer zawiera tylko liczby dodatnie. Napisz program który dla danego W typu integer sprawdza czy w A istnieje segment o sumie W (czyli czy istnieją p, k takie, że W<math>=A[p]+...+A[k-1]</math>).
Tablica A typu array[1..N] of integer, N > 0,  zawiera tylko liczby dodatnie. Napisz program który dla danego W typu integer sprawdza czy w A istnieje segment o sumie W (czyli czy istnieją l, p takie, że W<math>=A[l]+...+A[p-1]</math>).
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 1''' 
<div class="mw-collapsible-content" style="display:none">
Podobnie jak w zadaniu o segmencie o maksymalnej sumie można dla
danego początku l obliczać po kolei sumy coraz dłuższych segmentów zaczynających sie w l.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 1'''  
'''Rozwiązanie 1'''  
<div class="mw-collapsible-content" style="display:none">
'''program''' SegmentODanejSumie1(N,W:integer; A:array[1..N] of integer);
//Tablica A zawiera tylko liczby dodatnie
'''var''' l,p,suma: integer;
    znalezione: boolean;
'''begin'''
  '''if''' W < 0 '''then''' znalezione:=false
  '''else''' '''begin'''
    maks:=0;
    l:=1;
    znalezione:=false;
    '''while''' (l <= N) and (not znalezione) '''do''' '''begin'''
      p:=l;
      suma:=0;
      '''while''' (p <=  N) and (suma < W) '''do''' '''begin'''
          suma:=suma+A[p];
          p:=p+1;
      '''end'''; 
      znalezione:=(suma=W);
      l:=l+1;
    '''end''';  //while
  '''end''';  //else
  '''if''' znalezione '''then''' write('W tablicy A istnieje segment o sumie W);
'''end'''.
''Koszt czasowy'': kwadratowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Wskazówka 2''' 
<div class="mw-collapsible-content" style="display:none">
Podobnie jak w zadaniu o segmencie o maksymalnej sumie możliwe też jest rozwiązanie o liniowym koszcie czasowym.
</div>
</div>
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
'''Rozwiązanie 2'''
<div class="mw-collapsible-content" style="display:none">  
<div class="mw-collapsible-content" style="display:none">  
  '''program''' Segment_o_danej_sumie(N,A,W);
  '''program''' SegmentODanejSumie2(N,W:integer; A:array[1..N] of integer);
  '''var''' p,k,suma: integer;
//Tablica A zawiera tylko liczby dodatnie
     istnieje: boolean;
  '''var''' l,p,suma: integer;
     znalezione: boolean;
  '''begin'''
  '''begin'''
   '''if''' W < 0 '''then''' istnieje:=false  
   '''if''' W < 0 '''then''' znalezione:=false  
   '''else''' '''begin'''
   '''else''' '''begin'''
     p:=1; k:=1;
     l:=1; p:=1;
     suma:=A[1];
     suma:=0;
     '''while''' (suma <> W) '''and''' (k <= N) '''do'''
     '''while''' (suma <> W) '''and''' (p <= N) '''do'''
       '''if''' suma < W '''then''' '''begin'''
       '''if''' suma < W '''then''' '''begin''' //jeśli suma jest za mała to przesuwamy prawy koniec segmentu
         k:=k+1;
         suma:=suma+A[p];
         suma:=suma+A[k];
         p:=p+1;
       '''end'''
       '''end'''
       '''else''' '''begin'''
       '''else''' '''begin''' //jeśli za duża to przesuwamy lewy koniec segmentu
        p:=p+1;
         suma:= suma-A[l];
         suma:= suma-A[p];
        l:=l+1;
       '''end''';
       '''end''';
       istnieje:=(suma=W);
    '''while''' (suma > W) '''do''' '''begin'''          //jeśli suma nadal za duża to próbujemy ją zmniejszyć
   '''end''';
      suma:= suma-A[l];
       l:=l-1;
    '''end''';
    znalezione:=(suma=W);
   '''end''';  //else
  '''if''' znalezione '''then''' write('W tablicy A istnieje segment o sumie W);  
  '''end'''.
  '''end'''.
Ponieważ jest to rozwiązanie działające w czasie liniowym od N (l+p zwiększa się w każdym obrocie pętli) a wszystkich segmentów jest kwadratowo wiele, powstaje wątpliwość czy przypadkiem nie omijamy
segmentu a maksymalnej sumie. To trzeba by udowodnić. Wrócimy do tego problemu w module o niezmiennikach i logice Hoare'a.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>


== Zadanie 12 (Głosowanie większościowe) ==
== Zadanie 12 (Głosowanie większościowe) ==
Dana jest tablica A typu array[1..N] of integer, N > 1. Należy sprawdzić czy jest w niej element wystepujący więcej niż N/2 razy i jeśli tak wskazać go.
Dana jest tablica A typu array[1..N] of integer, N > 0. Sprawdzić czy jest w niej element wystepujący więcej niż N/2 razy i jeśli tak wskaż go.


<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
Linia 591: Linia 893:
'''Rozwiązanie 1'''  
'''Rozwiązanie 1'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' Glosowanie1(N,A);
  '''program''' Głosowanie1(N:integer; A:array[1..N] of integer);
  '''var''' i,j,ile,zwyciezca: integer;
  '''var''' i,j,ile,indeks_lidera: integer;
  '''begin'''
  '''begin'''
   i:=1;
   i:=1;
   zwyciezca:=0;
   indeks_lidera:=0;
   '''while''' (i <= (N div 2) + 1) '''and''' (zwyciezca=0)'''do''' '''begin'''
   '''while''' (i < (N+1) div 2) '''and''' (indeks_lidera=0) '''do''' '''begin'''
     ile:=0;
     ile:=0;
     '''for j:=1 '''to''' N '''do''' if A[i]=A[j] '''then''' ile:=ile+1;
     '''for j:=1 '''to''' N '''do''' if A[i]=A[j] '''then''' ile:=ile+1;
     '''if''' (ile > (N+1) div 2) '''then''' zwyciezca:=A[i];
     '''if''' (ile >= N div 2 + 1) '''then''' indeks_lidera:=i;
   '''end''';
   '''end''';
  '''if''' indeks_lidera <> 0 '''then''' write('Liderem jest: ', A[indeks_lidera]);
  '''end'''.
  '''end'''.
Ponieważ lider musi mieć co najmiej N div 2 + 1 wystąpień w tablicy, to wystarczy go szukać na ((N+1) div 2) pierwszych pozycjach tablicy A.
''Koszt czasowy'': kwadratowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>
Linia 608: Linia 916:
'''Wskazówka 2'''   
'''Wskazówka 2'''   
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
To zadanie ma też (piękne) rozwiązanie liniowe. Składa się ono z dwu faz. W pierwszej wyznaczamy takie a, że jeśli jest zwycięzca, to jest nim a, w drugiej (banalnej) sprawdzamy czy a wygrał.
To zadanie ma też (piękne) rozwiązanie liniowe. Składa się ono z dwóch faz. W pierwszej wyznaczamy takie kand, że jeśli jest lider, to jest nim kand, w drugiej (banalnej) sprawdzamy czy kand wygrał.
</div>
</div>
</div>
</div>
Linia 614: Linia 922:
'''Rozwiązanie 2'''  
'''Rozwiązanie 2'''  
<div class="mw-collapsible-content" style="display:none">
<div class="mw-collapsible-content" style="display:none">
  '''program''' Glosowanie2(N,A);
  '''program''' Głosowanie2(N,W:integer; A:array[1..N] of integer);
  '''var''' ile,i,a,kand,zwyciezca: integer;
  '''var''' ile,i,kand,lider: integer;
  '''begin'''
  '''begin'''
   kand:=1;
   kand:=A[1]; //szukamy kandydata na lidera
  a:=A[1];
   ile := 1;
   ile := 1;
   i := 1;
   '''for''' i:=2 '''to''' N '''do''' '''begin'''
  '''while''' i < N '''do''' '''begin'''
     '''if''' A[i]=kand '''then''' ile:=ile+1
    i:= i+1;
     '''if''' A[i]=a '''then''' ile:=ile+1
     '''else'''
     '''else'''
       '''if''' ile > 0 '''then''' ile:=ile-1
       '''if''' ile > 0 '''then''' ile:=ile-1
       '''else''' '''begin'''
       '''else''' '''begin'''
         a:=T[i];
         kand:=A[i];
         ile:=1;
         ile:=1;
       '''end''';
       '''end''';
   '''end''';
   '''end''';
   ile:=0;
   ile:=0; //sprawdzamy czy kandydat jest liderem
   '''for''' i:=1 '''to''' '''do'''  
   '''for''' i:=1 '''to''' '''do'''  
     '''if''' A[i]=a '''then''' ile:=ile+1;  
     '''if''' A[i]=kand '''then''' ile:=ile+1;  
   '''if''' (ile > (N+1)div 2) '''then'''  
   '''if''' (ile >= (N div 2 + 1) '''then''' '''begin'''  
     zwyciezca:=a
     lider:=kand;
    write('Liderem jest: ', kand);
  '''end'''
   '''else'''  
   '''else'''  
     zwyciezca:=0;
     lider:=0;
  '''end'''.
  '''end'''.
''Koszt czasowy'': liniowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>


== Zadanie 13 (Arytmetyka liczb wielocyfrowych) ==
== Zadanie 13 (Arytmetyka liczb wielocyfrowych) ==
Liczby wielocyfrowe będą reprezentowane w tablicach typu liczba=array[0..N-1] of integer w taki sposób, że najmniej znacząca cyfra jest pod indeksem 0.
Liczby wielocyfrowe będą reprezentowane w tablicach typu liczba=array[0..N-1] of integer, N > 1, w taki sposób, że najmniej znacząca cyfra jest pod indeksem 0. Rozpatrujemy liczby przy podstawie b > 1. Napisz procedury obliczające:
Rozpatrujemy liczby przy podstawie b &ge; 1. Napisz procedury obliczające:
# sumę liczb A i B do C. Jeśli wynik nie zmieści się w C to wartość C nie ma znaczenia. Zmienna przepełnienie wskazuje czy do niego doszło czy nie.
* sumę liczb A i B do C. Jeśli wynik nie zmieści się w C to wartość C nie ma znaczenia. Zmienna przepełnienie wskazuje czy do niego doszło czy nie.
# różnicę A i B do C. Jeśli wynik miałby byc liczbą ujemną to wartość C nie ma znaczenia. Zmienna ujemny wskazuje jaki jest znak wyniku.
* różnicę A i B do C. Jeśli wynik miałby byc liczbą ujemną to wartość C nie ma znaczenia. Zmienna ujemny wskazuje jaki jest znak wyniku.
# iloczyn A i B do C (C powinno być tablicą dwa razy dłuższą niż A i B, żeby móc pomieścić wynik).  
* iloczyn A i B do C (C powinno być tablicą dwa razy dłuższą niż A i B, żeby móc pomieścić wynik).  


<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
Linia 655: Linia 964:
   b=10;  
   b=10;  
  '''type''' liczba = array[0..N-1] of integer;
  '''type''' liczba = array[0..N-1] of integer;
   dwa_liczba = array[0..2N-1] of integer;
   dwa_liczba = array[0..2*N-1] of integer;
 
Poniżej treści procedur Suma, Roznica, Iloczyn:
   
   
  '''procedure''' Suma(A,B:liczba, var C:liczba, var:przepelnienie:boolean);
  '''procedure''' Suma(A,B:liczba, var C:liczba, var:przepełnienie:boolean);
//Sumujemy liczby zapisane w A i B do C; zmienna przepełnienie staje się true gdy wynik nie mieści się w C.
  '''var''' p: integer;
  '''var''' p: integer;
  '''begin'''
  '''begin'''
   p:=0;
   p:=0;
   '''for''' i:=0 '''to''' N-1 '''do''' '''begin'''
   '''for''' i:=0 '''to''' N-1 '''do''' '''begin'''
     C[i]:=A[i]+B[i];
     C[i]:=A[i]+B[i]+p;
     '''if''' C[i] >= b '''then''' '''begin'''
     '''if''' C[i] >= b '''then''' '''begin'''
       C[i]:=C[i]-b;
       C[i]:=C[i]-b;
Linia 669: Linia 981:
     '''else''' p:=0;
     '''else''' p:=0;
   '''end''';
   '''end''';
   przepelnienie:=(p=1);
   przepełnienie:=(p=1);
  '''end''';
  '''end''';
''Koszt czasowy'': liniowy względem N
  '''procedure''' Roznica(A,B:liczba, var C:liczba, var:ujemny:boolean);
 
''Koszt pamięciowy'': stały
  '''procedure''' Różnica(A,B:liczba, var C:liczba, var:ujemny:boolean);
//Odejmujemy od liczby zapisanej w A liczbę z B. Wynik zapisujemy w C, zmienna ujemny informuje o znaku wyniku.
  '''var''' p: integer;
  '''var''' p: integer;
  '''begin'''
  '''begin'''
Linia 686: Linia 1001:
   ujemny:=(p=1);
   ujemny:=(p=1);
  '''end''';
  '''end''';
''Koszt czasowy'': liniowy względem N
 
''Koszt pamięciowy'': stały
  '''procedure''' Iloczyn(A,B:liczba, var C:dwa_liczba);
  '''procedure''' Iloczyn(A,B:liczba, var C:dwa_liczba);
//Iloczyn liczb zapisanych w A i B zapisujemy w C.
  '''var''' p,i,j: integer;
  '''var''' p,i,j: integer;
  '''begin'''
  '''begin'''
Linia 698: Linia 1016:
       p:=w '''div''' b;
       p:=w '''div''' b;
     '''end''';
     '''end''';
     C[i+n]:=p;
     C[i+N]:=p;
     p:=0;
     p:=0;
   '''end''';
   '''end''';
  '''end''';
  '''end''';
''Koszt czasowy'': kwadratowy względem N
''Koszt pamięciowy'': stały
</div>
</div>
</div>
</div>

Aktualna wersja na dzień 13:02, 20 lip 2006

Ta strona zawiera podstawowe zadania na tablice.

Ogladaj wskazówki i rozwiązania __SHOWALL__
Ukryj wskazówki i rozwiązania __HIDEALL__


Zadanie 1 (Flaga polska)

Tablica A typu array[1..N] of integer (N > 0) wypełniona zerami i jedynkami reprezentuje ciąg N urn w których znajdują się żetony białe (0) i czerwone (1). Podaj algorytm działania automatu przestawiającego żetony w urnach tak, by najpierw były żetony czerwone, potem białe. Robot może wykonywać dwa rodzaje operacji:

  • Kol(i) - podaje kolor żetonu w i-tej urnie (1 ≤ i ≤ n)
  • Z(i,j) - zamienia żetony z i-tej i j-tej urny (1 ≤ i,j ≤ n)

Uwagi:

  1. Operacja Kol jest bardzo kosztowna, więc zależy nam na tym by kolor każdego żetonu był sprawdzany co najwyżej raz.
  2. Robot potrafi zapamiętać tylko kilka wartości z przedziału 0..N+1.
  3. Nie można założyć, że występuje choć jeden żeton w każdym z kolorów.

Wskazówka 1

Rozwiązanie 1

Wskazówka 2

Rozwiązanie 2

Wskazówka 3

Rozwiązanie 3

Wskazówka 4

Rozwiązanie 4

Pytanko 1

Pytanko 2


Zadanie 2 (Flaga trójkolorowa)

Dana jest tablica A typu array[1..N] of integer (N > 0). Należy tak poprzestawiać w niej elementy, żeby najpierw były elementy ujemne, potem równe zero, a na końcu dodatnie.

Wskazówka 1

Rozwiązanie 1

Rozwiązanie 2

Zadanie 3 (Najdłuższe plateau)

Napisz program znajdujący w zadanej tablicy A typu array[1..N] of integer, N > 0, długość najdłuższego stałego segmentu (spójnego fragmentu tablicy).

Wskazówka 1

Rozwiązanie 1

Wskazówka 2

Rozwiązanie 2

Pytanko 1

Inna wersja zadania

A co było gdyby tablica była posortowana ?

Wskazówka 3

Rozwiązanie 3

Zadanie 4 (Segment o maksymalnej sumie)

Napisz program znajdujący w zadanej tablicy A typu array[1..N] of integer, N > 0, maksymalną sumę segmentu (spójnego fragmentu tablicy). Przyjmujemy, że segment pusty ma sumę 0.

Wskazówka 1

Rozwiązanie 1

Wskazówka 2

Rozwiązanie 2

Wskazówka 3

Rozwiązanie 3

Wskazówka 4

Rozwiązanie 4

Rozwiązanie 5

Zadanie 5 (Część wspólna zbiorów)

Dane są dwie tablice A i B typu array[1..N] of integer, N > 0. Obie są posortowane rosnąco. Należy traktując A i B jako reprezentacje dwu zbiorów wypisać (operacją write) cześć wspólną tych zbiorów.

Wskazówka 1

Rozwiązanie 1

Zadanie 6 (Suma zbiorów)

Dane są dwie tablice A i B typu array[1..N] of integer, N > 0. Obie są posortowane rosnąco. Należy traktując A i B jako reprezentacje dwu zbiorów wypisać (operacją write) sumę tych zbiorów.

Wskazówka 1

Rozwiązanie 1

Pytanko 1

Wskazówka 2

Rozwiązanie 2

Zadanie 7 (Podciąg)

Dane są dwie tablice A typu array[1..N] of integer i B typu array[1..M] of integer, N, M > 0. Napisz program sprawdzający, czy A jest podciągiem B (tzn. czy istnieje funkcja f, rosnąca, z 1..N w 1..M, t. ze A[i]=B[f(i)]).

Wskazówka 1

Rozwiązanie 1

Zadanie 8 (Odwracanie tablicy)

Dana tablica A typu array[0..N-1] of integer, N > 1. Napisz program odwracający kolejność elementów w A.

Wskazówka 1

Rozwiązanie 1

Wskazówka 2

Rozwiązanie 2

Zadanie 9 (Przesunięcie cykliczne)

Dana tablica A typu array[0..N-1] of integer, N > 1, i liczba naturalna k > 1. Napisz program realizujący przesunięcie cykliczne w prawo o k pól, czyli przesuwający zawartość pola A[i] na A[(i+k) mod N] dla każdego i < N.

Wskazówka 1

Rozwiązanie 1

Wskazówka 2

Rozwiązanie 2

Wskazówka 3

Rozwiązanie 3

Zadanie 10 (Następna permutacja)

Tablica A typu array[1..N] of integer, N > 0, zawiera pewną permutację liczb 1.. N. Napisz program wpisujący do A następną leksykograficznie permutację. Zakładamy, że permutacja w A nie jest ostatnia leksykograficznie.

Przykład Dla N=3 kolejne permutacje w porządku leksykograficznym wyglądają nastepująco:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

Wskazówka 1

Rozwiązanie 1

Zadanie 11 (Segment o danej sumie)

Tablica A typu array[1..N] of integer, N > 0, zawiera tylko liczby dodatnie. Napisz program który dla danego W typu integer sprawdza czy w A istnieje segment o sumie W (czyli czy istnieją l, p takie, że W=A[l]+...+A[p1]).

Wskazówka 1

Rozwiązanie 1

Wskazówka 2

Rozwiązanie 2

Zadanie 12 (Głosowanie większościowe)

Dana jest tablica A typu array[1..N] of integer, N > 0. Sprawdzić czy jest w niej element wystepujący więcej niż N/2 razy i jeśli tak wskaż go.

Wskazówka 1

Rozwiązanie 1

Wskazówka 2

Rozwiązanie 2

Zadanie 13 (Arytmetyka liczb wielocyfrowych)

Liczby wielocyfrowe będą reprezentowane w tablicach typu liczba=array[0..N-1] of integer, N > 1, w taki sposób, że najmniej znacząca cyfra jest pod indeksem 0. Rozpatrujemy liczby przy podstawie b > 1. Napisz procedury obliczające:

  1. sumę liczb A i B do C. Jeśli wynik nie zmieści się w C to wartość C nie ma znaczenia. Zmienna przepełnienie wskazuje czy do niego doszło czy nie.
  2. różnicę A i B do C. Jeśli wynik miałby byc liczbą ujemną to wartość C nie ma znaczenia. Zmienna ujemny wskazuje jaki jest znak wyniku.
  3. iloczyn A i B do C (C powinno być tablicą dwa razy dłuższą niż A i B, żeby móc pomieścić wynik).

Rozwiązanie 1