Проблема в том, что вы перебираете коллекцию узлов и в некоторых случаях удаляете фактический элемент из коллекции внутри рекурсивного вызова. Вместо этого вы можете вернуть логический флаг из рекурсивного вызова, чтобы обозначить, что фактический элемент должен быть удален, а затем удалить его с помощью Iterator.remove()
(вам нужно изменить цикл foreach на цикл итератора, чтобы сделать это возможным).
Заменить фактический элемент его единственным подузлом сложнее - вы можете определить собственный класс, который будет возвращать больше информации из рекурсивного вызова метода, но он начинает становиться неловким. Или вы можете рассмотреть возможность замены рекурсивного вызова циклом, например, с помощью стек.