Java 合并两个索引列表以在其他两个列表之间创建1-1映射
我们将从这个例子开始 我有两份清单:Java 合并两个索引列表以在其他两个列表之间创建1-1映射,java,algorithm,combinations,indices,Java,Algorithm,Combinations,Indices,我们将从这个例子开始 我有两份清单: segments = [16, 19, 22, 26] labels = [horse, cow, mule] 这两个列表有一个优先顺序,优先选择另一个列表中的某些元素,如下表所示。请注意,一个段可以认为它应该有一个特定的标签,而相应的标签不认为它应该有该段 | Preferred Label | Preferred Segment | (in order, L -> R)
segments = [16, 19, 22, 26]
labels = [horse, cow, mule]
这两个列表有一个优先顺序,优先选择另一个列表中的某些元素,如下表所示。请注意,一个段可以认为它应该有一个特定的标签,而相应的标签不认为它应该有该段
| Preferred Label | Preferred Segment
| (in order, L -> R) | (in order, L -> R)
---+------------------- ------+-------------------
16 | horse, cow, mule horse | 26, 19, 22, 16
19 | horse, mule cow | 16, 22, 19
22 | mule, cow, horse mule | 26, 22, 19
26 | mule
可以用两个索引列表的形式表示:
// We have 4 segments, each have a ranked list (length 0-3) of preferred label
labelIndicesForSegments = [[0, 1, 2], [0, 2], [2, 1, 0], [2]]
// We have 3 labels, each have a ranked list (length 0-4) of preferred segment
segmentIndicesForLabels = [[3, 1, 2, 0], [0, 2, 1], [3, 2, 1]]
现在,如何在线段和标签之间创建“最佳1:1映射”?即,段在其表中得到尽可能向左的标签,反之亦然。即使片段和标签在其首选项列表中彼此不存在,该算法也应强制成对(但是,应尽可能避免这种情况)
我不知道上面这个例子的最佳答案是什么。一些答案可能是
1: [(16, horse), (19, mule), (22, cow)]
2: [(16, cow), (19, horse), (26, mule)]
3: [(19, horse), (22, cow), (26, mule)]
但是,如果没有匹配的标签,我如何选择哪个片段?我如何计算哪一个是最佳的
正如你所看到的,几乎每件事都会有所不同。线段和标签不必等长,索引列表也不必等长。虽然算法速度总是很重要,但我可以说,在这种情况下,我不会在片段或标签中处理超过10-20个元素
我的问题是我没有解决这个问题的切入点。很可能有一种算法可以解决这个问题,但我不知道它的名字。我也在用Java实现它,以防您想制作一个具体的非伪代码示例;) 这个问题被称为稳定婚姻问题 解决此问题的算法的思想是,每个分段将依次分配给其首选项列表中尚未分配给其首选分段的下一个标签 这将收敛到最佳匹配(请注意,可以有多个) 下面是一个java示例(我没有对它进行太多测试,使用风险自负;)
类SMP{
静态int[]段={16,19,22,26};
静态字符串[]标签={“马”、“牛”、“骡”};
静态int[]labelIndicesForSegments={{0,1,2},{0,2},{2,1,0},{2};
静态int[][]segmentIndicatesForLabels={{3,1,2,0},{0,2,1},{3,2,1};
静态int[]匹配=新int[segments.length];
static int[]nextLabel=new int[segments.length];//指向每个段要测试的下一个标签的简单指针(在其自己的首选项列表中的当前位置)
公共静态void main(字符串[]args){
//初始化所有匹配
对于(int i=0;iIt不清楚您需要完成什么。请发布您的样本的预期答案和解释。我将创建一个包含首选项总和的表,然后为每行选择具有更高首选项总和的元素。希望这有帮助!如果片段和实验室之间存在一对一的对应关系els,那么您能解释SegmentIndicatesForLabels第一个元素如何包含段3吗?labelIndicesForSegments中的元素3只包含2的索引。那么,SegmentIndicatesForLabels中的元素2不应该只包含2和1吗?同样,SegmentIndicatesForLabels中的元素1不应该包含元素1,因为1不出现在labelI中NDICESFOR该元素的分段。如果这不正确,那么您可以编辑问题并更好地解释问题。我已经更新了问题以澄清许多事情。希望现在它应该更容易理解。@BobBryan 1-1通信从一开始就不需要存在,但如果出现这种情况,可以强制执行。好的。That有助于澄清一些问题。我想知道您的输入是什么样子的。它可能是一个段列表,其中包含每个段的标签列表,以及一个段列表,其中包含这些段的标签列表?至于输出容器,您希望稍后如何处理这些数据?一次全部还是随机访问?当y你说“我如何计算哪一个是最理想的?”-你是什么意思?你是指标签数量最少的部分吗?
class SMP {
static int[] segments = {16, 19, 22, 26};
static String[] labels = {"horse", "cow", "mule"};
static int[][] labelIndicesForSegments = {{0, 1, 2}, {0, 2}, {2, 1, 0}, {2}};
static int[][] segmentIndicesForLabels = {{3, 1, 2, 0}, {0, 2, 1}, {3, 2, 1}};
static int[] matching = new int[segments.length];
static int[] nextLabel = new int[segments.length]; // A simple pointer to the next label to test for each segment (the current position in its own preference list)
public static void main(String[] args) {
// initialize all matchings
for (int i=0; i<matching.length; i++) {
matching[i] = -1;
nextLabel[i] = 0;
}
// While there is at least one free label and one free segment
while (canEnhance()) {
int unmatched = findUnmatchedSegment(); // Pick an unmatched segment
int label = labelIndicesForSegments[unmatched][nextLabel[unmatched]];
nextLabel[unmatched]++;
int matchedSegment = getMatchedSegment(label);
if (matchedSegment == -1) { // The label is not matched
matching[unmatched] = label;
} else {
if (labelPrefersSegment(label, matchedSegment, unmatched)) {
matching[unmatched] = label;
matching[matchedSegment] = -1;
}
}
for (int i = 0; i < matching.length; i++) {
if (matching[i] != -1)
System.out.println("Segment "+segments[i]+" matched with label "+labels[matching[i]]);
}
System.out.println("-----");
}
for (int i = 0; i < matching.length; i++) {
if (matching[i] != -1)
System.out.println("Segment "+segments[i]+" matched with label "+labels[matching[i]]);
}
}
public static boolean labelPrefersSegment(int label, int currentSegment, int newSegment) {
int[] preferenceList = segmentIndicesForLabels[label];
for (int i = 0; i < preferenceList.length; i++) {
if (preferenceList[i] == currentSegment) return false;
if (preferenceList[i] == newSegment) return true;
}
return false;
}
public static int getMatchedSegment(int label) {
for (int i=0; i<matching.length; i++) {
if (matching[i] == label) return i;
}
return -1;
}
public static int findUnmatchedSegment() {
for (int i=0; i<matching.length; i++) {
// The segment need to be free and to still have labels to test
if (matching[i] == -1 && nextLabel[i] < labelIndicesForSegments[i].length) {
return i;
}
}
return -1;
}
public static boolean canEnhance() {
return findUnmatchedSegment() != -1;
}
}