$result = preg_replace('#<p[^>]*>(\s| ?)*</p>#', '', $input);
Это не перехватывает буквальные nbsp символы в выводе, но это очень редко можно увидеть.
Поскольку вы имеете дело с HTML, если это пользовательский ввод, я мог бы предложить использовать HTML Purifier, который также будет иметь дело с уязвимостями XSS. Параметр конфигурации, который вы хотите там удалить пустые теги p, это% AutoFormat.RemoveEmpty.