# exercice: guess
# default_start
def mystere(values, target):
start = 0
end = values.size() - 1
found = False
while start <= end and not found:
middle = (start + end) // 2
middle_value = values[middle]
if middle_value == target:
found = True
elif middle_value < target:
start = middle + 1
else:
end = middle - 1
return found
# default_end
# test_start
print(mystere(Array([1, 3, 7, 14, 28, 34, 45, 51]), 67))
# test_endExercices
1 Exercice 1
Difficulté :
Comprendre
Quelle est la sortie de ce programme ?
# exercice: show
# default_start
def mystere(values, target): # values=Array([1,3,7,14,28,34,45,51]), target=67
start = 0 # start=0
end = values.size() - 1 # end=7
found = False # found=False
while start <= end and not found: # 0<=7 and True 4<=7 and True 6<=7 and True 7<=7 and True 8<=8
middle = (start + end) // 2 # middle=3 middle=5 middle=6 middle=7
middle_value = values[middle] # middle_value=14 middle_value=34 middle_value=45 middle_value=51
if middle_value == target: # 14==67 34==67 45==67 51==67
found = True #
elif middle_value < target: # 14<67 34<67 45<67 51<67
start = middle + 1 # start=4 start=6 start=7 start=8
else: # 14>67 34>67 45>67
end = middle - 1 #
return found # False
print(mystere(Array([1, 3, 7, 14, 28, 34, 45, 51]), 67))
# default_endAnalyser
Quelle est la complexité en temps de la fonction mystere ?
# exercice: show
# default_start
def mystere(items):
start = 0 # 1 affectation
end = values.size() - 1 # 1 affectation + 1 soustraction
found = False # 1 affectation
# log2(items.size()) iterations jusqu'à ce que start > end (voir démonstration ci-dessous)
while start <= end: # 1 comparaison
middle = (start + end) // 2 # 1 affectation + 1 addition + 1 division
middle_value = values[middle] # 1 affectation
if middle_value == target: # 1 comparaison
found = True # 1 affectation
elif middle_value < target: # 1 comparaison
start = middle + 1 # 1 affectation + 1 soustraction
else: # 1 comparaison
end = middle - 1 # 1 affectation + 1 soustraction
return found # 1 affectation
# n = items.size()
# T(n) = 1 + 2 + 1 + log2(n) * (1 + 3 + 1 + max(2, 4, 4)) + 1
# T(n) = 4 + log2(n) * (5 + 4) + 1
# T(n) = 9log2(n) + 5
# T(n) => O(logn)
# default_endL’algorithme ci-dessus divise la taille du tableau par deux à chaque iteration. En effet, La longueur de la partie du tableau comprise entre \(start\) et \(end\) est d’abord \(n\), puis \(n/2\), puis \(n/4\), puis \(n/8\), …, jusqu’à ce que \(n/2^t = 1\).
- Le nombre d’itérations est donc un entier \(t\) tel que \(n/2^t = 1\).
- A ce stade il est nécessaire d’introduire une nouvelle notion mathématique : le “logarithme base 2” noté \(log2\). Par définition, \(log2(2^x)=x\).
- On a donc:
\[n/2^t = 1\] \[2^t = n\] \[log_2(2^t) = log_2(n)\] \[t = log_2(n)\]
2 Exercice 2
Difficulté :
Concevoir
Écrire une fonction \(sort(array)\) qui prend en paramètre un tableau \(array\) et retourne un nouveau tableau contenant les valeurs du tableau \(array\) ordonnées par ordre croissant.
Exemple d’utilisation :
- \(sort(Array([8, 14, 7]))\) retourne \(Array([7, 8, 14])\)
- \(sort(Array([ 0, 2, 47, 5, -5]))\) retourne \(Array([-5, 0, 2, 5, 47])\)
Votre réponse
# exercice: design
# default_start
def sort(array):
return None
# default_end
# test_start
print(sort(Array([8, 14, 7])))
print("C683AKRMaR")
print(sort(Array([0, 2, 47, 5, -5])))
# test_end
# solution_start
# SELECTION SORT -> worst: O(n²), best: O(n²) [Algorithme lent]
def selectionSort(array):
n = array.size()
i = 0
while i < n - 1:
min_i = i
j = i
while j < n:
if array[j] < array[min_i]:
min_i = j
j = j + 1
if min_i != i:
tmp = array[min_i]
array[min_i] = array[i]
array[i] = tmp
i = i + 1
return array
# BUBBLE SORT -> worst: O(n²), best: O(n) [Algorithme moyennement rapide]
def bubbleSort(array):
i = 0
while i < array.size():
j = 0
while j < array.size() - i - 1:
if array[j] > array[j + 1]:
tmp = array[j]
array[j] = array[j + 1]
array[j + 1] = tmp
j = j + 1
i = i + 1
return array
# INSERTION SORT -> worst: O(n²), best: O(n) [Algorithme moyennement rapide]
def insertionSort(array):
i = 1
while i < array.size():
key = array[i]
j = i - 1
while j >= 0 and key < array[j]:
array[j + 1] = array[j]
j = j - 1
array[j + 1] = key
i = i + 1
return array
# MERGE SORT -> worst: O(nlogn), best: O(nlogn) [Algorithme rapide]
def slicing(array1, start, end):
new_size = end - start
new_arr = Array([0] * new_size)
i = 0
while i < new_size:
new_arr[i] = array1[start + i]
i = i + 1
return new_arr
def concatenate(array1, array2):
new_size = array1.size() + array2.size()
new_arr = Array([0] * new_size)
i = 0
while i < array1.size():
new_arr[i] = array1[i]
i = i + 1
i = 0
while i < array2.size():
new_arr[array1.size() + i] = array2[i]
i = i + 1
return new_arr
def merge(array1, array2):
new_size = array1.size() + array2.size()
new_arr = Array([0] * new_size)
i = 0
j = 0
k = 0
while i < array1.size() and j < array2.size():
if array1[i] <= array2[j]:
new_arr[k] = array1[i]
i = i + 1
k = k + 1
else:
new_arr[k] = array2[j]
j = j + 1
k = k + 1
new_arr = slicing(new_arr, 0, k)
new_arr = concatenate(new_arr, slicing(array1, i, array1.size()))
new_arr = concatenate(new_arr, slicing(array2, j, array2.size()))
return new_arr
def mergeSort(array):
ans = array
if array.size() > 1:
mid_size = array.size()//2
left_arr = slicing(array, 0, mid_size)
right_arr = slicing(array, mid_size, array.size())
ans = merge(mergeSort(left_arr), mergeSort(right_arr))
return ans
def sort(array):
return mergeSort(array)
# solution_end3 Exercice 3
Difficulté :
Concevoir
Écrire une fonction \(getMaximumSubarraySum(array)\) qui prend en paramètre un tableau \(array\) et retourne la somme maximale parmi tous les sous-tableaux possibles de \(array\).
La fonction doit prendre en compte que le sous-tableau peut être constitué d’un seul élément dans le cas où tous les éléments sont négatifs, ou bien il peut s’agir de la totalité du tableau si cela maximise la somme.
Exemple d’utilisation :
- \(getMaximumSubarraySum(Array([0, 2, 47, 5, -5]))\) retourne \(54\) car \(Array([0, 2, 47, 5])\) est le sous-tableau avec la somme maximale.
- \(getMaximumSubarraySum(Array([1, 2, 3, -2, 5]))\) retourne \(9\) car \(Array([1, 2, 3, -2, 5])\) est le sous-tableau avec la somme maximale.
- \(getMaximumSubarraySum(Array([-1, -2, -3, -4]))\) retourne \(-1\) car \(Array([-1])\) est le sous-tableau avec la somme maximale.
- \(getMaximumSubarraySum(Array([5, 4, 7]))\) retourne \(16\) car \(Array([5, 4, 7])\) est le sous-tableau avec la somme maximale.
- \(getMaximumSubarraySum(Array([8, -14, 7]))\) retourne \(8\) car \(Array([8])\) est le sous-tableau avec la somme maximale.
Votre réponse
# exercice: design
# default_start
def getMaximumSubarraySum(array):
return None
# default_end
# test_start
print(getMaximumSubarraySum(Array([0, 2, 47, 5, -5])))
print("C683AKRMaR")
print(getMaximumSubarraySum(Array([1, 2, 3, -2, 5])))
print("C683AKRMaR")
print(getMaximumSubarraySum(Array([-1, -2, -3, -4])))
print("C683AKRMaR")
print(getMaximumSubarraySum(Array([5, 4, 7])))
print("C683AKRMaR")
print(getMaximumSubarraySum(Array([8, -14, 7])))
# test_end
# solution_start
# SOLUTION 1 : Force brute => O(n**3)
def getSubarraySum(array, start, end):
res = 0
i = start
while i < end:
res = res + array[i]
i = i + 1
return res
def getMaximumSubarraySum(array):
i = 0
maxSubarraySum = getSubarraySum(array, 0, 1)
while i < array.size():
j = i
while j < array.size():
subarraySum = getSubarraySum(array, i, j + 1)
if subarraySum > maxSubarraySum:
maxSubarraySum = subarraySum
j = j + 1
i = i + 1
return maxSubarraySum
# SOLUTION 2 : Algorithme de Kadane => OPTIMAL => O(n)
def maximum(a, b):
res = a
if b > a:
res = b
return res
def getMaximumSubarraySum(array):
best_sum = array[0]
current_sum = 0
i = 0
while i < array.size():
current_sum = maximum(array[i], current_sum + array[i])
best_sum = maximum(best_sum, current_sum)
i = i + 1
return best_sum
# solution_end4 Exercice 4
Difficulté :
Concevoir
Écrire une fonction \(getEquilibriumIndex(array)\) qui prend en paramètre un tableau d’entiers \(array\) et retourne un indice d’équilibre (s’il existe) ou \(-1\) s’il n’existe pas d’indice d’équilibre.
L’indice d’équilibre d’un tableau est un indice tel que la somme des éléments situés à des indices inférieurs est égale à la somme des éléments situés à des indices supérieurs.
Exemple d’utilisation :
- \(getEquilibriumIndex(Array([-7, 1, 5, 2, -4, 3, 0]))\) retourne \(3\).
- \(getEquilibriumIndex(Array([1, 3, 3, 2, 2]))\) retourne \(2\).
- \(getEquilibriumIndex(Array([8, 4, 3, 1, 4]))\) retourne \(1\).
- \(getEquilibriumIndex(Array([1, 1, 1, 1]))\) retourne \(-1\).
- \(getEquilibriumIndex(Array([1, 2, 3]))\) retourne \(-1\).
Votre réponse
# exercice: design
# default_start
def getEquilibriumIndex(array):
return None
# default_end
# test_start
print(getEquilibriumIndex(Array([-7, 1, 5, 2, -4, 3, 0])))
print("C683AKRMaR")
print(getEquilibriumIndex(Array([1, 3, 3, 2, 2])))
print("C683AKRMaR")
print(getEquilibriumIndex(Array([8, 4, 3, 1, 4])))
print("C683AKRMaR")
print(getEquilibriumIndex(Array([1, 1, 1, 1])))
print("C683AKRMaR")
print(getEquilibriumIndex(Array([1, 2, 3])))
# test_end
# solution_start
# SOLUTION 1: force brute => O(n²)
def getEquilibriumIndex(array):
i = 1
equilibrium_index = -1
while i < array.size() and equilibrium_index == -1:
left_sum = 0
j = 0
while j < i:
left_sum = left_sum + array[j]
j = j + 1
right_sum = 0
k = i + 1
while k < array.size():
right_sum = right_sum + array[k]
k = k + 1
if left_sum == right_sum:
equilibrium_index = i
i = i + 1
return equilibrium_index
# SOLUTION 2: Optimale => O(n)
def getSum(array):
res = 0
i = 0
while i < array.size():
res = res + array[i]
i = i + 1
return res
def getEquilibriumIndex(array):
total_sum = getSum(array)
left_sum = 0
i = 0
equilibrium_index = -1
while i < array.size() and equilibrium_index == -1:
right_sum = total_sum - array[i] - left_sum
if left_sum == right_sum:
equilibrium_index = i
left_sum = left_sum + array[i]
i = i + 1
return equilibrium_index
# solution_end# default_start
print("Hello World!")
# default_end