情形:甲和乙有些代办事项,每一个事项都有一个开始时间,和一个截止时间。但是甲和乙的代办事项可能会出现冲突,若在一个代码事项中,存在其他代办事项,则就认为是冲突。现要求合并甲和乙的代办事项,不能够有冲突。
解决:
由于我经常用java,所以就用java模拟该问题。
定义代办事项:
public class Node
{
private int startTime;
private int endTime;
Node cNode;
}
甲和乙的代办事项已经是有序的链表
初始化甲的代办事项:
Node nodeA = new Node(1, 2);// 初始化节点A
nodeA.addNode(new Node(2, 6));
nodeA.addNode(new Node(3, 7));
nodeA.addNode(new Node(4, 9));
nodeA.addNode(new Node(7, 12));
nodeA.addNode(new Node(16, 19));
初始化乙的代办事项:
Node nodeB = new Node(2, 4);
nodeB.addNode(new Node(3, 6));
nodeB.addNode(new Node(7, 10));
nodeB.addNode(new Node(9, 15));
nodeB.addNode(new Node(18, 20));
注意:甲乙各自的代办事项中都可能存在冲突,合并后的代办事项也可能存在冲突。
基于此的话,我们考虑直接将甲和乙的代办事项合并,然后再将合并后的代办事项中冲突的事项给删除掉。
printNode(nodeA);
printNode(nodeB);
Node mergeNode=mergeWithNoSort(nodeA, nodeB);//将两个节点合并
printNode(mergeNode);
Node deleteNode=deleteNode(mergeNode);//删除节点中冲突的节点
printNode(deleteNode);
运行结果如图:
public static Node mergeWithNoSort(Node nodeA, Node nodeB)
{
Node tempNode = nodeA;
// 合并nodeA 和nodeB
// 采用插入删除,将nodeB插入到nodeA中
Node insertNode = nodeB;
while (tempNode != null)
{
if (tempNode.cNode == null)
{
if (insertNode.startTime <= tempNode.startTime)
{
Node tempInsert = insertNode;
insertNode.cNode = tempNode;
tempNode = insertNode;
insertNode = tempInsert;
break;
}
else
{
tempNode.cNode = insertNode;
return nodeA;
}
}
else
{
if (insertNode.startTime <= tempNode.startTime)
{
Node tempInsert = insertNode;
insertNode.cNode = tempNode;
tempNode = insertNode;
insertNode=tempInsert;
break;
}
else if (insertNode.startTime>tempNode.startTime&&insertNode.startTime<=tempNode.cNode.startTime)
{
Node tempInsert=insertNode.cNode;
insertNode.cNode=tempNode.cNode;
tempNode.cNode=insertNode;//巧妙利用nodeB已经是有序,少写外面一个循环
insertNode=tempInsert;
}
else {
tempNode=tempNode.cNode;
}
}
}
return nodeA;
}
删除重复节点的函数:
// 删除有冲突的节点
public static Node deleteNode(Node node)
{
Node tempNode = node;
while (tempNode!=null&&tempNode.cNode != null)
{
if (tempNode.cNode.startTime < tempNode.endTime)// 有冲突,删除节点
{
Node temp = tempNode.cNode;
tempNode.cNode = temp.cNode;
continue;
}
tempNode = tempNode.cNode;
}
return node;
}
打印节点函数:
// 打印一个节点
public static void printNode(Node node)
{
Node tempNode = node;
while (tempNode != null)
{
System.out.print("(" + tempNode.startTime + "," + tempNode.endTime
+ ")->");
tempNode = tempNode.cNode;
}
System.out.println();
}
在节点的最后一个节点添加一个节点:
// 向节点后面添加一个节点
public void addNode(Node node)
{
Node tempNode = this;
while (tempNode.cNode != null)
{
tempNode = tempNode.cNode;
}
tempNode.cNode = node;
}
其实仔细分析,这在逻辑上并不是太难。对于我一个很久没写过算法的人来说,当面试是时,没有写出来,悲剧,一面就被拒绝了,看来找工作前,一定要多写点代码,多复习数据结构啊。