Corrigé
Existence
On donne trois preuves possibles
En reprenant la définition
Si la première condition (
Les deux conditions précédentes montrent qu'il existe
Une astuce
Un tableau d'entier possède forcément un élément minimum. Il existe donc
- soit
et - soit
et - soit
et
Simple et efficace, non ?
Par récurrence
On montre par récurrence sur la taille
- Initialisation. Si
soit soit (ce qui est équivalent pour à ). Ces deux cas correspondent aux deux premières possibilités pour un col - on suppose la propriété vrai pour
. Et on se donne un tableau de taille . - l'hypothèse de récurrence stipule que le tableau
constitué des premières cases de ( ) possède un col, disons à l'indice . 3 cas sont possibles : et ce qui implique : est aussi un col pour et ce qui implique : est aussi un col pour et ce qui implique . On conclut en remarquant que :- soit
et : est aussi un col pour - soit
et est un col pour .
- soit
Découverte
La preuve de la 1ère question montrant qu'il existe forcément un col, l'algorithme suivant qui mime directement la définition (lignes 2-3 : 1ère condition, lignes 5-6 : 2ème condition et lignes 8-10 la troisième condition) trouvera forcément un col :
def trouve(T):
if T[0] <= T[1]:
return 0
if T[-1] <= T[-2]:
return len(T) - 1
for i in range(1, len(T) - 1):
if T[i] <= min(T[i-1], T[i + 1]):
return i
Sa complexité dans le cas le pire a lieu pour les tableaux dont le premier et seul col se trouve à l'avant dernier indice (comme pour la liste
- faire échouer le 1er test de la ligne 2 en
opérations - faire échouer le 2er test de la ligne 5 en
opérations - faire les
itérations de la boucle for en :- faisant échouer tous les tests sauf le dernier
opérations - réussissant le dernier test et en faisant un retour de fonction en
opérations
- faisant échouer tous les tests sauf le dernier
La complexité totale maximale est alors :
On peut aussi utiliser la preuve précédente et simplifier la boucle for
en gardant la même complexité :
def trouve(T):
if T[0] <= T[1]:
return 0
if T[-1] <= T[-2]:
return len(T) - 1
for i in range(1, len(T) - 1):
if T[i] <= T[i + 1]:
return i
Rapidité
La preuve d'existence du 1 montre que pour tout
L'invariant de boucle de la boucle while
est alors :
invariant
A la fin de chaque itération de la boucle while
, soit :
T[milieu]
est un colT[milieu]
n'est pas un col et :début + 1 < fin
T[début] > T[début+1]
etT[fin] > T[fin-1]
A la fin de la première itération, on a soit :
T[milieu] <= min(T[milieu - 1], T[milieu + 1])
etmilieu
est un colfin' = milieu
etdébut' = début
siT[milieu] > T[milieu -1]
. Comme initialement0 = début + 1 < fin = len(T) - 1
on a égalementmilieu - 1 > début
puisqueT[0] > T[1]
et l'invariant est vérifié.fin' = fin
etdébut' = milieu
siT[milieu] <= T[milieu -1]
etT[milieu] > T[milieu + 1]
. Comme0 = début + 1 < fin = len(T) - 1
on a égalementmilieu + 1 < fin
puisqueT[-1] > T[-2]
et l'invariant est vérifié.
La même démonstration fonctionne à l'identique à la fin de l'itération
Comme fin - début >= 0
et diminue strictement à chaque itération de la boucle while
, il arrivera forcément un moment où milieu
sera un col.
Complexité
La procédure de la boucle while
est identique à la recherche dichotomique puisque l'on se place toujours au milieu de l'espace de recherche. Le cours nous indiquant que la complexité de la recherche dichotomique est trouve_vite(T)
est également en
Complexité du problème
Il existe des tableaux ayant tous un unique col en position
Comme l'algorithme trouve_vite(T)
est de complexité
Généralisation
Existence
Une matrice avec ses lignes croissantes et ses colonnes décroissantes n'a pas de col.
Algorithme
On peut stocker les maximaux des colonnes et les minimaux des lignes dans deux listes puis parcourir chaque élément de la matrice et vérifier s'il est égal au maximum de la colonne et au minimum de la ligne.
Optimisation impossible
L'optimisation trouve un col de ligne, mais pas forcément le bon pour la matrice.
- montrez qu'il n'existe pas forcément de col à une matrice
- donnez un algorithme linéaire en la taille de la matrice pour trouver un col s'il existe