docs: protected List<SparseItemset> frequentItemsetsSparse(List<SparseItemset> candidates, Relation<BitVector> relation, int needed, DBIDs ids, ArrayModifiableDBIDs survivors, int length) {
      // Current search interval:
      int begin = 0, end = candidates.size();
      int[] scratchi = new int[length], iters = new int[length];
      SparseItemset scratch = new SparseItemset(scratchi);
      for(DBIDIter iditer = ids.iter(); iditer.valid(); iditer.advance()) {
        BitVector bv = relation.get(iditer);
        if(!initializeSearchItemset(bv, scratchi, iters)) {
          continue;
        }
        int lives = 0;
        while(begin < end) {
          begin = binarySearch(candidates, scratch, begin, end);
          if(begin > 0) {
            candidates.get(begin).increaseSupport();
            ++lives;
          }
          else {
            begin = (-begin) - 1;
          }
          if(begin >= end || !nextSearchItemset(bv, scratchi, iters)) {
            break;
          }
        }
        for(Itemset candidate : candidates) {
          if(candidate.containedIn(bv)) {
            candidate.increaseSupport();
            ++lives;
          }
        }
        if(lives > length) {
          survivors.add(iditer);
        }
      }
      // Retain only those with minimum support:
      List<SparseItemset> frequent = new ArrayList<>(candidates.size());
      for(Iterator<SparseItemset> iter = candidates.iterator(); iter.hasNext();) {
        final SparseItemset candidate = iter.next();
        if(candidate.getSupport() >= needed) {
          frequent.add(candidate);
        }
      }
      return frequent;
    }