private void dfsRemoveNodeReplica(
      int index,
      int currentMaxGlobalLoad,
      int currentScatter,
      int[] currentAssignment,
      int[] additionalLoad) {
    // Compute the maximum global load and maximum database load among all nodes that received
    // additional load.
    int[] currentMetrics = getCurrentMetrics(additionalLoad, currentScatter, currentAssignment);
    // Lexicographically compare currentMetrics with bestMetrics.
    // If currentMetrics is better than bestMetrics, update bestMetrics and clear the candidate
    // buffer.
    boolean isBetter = false;
    boolean isEqual = true;
    for (int i = 0; i < 3; i++) {
      if (currentMetrics[i] < bestMetrics[i]) {
        isBetter = true;
        isEqual = false;
        break;
      } else if (currentMetrics[i] > bestMetrics[i]) {
        isEqual = false;
        break;
      }
    }
    if (!isBetter && !isEqual) {
      return;
    }

    if (index == dfsRegionKeys.size()) {
      if (isBetter) {
        bestMetrics[0] = currentMetrics[0];
        bestMetrics[1] = currentMetrics[1];
        bestMetrics[2] = currentMetrics[2];
        System.arraycopy(currentAssignment, 0, bestAssignment, 0, dfsRegionKeys.size());
      }
      return;
    }

    // Process the region at the current index.
    TConsensusGroupId regionId = dfsRegionKeys.get(index);
    List<Integer> candidates = allowedCandidatesMap.get(regionId);
    for (Integer candidate : candidates) {
      currentAssignment[index] = candidate;
      currentScatter += scatterDelta[index][currentAssignment[index]];
      additionalLoad[candidate]++;
      int nextMaxGlobalLoad =
          Math.max(currentMaxGlobalLoad, regionCounter[candidate] + additionalLoad[candidate]);

      dfsRemoveNodeReplica(
          index + 1, nextMaxGlobalLoad, currentScatter, currentAssignment, additionalLoad);
      // Backtrack
      additionalLoad[candidate]--;
      currentScatter -= scatterDelta[index][currentAssignment[index]];
    }
  }
DFS method that searches for migration target assignments.

<p>It enumerates all possible assignments (one candidate for each region) and collects
candidate solutions in the optimalAssignments buffer. The evaluation metrics for each complete
assignment (i.e. when index == regionKeys.size()) are:

<p>1. Max global load: the maximum over nodes of (regionCounter[node] + additionalLoad[node])
2. Max database load: the maximum over nodes of (databaseRegionCounter[node] +
additionalLoad[node]) 3. Scatter value: computed per region, summing the combinationCounter for
every pair in the complete replica set. The complete replica set for a region includes nodes in
its remain replica set plus the newly assigned node.

<p>The candidates are compared lexicographically (first by global load, then by database load,
then by scatter). When a better candidate is found, the optimalAssignments buffer is cleared
and updated; if the new candidate matches the best found metrics, it is added to the buffer.

<p>DFS search is pruned if the optimalAssignments buffer reaches CAPACITY.

@param index Current DFS level, corresponding to regionKeys.get(index)
@param currentMaxGlobalLoad The maximum global load across all data nodes.
@param currentScatter The scatter value for the complete assignment.
@param currentAssignment Current partial assignment; its length equals the number of regions.
@param additionalLoad Extra load currently assigned to each node.
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/balancer/region/GreedyCopySetRegionGroupAllocator.java