You can use the lag function to refer back to a value on the previous row (defining what 'previous' means as part of the query; I've assumed your 'row number' is a pseudocolumn, not an actual column you could order by, and you want them in start-date order):
select start_date, end_date,
case
when lag_end_date is null then start_date
when lag_end_date = start_date then start_date
else lag_end_date
end as adj_start_date
from (
select start_date, end_date,
lag(end_date) over (order by start_date, end_date) as lag_end_date
from <your_table>
)
(SQL Fiddle).
The first when clause of the case is dealing with the 'first' row, with the earliest start date; since there is no previous row the lag is going to be null.
You can then filter the results to get those where start_date and adj_start_date don't match. (Another SQL Fiddle).
You can use the same kind of construct in a merge to do the update:
merge into <your table>
using (
select r_id, start_date, end_date,
case when lag_end_date is null then null
when lag_end_date = start_date then null
else lag_end_date
end as adj_start_date
from (
select rowid as r_id, start_date, end_date,
lag(end_date) over (order by start_date, end_date) as lag_end_date
from t42
)
) t
on (your_table>.rowid = t.r_id and t.adj_start_date is not null)
when matched then
update set <your table>.start_date = t.adj_start_date;
(SQL Fiddle).