欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python无序链表删除重复项的方法

程序员文章站 2022-06-20 14:33:46
题目描述: 给定一个没有排序的链表,去掉重复项,并保留原顺序 如: 1->3->1->5->5->7,去掉重复项后变为:1->3->5-&g...

题目描述:

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

方法:

  1. 顺序删除
  2. 递归删除

1.顺序删除

由于这种方法采用双重循环对链表进行遍历,因此,时间复杂度为o(n**2)
在遍历链表的过程中,使用了常数个额外的指针变量来保存当前遍历的结点,前驱结点和被删除的结点,所以空间复杂度为o(1)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @time  : 2020/1/15 20:55
# @author : buu
# @software: pycharm
# @blog  :https://blog.csdn.net/weixin_44321080
class lnode:
  def __init__(self, x):
    self.data = x
    self.next = none

def removedup(head):
  """
  对带头结点的无序单链表删除重复的结点
  顺序删除:通过双重循环直接在链表上进行删除操作
  即,外层循环用一个指针从第一个结点开始遍历整个链表,内层循环从外层指针指向的下一个结点开始,
  遍历其余结点,将与外层循环遍历到的的指针所指的结点的数据域相同的结点删除
  :param head: 头指针
  :return:
  """
  if head is none or head.next is none:
    return
  outercur = head.next
  innercur = none
  innerpre = none
  while outercur is not none:
    innercur = outercur.next
    innerpre = outercur
    while innercur is not none:
      if outercur.data == innercur.data:
        innerpre.next = innercur.next
        innercur = innercur.next
      else:
        innerpre = innercur
        innercur = innercur.next
    outercur = outercur.next

if __name__ == '__main__':
  i = 1
  head = lnode(6)
  tmp = none
  cur = head
  while i < 7:
    if i % 2 == 0:
      tmp = lnode(i + 1)
    elif i % 3 == 0:
      tmp = lnode(i - 2)
    else:
      tmp = lnode(i)
    cur.next = tmp
    cur = tmp
    i += 1
  print("before removedup:")
  cur = head.next
  while cur is not none:
    print(cur.data, end=' ')
    cur = cur.next
  removedup(head)
  print("\nafter removedup:")
  cur = head.next
  while cur is not none:
    print(cur.data, end=' ')
    cur = cur.next

结果:

python无序链表删除重复项的方法

2.递归

此方法与方法一类似,从本质上而言,由于这种方法需要对链表进行双重遍历,所以时间复杂度为o(n**2)
由于递归法会增加许多额外的函数调用,所以从理论上讲,该方法效率比方法一低

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @time  : 2020/1/15 21:30
# @author : buu
# @software: pycharm
# @blog  :https://blog.csdn.net/weixin_44321080
class lnode:
  def __init__(self, x):
    self.data = x
    self.next = none
def removeduprecursion(head):
  """
  递归法:将问题逐步分解为小问题,即,对于结点cur,首先递归地删除以cur.next为首
  的子链表中重复的结点;接着删除以cur为首的链表中的重复结点,
  :param head:
  :return:
  """
  if head.next is none:
    return head
  pointer = none
  cur = head
  head.next = removeduprecursion(head.next)
  pointer = head.next
  while pointer is not none:
    if head.data == pointer.data:
      cur.next = pointer.next
      pointer = cur.next
    else:
      pointer = pointer.next
      cur = cur.next
  return head
def removedup(head):
  """
  对带头结点的单链表删除重复结点
  :param head: 链表头结点
  :return:
  """
  if head is none:
    return
  head.next = removeduprecursion(head.next)
if __name__ == '__main__':
  i = 1
  head = lnode(6)
  tmp = none
  cur = head
  while i < 7:
    if i % 2 == 0:
      tmp = lnode(i + 1)
    elif i % 3 == 0:
      tmp = lnode(i - 2)
    else:
      tmp = lnode(i)
    cur.next = tmp
    cur = tmp
    i += 1
  print("before recursive removedup:")
  cur = head.next
  while cur is not none:
    print(cur.data, end=' ')
    cur = cur.next
  removedup(head)
  print("\nafter recurseve removedup:")
  cur = head.next
  while cur is not none:
    print(cur.data, end=' ')
    cur = cur.next

结果:

python无序链表删除重复项的方法

引申:从有序链表中删除重复项

上述介绍的方法也适用于链表有序的情况,但是由于上述方法没有充分利用到链表有序这个条件,因此,算法的性能肯定不是最优的。本题中,由于链表具有有序性,因此不需要对链表进行两次遍历。所以有如下思路:
用cur指向链表的第一个结点,此时需要分为以下两种情况讨论:

  • 如果cur.data == cur.next.data,则删除cur.next结点;
  • 如果cur.data != cur.next.data,则cur=cur.next,继续遍历其余结点;

总结

以上所述是小编给大家介绍的python无序链表删除重复项的方法,希望对大家有所帮助