@Override
    public double findMin(double leftBound, double rightBound, double L, double epsilon) {
        resetCounter();
        List<Double> y = new ArrayList<>();
        int sizeFz = 3;
        y.add(leftBound);
        y.add((leftBound + rightBound) / 2);
        y.add(rightBound);

        List<Double> z = new ArrayList<>();
        List<Double> fz = new ArrayList<>();

        z.add(minorantZ0(y.get(0), y.get(1), L));
        fz.add(minorantZF0(z.get(0), y.get(0), L));

        z.add(minorantZ0(y.get(1), y.get(2), L));
        fz.add(minorantZF0(z.get(1), y.get(1), L));

        int i;
        double min;

        do {
            min = fz.get(0);
            int iMin = 0;

            y.add(0.0);
            z.add(0.0);
            fz.add(0.0);

            for (int k = 1; k < sizeFz; k++) {
                if (min > fz.get(k)) {
                    min = fz.get(k);
                    iMin = k;
                }
            }
            i = 1;
            while (y.get(i) < z.get(iMin) && i < y.size() - 2) {
                i++;
            }

            for (int k = sizeFz - 1; k >= i; k--) {
                y.set(k + 1, y.get(k));
            }

            y.set(i, z.get(iMin));

            z.set(iMin, minorantZ0(y.get(i - 1), y.get(i), L));
            fz.set(iMin, minorantZF0(z.get(iMin), y.get(i - 1), L));

            z.set(sizeFz - 1, minorantZ0(y.get(i), y.get(i + 1), L));
            fz.set(sizeFz - 1, minorantZF0(z.get(sizeFz - 1), y.get(i), L));

            sizeFz++;
            countIter++;
        } while (function.calculate(y.get(i)) - min >= epsilon);

        countCalc = function.getCountCalc();
        return y.get(i);
    }