If the task can be performed using native SQL then always go for it. Because SQL and PLSQl are two different languages and if you call SQL from PLSQL block then context switch(exchange of processing control between SQL and PLSQL) occurs.
So I would prefer the native SQL.
Now, you have couple of options such as-
If you are going to delete large percentage of rows from the table, keeping 1 million rows is better that deleting 2 millions rows from table having 3 millions rows,
create <new table> as select * from <old table> where <condition>, you can also use parallel here, drop old table, rename to , create necessary indexes in parallel.
Down side of this method is that other session can't use this table during the operation.
Another method is to partition the table then drop the unnecessary partitions.
Note: If you still want to do it with PLSQl(for concurrency) then instead of deleting one by one, you can use BULK DELETE.