Create an array of all id's, than generate a series of every second element of this array. Apply this only for features that intersect other features.
To do so, use this expression with select by expression:
case
when overlay_intersects(@layer)
then
array_contains(
with_variable (
'array',
array_agg( $id),
generate_series (1, array_length(@array),2)
),
$id
)
end

There might be the case that you don't have an id that follows the spatial order of your polygons. In this case, create a new field that you can use in the expression above instead of $id
. For this, first create a line layer and draw a line along the polygons in the correct order. Then on the polygon layer, create this order field using the following expression:
with_variable(
'line',
overlay_nearest ('lineorder', $geometry)[0],
array_find (
array_sort(
array_agg (
line_locate_point (
@line,
centroid ($geometry)
)
)
),
line_locate_point (
@line,
centroid ($geometry)
)
)
)
Or, without creating a separate field, use this expression directly in select by expression:
with_variable (
'order',
with_variable(
'line',
overlay_nearest ('lineorder', $geometry)[0],
array_find (
array_sort(
array_agg (
line_locate_point (
@line,
centroid ($geometry)
)
)
),
line_locate_point (
@line,
centroid ($geometry)
)
)
),
case
when overlay_intersects(@layer)
then
array_contains(
with_variable (
'array',
array_agg(@order),
generate_series (1, array_length(@array),2)
),
@order
)
end
)
Correctly selecting every second polygon even though id
(see labeled values) are in random order. The order of the polygon is createad as distance along the red line of the polygon's centroid:
