day4-linked list-part02-7.6

task for today

1. 24. 两两交换链表中的节点

2. 19.删除链表的倒数第N个节点

3. 面试题 02.07. 链表相交

4. 142.环形链表II

-------------------------------------------------------------------

1. 24. 两两交换链表中的节点

In this practice, pay attention to following several key points:

(1) dummy point is still recommended;

(2) the condition for while loop to execute the swap operation;

(3) node at odd position should be reserved as "temp=cur.next" and "temp1=cur.next.next.next" for avoiding being modified;

(4) the special circumstances of none head or single node

class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # special cases
        if not head or not head.next:
            return head
        
        # create dummy node
        dummy_node = ListNode(next=head)
        cur = dummy_node
        
        # the condition for while loop
        while cur.next and cur.next.next:
            # reserve odd position node
            temp = cur.next
            temp1 = cur.next.next.next

            cur.next = cur.next.next
            cur.next.next = temp
            temp.next = temp1
            cur = cur.next.next

        return dummy_node.next

Here are the corresponding version for Go

func swapPairs(head *ListNode) *ListNode {
    // special circumstance
    if head == nil || head.Next == nil {
        return head
    }
    // dummmy node
    dummy_node := &ListNode{}
    dummy_node.Next = head

    cur := dummy_node

    // condition for while loop
    for cur.Next != nil && cur.Next.Next != nil {
        temp := cur.Next
        temp1 := cur.Next.Next.Next

        cur.Next = cur.Next.Next
        cur.Next.Next = temp
        temp.Next = temp1
        cur = cur.Next.Next
    }
    return dummy_node.Next
}

Use Rust to code linked list related practice is too disgusting, so I skip rust in linked list part ;-|

2. 19.删除链表的倒数第N个节点

In this practice, it is more desirable to finish it just within once going-through. Therefore, double pointer mindset should be recalled. Following points should be paid attention to.

(1) dummy node is still needed;

(2) slow and fast both start from dummy node

(3) fast should firsly go (n+1) step, which is more convinent as the slow would stop at the node in front of the node penidng to be deleted.

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        # dummy node
        dummy_node = ListNode(next=head)
        slow = dummy_node
        fast = dummy_node

        # start to move fast for n+1 steps
        for i in range(n + 1):
            fast = fast.next

        # start to simultaneously move fast and slow
        while fast:
            slow = slow.next
            fast = fast.next
        
        # do the deleting
        slow.next = slow.next.next

        return dummy_node.next

Go version

func removeNthFromEnd(head *ListNode, n int) *ListNode {
    // dummy node
    dummy_node := &ListNode{}
    dummy_node.Next = head

    slow := dummy_node
    fast := dummy_node

    // move fast for n+1 steps
    for i := 0; i < n+1; i++ {
        fast = fast.Next
    }

    // move slow and fast simultaneously until fast point to None 
    for fast != nil {
        slow = slow.Next
        fast = fast.Next
    }

    // do the deleting
    slow.Next = slow.Next.Next

    return dummy_node.Next
}

3. 面试题 02.07. 链表相交

In this practice, the key point is to find the difference of the two linked list's length, here are the key steps:

(1) find each length

(2) calculate the difference

(3) move the longer pointer to align with the shorter pointer

(4) move together to find the intersection

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        # derive the length for two linked list
        lenA, lenB = 0, 0
        curA, curB = headA, headB
        while curA:
            curA = curA.next
            lenA += 1
        while curB:
            curB = curB.next
            lenB += 1

        # move the longer one first to align with the shorter one
        if lenA > lenB:
            diff = lenA - lenB
            curA = headA
            curB = headB
            for i in range(diff):
                curA = curA.next
        else:
            diff = lenB - lenA
            curA = headA
            curB = headB
            for i in range(diff):
                curB = curB.next
        
        # move together to find the intersection node
        while curA != curB:
            curA = curA.next
            curB = curB.next
        
        return curA

GO verion

func getIntersectionNode(headA, headB *ListNode) *ListNode {
    // find length
    lenA := 0
    lenB := 0
    curA := headA
    curB := headB
    for curA != nil {
        curA = curA.Next
        lenA += 1
    }
    for curB != nil {
        curB = curB.Next
        lenB += 1
    }

    if lenA > lenB {
        diff := lenA - lenB
        curA = headA
        curB = headB
        for i := 0; i < diff; i++ {
            curA = curA.Next
        }
    } else {
        diff := lenB - lenA
        curA = headA
        curB = headB
        for i := 0; i < diff; i++ {
            curB = curB.Next
        }
    }

    for curA != curB {
        curA = curA.Next
        curB = curB.Next
    }

    return curA
}

4. 142.环形链表II

In this practice, three key points need to be clear:

(1) decide whether there is a circle, use fast and slow pointer, if they meet, then there must be a circle;

(2) since they will meet within the circle, which will be position: let the line part is x, length between meetup point and entrance of the circle is y, "the other way around" length is z, which makes the circle circumvent is (y + z);

when they meet, the distance of fast should be twice as that of short one, which gives: (x + y) * 2 = x + y + (y + z) * n, where n represents the circles that fast pointer have finished before meeting slow pointer.

this equation gives results: x = z + (n - 1)*(y + z), this represent the line part equals to the z, as (n - 1)*(y + z) represents the circles which can be offset

(3) based on (2), set two pointers, respectively starting from head and meetup node, both with speed 1 node/setp, they will meet at the entrance node of the circle.

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow = head
        fast = head
        # move fast and slow
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next

            # meet up
            if slow == fast:
                # move one to head
                slow = head
                # move at same speed
                while slow != fast:
                    slow = slow.next
                    fast = fast.next
                # meet node will be the entrance of circle       
                return slow
        # no circle return
        return None

Go version

func detectCycle(head *ListNode) *ListNode {
    slow := head
    fast := head

    for fast != nil && fast.Next != nil {
        slow = slow.Next
        fast = fast.Next.Next

        if slow == fast {
            slow = head

            for slow != fast {
                slow = slow.Next
                fast = fast.Next
            }
            return slow
        }
    }
    return nil 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值