算法题002 -- [删除链表中重复的结点] by java

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cjh_android/article/details/82867212

程序运行截图:
在这里插入图片描述

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;
	}
}

猜你喜欢

转载自blog.csdn.net/cjh_android/article/details/82867212