zoukankan      html  css  js  c++  java
  • python经典面试算法题1.2:如何从无序链表中移除重复项

    本题目摘自《Python程序员面试算法宝典》,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中。

    1.2 如何实现链表的逆序
    【蚂蚁金服面试题】

    难度系数:⭐⭐⭐
    考察频率:⭐⭐⭐⭐

    题目描述:

    给定一个没有排序的链表,去掉其重复项,并保留原顺序,例如链表1 -> 3 -> 1 -> 5 -> 5 -> 7,去掉重复项后变成 1-> 3 -> 5 -> 7

    方法一:双重循环
    我们从头结点往后以此判断每一个结点,即每一个结点从该结点都往后遍历一遍,往后遍历的过程中,如果有结点和当前结点的值相同,就把这个结点删除掉。

    class Node:  # 定义一个结点类,每一个结点都有data和next
    	def __init__(self, data=None):
    		self.data = data
    		self.next = None
    
    def remove(first_node):  # 这个函数接受的参数是,如果是有头结点的链表传入head.next,没头结点的链表传入head
    	p = first_node
    	while p is not None and p.next is not None:  # and前面的条件控制了first_node是空的时候进不来
    		q = p.next                               # and后面的条件控制了到最后一个元素能够结束
    		prev = p
    		while q is not None:  # 到最后一个结点还会进行比较一次,
    			if q.data == p.data:  # 如果相等
    				prev.next = q.next  # 直接删掉q
    			else:  # 不相等的时候prev向后移动一个
    				prev = q
    			q = q.next
    		p = p.next
    
    # 测试
    data_list = [1, 3, 1, 5, 5, 7]
    
    head = Node(1)
    p = head
    for data in data_list[1:]:  # 按照data_list生成一个单链表
    	p.next = Node(data)
    	p = p.next
    
    first_node = head
    print("删除前: ", end=' ')
    while first_node is not None:  # 打印出每一个结点
    	print(first_node.data, end='	')
    	first_node = first_node.next
    
    print()
    
    first_node = head
    remove(first_node)  # 把重复的结点删除
    
    
    first_node = head
    print("删除后: ", end=' ')
    while first_node is not None:  # 打印出删除之后的各个结点
    	print(first_node.data, end='	')
    	firtst_node = first_node.next
    
    # 程序输出
    删除前:  1	3	1	5	5	7	
    删除后:  1	3	5	7	
    
    

    这种双重循环的方法的时间复杂度是O(n^2),相对来说比较慢。

    方法二:时间换空间
    我们还有一种思路就是,用一个查询很快的容器盛放我们遍历过的结点,如果当前结点在容器中,那么当前结点已经出现过了,就可以把当前结点删除掉,我们可以选用集合set来当作这个容器。

    class Node:
    	def __init__(self, data):
    	    self.data = data
    	    self.next = None
    
    def remove(first_node):  # 传参和上面的是一样的  
    	
    	if not first_node.data:
    		return None
    	p = first_node.next
    	s = {first_node.data}  # 第一个
    	prev = first_node
    	while p is not None:
    		if p.data in s:
    			prev.next = p.next
    		else:
    			s.add(p.data)
    			prev = p
    		p = p.next
    
    
    
    # 测试
    data_list = [1, 3, 1, 5, 5, 7]
    
    head = Node(1)
    p = head
    for data in data_list[1:]:  # 按照data_list生成一个单链表
        p.next = Node(data)
        p = p.next
    
    first_node = head
    print("删除前: ", end=' ')
    while first_node is not None:  # 打印出每一个结点
        print(first_node.data, end='	')
        first_node = first_node.next
    
    print()
    
    first_node = head
    remove(first_node)  # 把重复的结点删除
    
    
    first_node = head
    print("删除后: ", end=' ')
    while first_node is not None:  # 打印出删除之后的各个结点
        print(first_node.data, end='	')
        first_node = first_node.next
     
    程序运行结果:
    删除前:  1	3	1	5	5	7	
    删除后:  1	3	5	7	
    

    这样我们增加了一个set的空间,但是我们把时间复杂度从O(n^2)直接提到了O(n)

    if hasattr(reader, "QQ"):
    	print(f"请{reader}加入交流群:6259 88679 !")
    
  • 相关阅读:
    诸侯安置
    可可西里
    直线交点
    切割多边形
    ACM挑战程序设计竞赛1.1抽签
    朝鲜战争:轰炸大小和岛
    星际争霸II 战斗问题
    乒乓球
    瑞士轮
    NOIP 2010 普及组解题报告
  • 原文地址:https://www.cnblogs.com/duanming/p/11830265.html
Copyright © 2011-2022 走看看