• 玩转单链表


    玩指针是许多算法的精髓,就是要像六脉神剑一样,指针乱指一通之后,内存中的数据变得井然有序。

    操作指针真的是太好玩了。下面出几道题。

    一、不用额外空间翻转单链表

    给定一个单链表,要求翻转之。

    import random
    
    """
    O(1)空间复杂度翻转链表
    方法:one->two->three 三元组构成一个窗口,每次都翻转窗口内的元素,然后将
    窗口从左往右滑动
    """
    
    list_length = 4
    
    
    class Node:
        def __init__(self, value, nex):
            self.value = value
            self.next = nex
    
    
    def generate_list():
        a = Node(0, None)
        now = a
        for i in range(list_length):
            x = Node(random.randint(0, 100), None)
            now.next = x
            now = x
        return a.next
    
    
    def print_list(x):
        while x:
            print(x.value, end=' ')
            x = x.next
        print()
    
    
    def reverse(x):
        one = x
        two = one.next
        one.next = None
        # 如果只有一个元素,那么直接返回
        if not two: return x
        three = two.next
        while 1:
            two.next = one
            if not three: break
            temp = three.next
            three.next = two
            one = two
            two = three
            three = temp
        return two
    
    
    l = generate_list()
    print_list(l)
    print_list(reverse(l))
    
    

    二、两个无环单链表求第一个公共结点

    方法非常简单:求出两个链表长度之差,记为x;然后让较长的链表先走x步;最后让两个链表携手并进。

    时间复杂度:O(N+M)
    空间复杂度:O(1)

    三、判断单链表中是否有环,如果有环,找出环的第一个结点

    有一个著名的ro算法,甲乙两个人同时从起点出发,甲每次走1格,乙每次走两格。如果甲乙二人有一人走到了终点,那么说明无环;如果甲乙二人都没有走到终点,而是经过s次走路之后,甲乙二人相遇了,说明有环,并且环的长度必然是s。因为在x次走路中,甲比乙少走了s步,也就是说环的长度是s。

    ----x--|----y----|
           |____z____|
    

    如上图所示,将链表三部分的长度记为x,y,z,甲乙二人在y线段的最右侧相遇。那么甲走了x+y步,乙走了x+y+z+y步,显然(x+y)乘以2等于x+y+z+y。所以z=x。要想找到环中的第一个结点,只需要发现一个规律:让乙回到起点处(x最左侧)且将乙的步伐改为每次走一格,甲继续从y的右侧(相遇点)出发,两人下次相遇的地方就是环中的第一个结点,因为x=z!

    有一道类似的趣题:无限一维空间中有两个生物,这两个生物之间无法进行交流,现在让你用如下四条汇编指令编程:
    (1)move left
    (2)move right
    (3)if this position is visited,then goto 语句标号
    (4)goto语句(程序中可以使用标号)

    现在你需要开发一套汇编代码,给这两个生物安装上这套程序,保证这两个生物一定会相遇。
    代码如下:

    loop:
        if this position is visited,then goto movefast
        moveleft
        goto loop
    movefast:
        moveleft
        moveleft
    goto loop
    

    原理是:两个生物一前一后同时往一个方向走,速度相同。如果看见了另一个生物的轨迹,就开始提速。这样就肯定能够追上前面的生物。

    四、给定两个单链表,判定它们是否拥有共同结点

    ---------
              \________
              /
    _________/
    

    这个问题比较复杂,需要分类讨论。
    1、如果两个链表都是无环单链表,那么只需要判断最后一个结点是否相同即可!
    2、如果一个链表是无环单链表,而另一个链表是有环的,那么这两个链表必然无公共结点!
    3、如果两个链表都是有环的:
    (1)假如两个链表相交,那么环必然是这两个链表的公共部分,只需要找到链表1环上的某个结点x,看看链表2是否会经过结点x
    (2)假如两个链表不相交,那么它们的环必然不相交

    五、求两个有环单链表的第一个公共结点(两个链表保证有公共结点)

    首先用ro算法求出环上的某个点,把这个点当做链表的结尾,相当于把这个结点的next设为null。从而问题转换成了两条无环单链表求第一个公共结点。这个问题复杂度也是O(M+N)

    参考资料

    http://blog.csdn.net/v_JULY_v/article/details/6447013

  • 相关阅读:
    20172301 2018-2019-1《程序设计与数据结构》课程总结
    20172301 哈夫曼树实验报告
    20172301 《Java软件结构与数据结构》实验三报告
    20172301 《程序设计与数据结构》第九周学习总结
    20172301 《Java软件结构与数据结构》实验二报告
    20172301 《程序设计与数据结构》第八周学习总结
    20172301 《程序设计与数据结构》第七周学习总结
    20172301 《程序设计与数据结构》第六周学习总结
    20172301 《程序设计与数据结构》课堂测试修改报告
    20172301 《程序设计与数据结构》第五周学习总结
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/8563574.html
Copyright © 2020-2023  润新知