Предложу свой вариант. Не судите строго

алгоритмам не обучен, математику не знаю

Решение для 3-х колонок, при желании можно модифицировать для N.
Integer partSize = Integer.valueOf((Decimal.valueOf(payments.size()) / 3).round(System.RoundingMode.DOWN));
paymentsColsN = new List<Integer>{
partSize, partSize, partSize
};
for (Integer i = 0; i < payments.size() - partSize * 3; i++) {
paymentsColsN[i]++;
}
Integer n = 0;
for (Integer i = 0; i < 3; i++) {
paymentsCols.add(new List<PaymentDTO>());
for (Integer j = 0; j < paymentsColsN[i]; j++) {
Invoice_Payment__c sp = payments[n];
paymentsCols[i].add(
new PaymentDTO(sp)
);
totalPaid += sp.Amount__c;
n++;
}
}
paymentsCol1 = paymentsCols[0];
paymentsCol2 = paymentsCols[1];
paymentsCol3 = paymentsCols[2];
Предлагаю довести данный алгоритм до совершенства