You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala技术需求:实现列表无重复拆分指定最大长度子列表的算法

Got it, let's tackle this problem step by step. The core issue here is generating unique set partitions of your order list, where each partition (trolley) has a maximum size N, and neither the order of trolleys nor the order of items inside a trolley matters. Let's break down why your initial approaches fall short, then build an efficient solution.


Understanding the Problem

First, let's formalize the requirements to avoid ambiguity:

  • Split the input order list into disjoint subsets (trolleys), each with size ≤ N
  • Subsets are unordered (e.g., List(1,2)+List(3,4) is identical to List(3,4)+List(1,2))
  • Items within subsets are unordered (e.g., List(2,1) is the same as List(1,2))
  • Optional: Generate only solutions with the minimum number of trolleys (as in your supplementary example)

Why Your Initial Approaches Have Issues

Let's break down the flaws in your first two attempts:

  • Permutations + Grouped: This generates tons of redundant results because permutations account for item order, which we don't care about. You end up with identical partitions just reordered, wasting computation and requiring post-filtering.
  • Nested Combinations + Filter: While correct for small lists, it's inefficient for larger datasets. The nested combinations generate many invalid intermediate results (e.g., overlapping subsets) that you have to filter out, which scales poorly as the order list grows.

Efficient Solution: Recursive Partitioning with Duplicate Avoidance

The key to avoiding duplicates is to fix the first element of the remaining list in the current subset. This ensures we never generate permutations of the same partition (since we always build subsets starting with the smallest remaining element, eliminating reorderings of trolleys or items).

1. Generate All Valid Partitions (Any Number of Trolleys)

This function will generate every possible valid partition where each trolley holds ≤ N items, with no duplicates:

def findAllValidPartitions(orders: List[Int], maxTrolleySize: Int): List[List[Set[Int]]] = {
  def helper(remaining: List[Int]): List[List[Set[Int]]] = remaining match {
    case Nil => List(Nil)
    case head :: tail =>
      // Generate all possible subsets starting with `head` (to avoid duplicates)
      // Subset size ranges from 1 to min(maxTrolleySize, remaining.length)
      (1 to Math.min(maxTrolleySize, remaining.length)).flatMap { subsetSize =>
        tail.combinations(subsetSize - 1).map { combo =>
          val currentTrolley = (head :: combo).toSet
          helper(tail.filterNot(combo.contains)).map(currentTrolley :: _)
        }
      }.toList
  }

  helper(orders.sorted) // Sort first to ensure consistent starting element
}

2. Generate Partitions with Minimum Trolleys

To get only the solutions with the least number of trolleys (as in your supplementary example), we first calculate the minimum required trolleys, then filter results to only include partitions of that size:

def findMinTrolleyPartitions(orders: List[Int], maxTrolleySize: Int): List[List[Set[Int]]] = {
  val totalOrders = orders.length
  val minTrolleys = Math.ceil(totalOrders.toDouble / maxTrolleySize).toInt

  def helper(remaining: List[Int]): List[List[Set[Int]]] = remaining match {
    case Nil => List(Nil)
    case head :: tail =>
      // Prioritize largest possible subsets to reach min trolley count
      val maxPossibleSubsetSize = Math.min(maxTrolleySize, remaining.length)
      // Subset size starts from maxPossible down to the minimum needed to reach minTrolleys
      val minRequiredSubsetSize = remaining.length - (minTrolleys - 1) * maxTrolleySize
      (minRequiredSubsetSize to maxPossibleSubsetSize).flatMap { subsetSize =>
        tail.combinations(subsetSize - 1).map { combo =>
          val currentTrolley = (head :: combo).toSet
          helper(tail.filterNot(combo.contains)).map(currentTrolley :: _)
        }
      }.toList
  }

  helper(orders.sorted).filter(_.length == minTrolleys)
}

Testing the Examples

Example 1: N=2, Orders = List(1,2,3,4)

val orders1 = List(1,2,3,4)
findMinTrolleyPartitions(orders1, 2)

Output (formatted for readability):

List(
  List(Set(1,2), Set(3,4)),
  List(Set(1,3), Set(2,4)),
  List(Set(1,4), Set(2,3))
)

This matches your expected result exactly.

Supplementary Example: N=3, Orders = List(1,2,3,4,5)

val orders2 = List(1,2,3,4,5)
findMinTrolleyPartitions(orders2, 3)

Output (formatted):

List(
  List(Set(1,2,3), Set(4,5)),
  List(Set(1,2,4), Set(3,5)),
  List(Set(1,2,5), Set(3,4)),
  List(Set(1,3,4), Set(2,5)),
  List(Set(1,3,5), Set(2,4)),
  List(Set(1,4,5), Set(2,3))
)

This includes all unique minimal partitions, with no duplicates from reordered items or trolleys.


Key Optimizations
  • Duplicate Avoidance: By always starting subsets with the smallest remaining element, we eliminate all redundant permutations of partitions.
  • Efficiency: We avoid generating invalid or redundant intermediate results, making this solution scale much better than nested combinations or permutations.
  • Min Trolley Focus: When targeting minimal partitions, we only generate subsets that can lead to the required minimum trolley count, skipping unnecessary smaller subsets.

内容的提问来源于stack exchange,提问作者Meiko Rachimow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:48:23