To clarify, the LF (aka \n or newline) character is the line delimiter, it's not the line separator. A line is not finished unless it's terminated by a newline character. A file that only contains a\nb is not a valid text file because it contains characters after the last line. Same for a file that contains only a. A file that contains a\n contains one non-empty line.
So a file that ends with at least one empty line ends with two newline characters or contains a single newline character.
If:
tail -c 2 file | od -An -vtc
Outputs \n or \n \n, then the file contains at least one trailing empty line. If it outputs nothing, then that's an empty file, if it outputs <anything-but-\0> \n, then it ends in a non-empty line. Anything else, it's not a text file.
Now, to use that to find files that end in an empty line, OK that's efficient (especially for large files) in that it only reads the last two bytes of the files, but first the output is not easily parsable programmatically especially considering that it's not consistent from one implementation of od to the next, and we'd need to run one tail and one od per file.
find . -type f -size +0 -exec gawk '
ENDFILE{if ($0 == "") print FILENAME}' {} +
(to find files ending in an empty line) would run as few commands as possible but would mean reading the full content of all files.
Ideally, you'd need a shell that can read the end of a file by itself.
With zsh:
zmodload zsh/system
for f (**/*(D.L+0)) {
{
sysseek -w end -2
sysread
[[ $REPLY = $'\n' || $REPLY = $'\n\n' ]] && print -r -- $f
} < $f
}