Запит на знаходження мінімальної суми для рівняння за заданим набором обмежень може бути ефективніше оптимізований. За введеним алгоритмом часова складність становить O(n^4 * Z_MAX^2), що може бути неприйнятно великою при значних значеннях n та Z_MAX. Одним із способів зменшення часової складності є використання підходу, який дозволяє знаходити розв’язок без перебору всіх можливих комбінацій a і b.
Замість перебору всіх можливих значень a і b можна скористатися властивостями математичного рівняння a*x + b*y = z. Зауважимо, що якщо знаємо значення змінних x і y, то можемо знайти a і b шляхом ділення z на x або y з урахуванням цілочисельного ділення. Таким чином, замість перебору всіх значень a і b, ми можемо знаходити відповідні значення a і b відразу.
Перепишемо функцію solve, використовуючи цей підхід:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public static int[] solveOptimized(int[] arr, int[] zArr, int Z_MAX) { int n = arr.length; int[] result = new int[zArr.length]; for(int i = 0; i < zArr.length; i++) { result[i] = Integer.MAX_VALUE; } for(int p = 0; p < zArr.length; p++) { int z = zArr[p]; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { int x = arr[i]; int y = arr[j]; if(x != 0 && z % x == 0) { int a = z / x; int b = (z - a * x) / y; if(b * y + a * x == z && a + b <= Z_MAX) { result[p] = Math.min(result[p], a + b); } } if(y != 0 && z % y == 0) { int b = z / y; int a = (z - b * y) / x; if(a * x + b * y == z && a + b <= Z_MAX) { result[p] = Math.min(result[p], a + b); } } } } if(result[p] > Z_MAX) { result[p] = -1; } } return result; } |
Цей підхід зменшує часову складність алгоритму до O(n^2), оскільки ми більше не перебираємо всі можливі значення a і b.
Тепер функція solveOptimized має значно меншу часову складність і здатна ефективно обробляти навіть великі вхідні дані.