将链表分成2个具有相等总和的子列表

时间:2014-05-05 15:03:40

标签: algorithm data-structures linked-list pseudocode partition-problem

我正在尝试将一个链表分成两个具有相等总和的子列表。这些子列表不需要由连续元素组成。

我有一个链接列表

Eg.1
LinkedList={1,7,5,5,4}
should be divided into
LinkedList1={1,5,5}
LinkedList2={7,4}

两者都具有与11相同的元素总和。

Eg.2
LinkedList={42,2,3,2,2,2,5,20,2,20}
This should be divided into two list of equal sum i.e 50.
LinkedList1={42,3,5}
LinkedList2={2,2,2,2,20,2,20}

有人可以提供一些伪代码来解决这个问题吗?

这是我到目前为止所想的:

  1. 对链表的元素求和并除以2.

  2. 现在直到你的linkedlist1的总和小于linkedlist / 2的总和,继续将元素推送到linkedlist1。

  3. 如果不相等且小于linkedlist sum / 2移动到下一个元素,则当前元素可以推送到linkedlist2。

  4. 但这只有在元素按特定顺序排列时才有效。

1 个答案:

答案 0 :(得分:1)

这称为the partition problem

有几种方法可以解决这个问题,但我只会提到下面最常见的2(有关这两种方法或其他方法的详细信息,请参阅Wikipedia。)


这可以通过dynamic programming方法解决,该方法基本上归结为每个元素和值,包括或排除该元素,并查找是否存在与相应值相加的子集。更具体地说,我们有以下递归关系:

  如果p(i, j)的子集总和为True{ x1, ..., xj },则

iFalse

     如果p(i, j)Truep(i, j − 1)True,则

p(i − xj, j − 1)True       p(i, j)False否则

然后p(N/2, n)告诉我们是否存在子集。

运行时间为O(Nn),其中n是输入集中元素的数量,N是输入集中元素的总和。


“近似”贪婪方法(不一定找到等和分区)非常直接 - 它只涉及将每个元素放入具有最小和的集合中。这是伪代码:

INPUT:  A list of integers S
OUTPUT: An attempt at a partition of  S into two sets of equal sum
1  function find_partition( S ):
2     A ← {}
3     B ← {}
4     sort  S in descending order
5     for i in S:
6        if sum(A) <= sum(B)
7           add element i to set A
8        else
9           add element i to set B
10    return {A, B}

运行时间为O(n log n)