zoukankan      html  css  js  c++  java
  • 玩转单链表

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

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

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

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

    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

  • 相关阅读:
    184. Department Highest Salary【leetcode】sql,join on
    181. Employees Earning More Than Their Managers【leetcode】,sql,inner join ,where
    178. Rank Scores【leetcode】,sql
    177. Nth Highest Salary【leetcode】,第n高数值,sql,limit,offset
    176. Second Highest Salary【取表中第二高的值】,sql,limit,offset
    118. Pascal's Triangle【LeetCode】,java,算法,杨辉三角
    204. Count Primes【leetcode】java,算法,质数
    202. Happy Number【leetcode】java,hashSet,算法
    41. First Missing Positive【leetcode】寻找第一个丢失的整数,java,算法
    删除
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/8563574.html
Copyright © 2011-2022 走看看