Day56:删除链表中重复的结点

剑指Offer_编程题——删除链表中重复的结点

题目描述:

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

具体要求:

时间限制: C/C++ 1秒,其他语言2秒
空间限制: C/C++32M,其他语言64M

具体实现:

思路一:
  由于本题明确说明是已经排好序的链表,因此我们创建一个新的节点为了防止第一是重复的元素并且连上原来的链表,遍历原来的元素进行删除。如果有重复的那么就保存第一节点值,然后进行全部删除。如果不是重复正常遍历。之后返回新的链表的头结点。这里需要我们特别注意的是:不仅要删除重复的节点,就连本节点也一起删除。并且返回的是第一个结点——头结点。接下来我们分别用java和python将其实现。
1、首先我们用java将其实现:

public class Solution{
	public static ListNode deleteDuplication(ListNode pHead){
		ListNode first = new ListNode(-1);
		first.next = pHead;
		ListNode p = pHead;
		ListNode last = first;
		while(p != null && p.next != null){
			if(p.val == p.next.val){
				int val = p.val;
				while(p != null && p.val == val){
					p = p.next;
				}
				last.next = p;
			}else{
				last = p;
				p = p.next;
			}
		}
		 return first.next;
	}
}

代码效果图如图所示:
代码通过示意图
  如果在牛客网中,此代码可以通过,因为在牛客网中已经为我们定义了链表结构,但是在本地编译器中我们还需要定义链表结构才能正常运行,具体用Java定义链表结构实现如下:

public static class ListNode {
        int val;
        ListNode next = null;

        public  ListNode(int val) {
            this.val = val;
        }
    }

  这里需要我们注意的是:由于要新建一个空链表,如果我们在创建链表中不用static会报错,因此我们需要加上static,特此申明。另外我们要在本地测试代码的正确性还得加上main(),具体用Java实现如下:

public static void main(String[] args) {
		ListNode node1 = new ListNode(1);
		ListNode node2 = new ListNode(2);
		ListNode node3 = new ListNode(3);
		ListNode node4 = new ListNode(3);
		ListNode node5 = new ListNode(4);
		ListNode node6 = new ListNode(4);
		ListNode node7 = new ListNode(5);
		node1.next = node2;
		node2.next = node3;
		node3.next = node4;
		node4.next = node5;
		node5.next = node6;
		node6.next = node7;
		ListNode res = deleteDuplication(node1);
		System.out.println(res.val);
	}

该代码测试的效果如图所示:
代码测试结果图
2、接下来我们用python将其实现:

class Solution:
    def deleteDuplication(self, pHead):
        node_list = []
        nodes = []
        p = pHead
        node_list = [p]
        while p != None:
            p1 = p.next
            if p1 != None and p1.val == p.val:
                node_list.append(p1)
            if p1 == None or p1.val != p.val:
                if len(node_list) == 1:
                    nodes.append(p)
                node_list = [p1]
            p = p1
        if len(nodes) == 0:
            return None
        nodes.append(None)
        for k in range(len(nodes) - 1):
            nodes[k].next = nodes[k + 1]
        return nodes[0]

代码效果图如图所示:
代码通过示意图
  但是在本地编译器中我们还需要定义链表结构才能正常运行,具体用python定义链表结构实现如下:

class ListNode:
	def __init__(self, x):
		self.val = x
		self.next = None

  另外我们要在本地测试代码的正确性还得加上main(),具体用python实现如下:

if __name__ == '__main__':

    a1=ListNode(1)
    a2=ListNode(2)
    a3=ListNode(2)
    a4=ListNode(3)
    a5=ListNode(4)
    a1.next=a2
    a2.next=a3
    a3.next=a4
    a4.next=a5
    S = Solution().deleteDuplication(a1)
    print(S.val)

该代码测试的效果如图所示:
代码测试效果图如图所示
思路二:
  由于题目已经告诉我们该链表是排序链表;因此在相同元素的结点在逻辑上是相邻的。我们可以定义一个先驱结点dummyHead和链表相连 null->1->2->3->3->4->4->5。接着定义两个结点,一个node=phead next=phead.next,如果两个结点值不相等,都相后走一步,否则,node不动,走到next.val!=node.val;最后prev.next=next.next;这个思路可以有两种方法实现,一种是迭代,另一种是递归。
  首先我们用迭代法实现这一思路,我们分别用java和python两种语言将其实现。
1、首先我们用java将其实现:

public class Solution{
	 public static ListNode deleteDuplication(ListNode pHead){
        if(pHead==null||pHead.next==null){
            return pHead;
        }
        ListNode dummyHead=new ListNode(-1);
        dummyHead.next=pHead;
        ListNode prev=dummyHead,node=pHead,next=pHead.next;
        while(next!=null){
            if(node.val==next.val){
                ListNode temp=node;
                while(next!=null&&next.val==node.val){
                    next=next.next;
                    temp=temp.next;
                }
                prev.next=temp.next;
                temp.next=null;
                if(prev.next!=null) {
                    node = prev.next;
                    next = node.next;
                }else{
                    break;
                }
            }else{
                next=next.next;
                node=node.next;
                prev=prev.next;
            }
        }
        return dummyHead.next;
	}
}

代码效果图如图所示:
代码通过示意图
该代码测试的效果如图所示:
代码测试结果图
2、接下来我们用python将其实现:

class Solution:
	def deleteDuplication(self, pHead):
		pPre = None
		pCur = pHead
		pNext = None
		while pCur != None:
			if pCur.next != None and pCur.val == pCur.next.val:
				pNext = pCur.next
				while pNext.next != None and pNext.next.val == pCur.val:
					pNext = pNext.next
				if pCur == pHead:
					pHead = pNext.next
				else:
					pPre.next = pNext.next
				pCur = pNext.next
			else:
				pPre = pCur
				pCur = pCur.next
		return pHead

代码效果图如图所示:
代码通过示意图
该代码测试的效果如图所示:
代码测试结果图
  接下来我们用Java实现递归来解决该题。

public class Solution{
	public static ListNode deleteDuplication(ListNode pHead){
		if(pHead == null || pHead.next == null)
			return pHead;
		ListNode curr = null;
		if(pHead.next.val == pHead.val){
			curr = pHead.next.next;
			while(curr != null && curr.val == pHead.val){
				curr = curr.next;
			}
			return deleteDuplication(curr);
		}else{
			curr = pHead.next;
			pHead.next = deleteDuplication(curr);
			return pHead;
		}
	}
}

代码效果图如图所示:
代码通过示意图
该代码测试的效果如图所示:
代码测试结果图

总结

  本题主要考察大家对链表删除的理解与掌握,在解答本题中,本文给出了两种解题思路,并且分别用java和python将其实现,并且在第二种思路中,我们分别用迭代和递归两种思路来实现这一思路,然后再迭代中同样用java和python将其实现。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!

参考文献

[1] yg838457845
[2] 杨二K
[3] 草莓味儿的小米佳
[4] 章鱼四剑客

猜你喜欢

转载自blog.csdn.net/Oliverfly1/article/details/106941116
今日推荐