删除有序链表中重复的元素(Java)

思路:

顺序遍历链表,利用两个指针,一个preNode,一个curNode,当curNode值重复时,顺序遍历找出下一个不重复的节点,后改变preNode指向这个元素。

代码:

package com.datastructure.link;

/**
 * 有序链表删除重复元素
 */
public class RemoveRepeatNode {

	static class Node {
		int value;
		Node next;
		public Node(int value) {
			this.value = value;
		}
		
		// 便于打印不能作用与循环链表
        @Override
        public String toString() {
            if (this.next == null) {
                return String.valueOf(this.value);
            }
            return this.value + "->" + this.next.toString();
        }
	}
	

	
	/**
	 * 删除链表中所有重复的元素  0->1->1->2  =>   0->2 
	 * 
	 * 新建一个临时头节点,避免头节点是重复元素时,特殊处理
	 * 
	 * 返回链表头节点
	 */
	public static Node removeRepeat(Node head) {
		if (head == null) {
			return head;
		}
		
		// 临时头节点
		Node root = new Node(-1);
		root.next = head;
		
		// 两个指针
		Node preNode = root;
		Node curNode = head;
		
		while (curNode != null && curNode.next != null) {
			// 遇到重复节点,则遍历所有相同节点,pre->next 指向 最后一个相同节点的next
			if (curNode.value == curNode.next.value) {
				while (curNode != null && curNode.next != null && curNode.value == curNode.next.value) {
					curNode = curNode.next;
				}
				// curNode此时为重复元素中的最后一个元素
				// 删除重复元素
				preNode.next = curNode.next;
			} else {
				preNode = curNode;
			}
			// 后移curNode
			curNode = curNode.next;
		}
		
        return root.next;		
	}
	
	/**
	 * o(n)时间  有序的链表删除重复元素,保留第一个重复的元素
	 * 0->1->1->2  =>   0->1->2 
	 * 
	 * 遍历链表,一个指针指向前驱节点  一个指向下一个节点
	 * 
	 * @return 返回新的链表(新链表,头结点引用)
	 * 
	 */
	public static Node removeRepeat1(Node head) {
		if (head == null) {
			throw new RuntimeException("link is empty");
		}
		
		Node root = new Node(-1);
		root.next = head;
		
		Node pre = root;
		Node curNode;
		
		while (pre != null) {
			curNode = pre.next;
			// 元素重复时 删除后续重复元素
			if (curNode != null && pre.value == curNode.value) {
				pre.next = curNode.next;
			// 不重复时 pre后移一位
			} else {
				pre = pre.next;
			}
		}
		
		return root.next;
	}
	
	
	/**
	 * o(n)时间  有序的链表删除重复元素,保留最后一个重复的元素
	 * 0->1->1->2  =>   0->1->2 
	 * 
	 * 遍历链表,一个指针指向前驱节点 一个指向当前节点
	 * 
	 * @return 返回新的链表(新链表,头结点引用)
	 * 
	 */
	public static Node removeRepeat2(Node head) {
		if (head == null) {
			throw new RuntimeException("link is empty");
		}
		
		Node newHead = head;
		
		Node preNode = newHead;
		Node curNode = newHead.next;
	
		// 当头结点与下一结点值相同,需要删除头结点及后续相同节点
		if (preNode.value == curNode.value) {
			while (preNode.value == curNode.value) {
				preNode = preNode.next;
				curNode = curNode.next;
			}
			newHead = preNode;
		}
		
		// 头结点与下一结点值不同
		while (curNode != null && curNode.next != null) {
			if (curNode.value != curNode.next.value) {
				preNode = curNode;
			} else {
				preNode.next = curNode.next;
			}
			curNode = curNode.next;
		}
		
		return newHead;
	}
	
    public static void main(String args[]) {
        
		Node head = createTestLinkedList(5, new Node(4));
        // 原链表
        System.out.println("origin link: " + head);

        // 删除重复元素
        System.out.println("remove repeat node: " + removeRepeat(head));

        
		Node head1 = createTestLinkedList(5, new Node(4));
        // 删除重复元素,保留第一个重复的元素
        System.out.println("remove repeat node but left first one: " + removeRepeat1(head1));
        
        
		Node head2 = createTestLinkedList(5, new Node(4));
        // 删除重复元素,保留最后一个重复的元素
        System.out.println("remove repeat node but left last one: " + removeRepeat2(head2));
        
    }
    
    private static Node createTestLinkedList(int n, Node addNode) {
        Node head = new Node(0);
        Node head1 = new Node(0);
        head.next = head1;
        Node curNode = head1;
        int count = 1;
        for (int i = 1; i < n; i++) {
            curNode.next = new Node(i);
            curNode = curNode.next;
            if (i == 2 && count >= 0) {
            	i--;
            	count--;
            }
        }
        curNode.next = addNode;
        return head;
    }

}

猜你喜欢

转载自blog.csdn.net/zangdaiyang1991/article/details/88616832