程序运行截图:
public class Node {
public static final int HEAD = 0X66;
public int value;
public int count;
public Node preNode;
public Node nextNode;
public Node() {}
public Node(int value,Node nextNode) {
this.value = value;
this.nextNode = nextNode;
}
}
package algorithm2;
public class Algorithm2 {
/*
* [删除链表中重复的结点]
*
* [题目] 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
* 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
*
* [解析] 主要考代码的能力,注意边界条件的考虑,指针判空等。
*/
public static void main(String[] args) {
Node testNode = createTestLinked();
printNode(testNode);
testNode = filterNode(testNode);
printNode(testNode);
}
/**
* 创建测试链表
* 为了方便最后返回链表头指针,我给链表创建了一个 HEAD 节点->
* 这样不管后面的节点如何变动,我只要保证结果链表的结果正确,并且与 HEAD 节点依然链接在一起就好了
* @return
*/
private static Node createTestLinked() {
Node node5 = new Node(5, null);
Node node4_2 = new Node(4, node5);
Node node4_1 = new Node(4, node4_2);
Node node3_2 = new Node(3, node4_1);
Node node3_1 = new Node(1, node3_2);
Node node2 = new Node(2, node3_1);
Node node1 = new Node(2, node2);
node5.preNode = node5;
node4_2.preNode = node4_1;
node4_1.preNode = node3_2;
node3_2.preNode = node3_1;
node3_1.preNode = node2;
node2.preNode = node1;
Node headNode = new Node(Node.HEAD, node1);
node1.preNode = headNode;
return headNode;
}
/**
* 打印链表,不打印 HEAD 节点
* @param node
*/
private static void printNode(Node node) {
Node preNode = node.nextNode;
StringBuilder sb = new StringBuilder();
sb.append(preNode.value + ":: count = " + preNode.count + "-> ");
while (preNode.nextNode != null) {
sb.append(preNode.nextNode.value + ":: count = " + preNode.nextNode.count + "-> ");
preNode = preNode.nextNode;
}
System.out.println(sb.toString());
}
/**
* 删除重复节点的方法,可惜的是这个方法的时间复杂度是 O(n^2)
*
* 其实还有一种有缺陷的思路 ->
* 那就类似于桶排序的思路:
* 如果知道取值value的取值范围,并且跨度不大,在能接受范围内的话->
* 可以以value为index,为这个链表的值创建一个数组,而数组的内容则是index作为value出现在链表中的次数->
* 然后遍历链表,将其与数组互为对照,这样也能知道重复的节点。然后由于这个方法的局限性和缺陷就不编码了。->
* 然而,一旦符合上面的一些限制,那么这个思路的时间复杂度 O(n)
* @param node
* @return
*/
private static Node filterNode(Node node) {
Node compare = node.nextNode;
// 在 Node 节点中设置标记,在将每一个节点依次拿出来与所有节点对比时,如果相等标记递增
while (compare != null) {
Node nextNode = node.nextNode;
while (nextNode != null) {
if (nextNode.value == compare.value) {
compare.count++;
}
nextNode = nextNode.nextNode;
}
compare = compare.nextNode;
}
// 在全部比较之后再将重复的节点调节
compare = node.nextNode;
while(compare != null) {
if(compare.count != 1) {
compare.preNode.nextNode = compare.nextNode;
compare.nextNode.preNode = compare.preNode;
}
compare = compare.nextNode;
}
return node;
}
}