java – Is there a more optimal solution to this money change exam?

I was asked to create a method that would:

  • Return a Change object or null if there was no possible change
  • The “machine” has unlimited bills of: 2, 5 and 10
  • The Change object must return the most minimal amount of bills possible

This was a question asked in codingame.com and wanted to investigate further on it.
Here’s the code:

package com;

class Change {

    long coin2 = 0, bill5 = 0, bill10 = 0;
}

public class Test {

    static Change c = new Change();

    public static void main(String() args) {
        Change m = optimalChange(19L);

        if(m == null){
            System.out.println("no change possible ...");
            return;
        }
        
        System.out.println("Coin  2E: " + m.coin2);
        System.out.println("bill  5E: " + m.bill5);
        System.out.println("bill 10E: " + m.bill10);

        long result = m.coin2 * 2 + m.bill5 * 5 + m.bill10 * 10;

        System.out.println("Change given: " + result);
    }

    static Change optimalChange(long s) {

        if (s < 2) {
            return s == 0 ? c : null;
        } else if (s < 5) {
            c.coin2++;
            return optimalChange(s - 2);
        } else if (s < 10) {
            c.bill5++;
            return optimalChange(s - 5);
        } else {
            c.bill10++;
            return optimalChange(s - 10);
        }

    }

}

Edit 1

So I found an issue with this when s = 8, it reaches s = 3 and “fails”. But apart from this, something else to improve here?

This would be the new and “improved” code:

package moc;

class Change {

    long coin2 = 0, bill5 = 0, bill10 = 0;
}

public class Test {

    static Change c = new Change();

    public static void main(String() args) {
        Change m = optimalChange(19L);

        if (m == null) {
            System.out.println("no change possible ...");
            return;
        }

        System.out.println("Coin  2E: " + m.coin2);
        System.out.println("bill  5E: " + m.bill5);
        System.out.println("bill 10E: " + m.bill10);

        long result = m.coin2 * 2 + m.bill5 * 5 + m.bill10 * 10;

        System.out.println("Change given: " + result);
    }

    static Change optimalChange(long s) {

        if (s < 2) {
            return s == 0 ? c : null;
        } else {
            int decrementor = 0;

            if (s < 5) {
                c.coin2++;
                decrementor = 2;
            } else if (s < 10) {
                if (s % 2 != 0) {
                    c.bill5++;
                    decrementor = 5;
                } else {
                    c.coin2++;
                    decrementor = 2;
                }
            } else {
                c.bill10++;
                decrementor = 10;
            }

            return optimalChange(s - decrementor);

        }
    }

}