David Aldridge correctly points out that querying all_tables could give incorrect results due to missing or stale table statistics. But there is also a problem with using user_segments; Deleted blocks beneath the high water mark would still be counted for the size of the table.
Example:
SQL>create table t as select * from all_objects
Table created.
SQL>select blocks, bytes from user_segments where segment_name = 'T';
BLOCKS BYTES
768 6291456
SQL>delete from t
52676 rows deleted.
SQL>commit;
Commit complete.
SQL>select count(*) from t;
COUNT(*)
0
SQL>select blocks, bytes from user_segments where segment_name = 'T';
BLOCKS BYTES
768 6291456
SQL>truncate table t;
Table truncated.
SQL>select blocks, bytes from user_segments where segment_name = 'T';
BLOCKS BYTES
8 65536