Comprehensive analysis of the issue list

General problem solving ideas list:

Using a list of memory blocks of discrete, linear through a storage structure in each memory pointer stored in the memory and configured, it is a form of a linear linked list of tables.
Chain problem is a study of the basic coding capacity problem, the characteristics of this type of problem solution is not complicated, the difficulty is to prove the correctness of the solution and how to code. That is, whether the study can write bug freecode, mathematical algorithms examine a few will prove a problem.

  • Using drawing techniques, the release of part of the brain space. To consider the issue by drawing several examples of small-scale, if the problem requires more than three pointer can be resolved, then the time cost of drawing, it can be accepted.
  • Through case under normal circumstances the draw, the main idea of ​​the disintegration of thinking algorithm. 3-5 is generally the case where the nodes.
  • At this time, it is important not to immediately coded, but cite a few specific instances, to verify whether the general idea robust in Special Scenes, usually list the number of nodes 0,1,2,3,4, and head node pointer list, if it works with the tail node.
  • Be patient, do not go too fast and commit code, the list in question is the ability to exercise your code review, the idea is very simple, the difficulty lies at the heart resistant, sober analysis. Believe me, you can always find the problem first coding.

So what is the general idea of it?
This is a pattern, thinking algorithm list problem is so few, you can apply mathematics to prove after watching a few typical cases can grasp the real difficulty lies in coding, chain issues involving pointer operations, error-prone, write that bug freeis not the thing, so the most important thing is to practice more.

Classic problem list:

  1. Design a single list:
    Here we rely on sentry ideas
class MyLinkedList:

    def __init__(self):
        """
        初始化一个链表,使用一个永不存数据的节点作为哨兵,
        这样可以简化,在插入删除操作中对头节点与尾节点插入时的条件判读,
        进而提高速度。
        """
        self.sb = ListNode(-1)
        self.le = 0


    def get(self, index):
        """
        通过索引获取链表中的节点。
        """
        head = self.sb.next
        if  index < 0 or index >= self.le or head == None:
            return -1
        for i in range(index):
            head = head.next
        return head.val


    def addAtHead(self, val):
        """
        在头节点的位置插入节点,哨兵思想使其不用判读非空情况。
        """
        head = self.sb.next
        self.sb.next = ListNode(val)
        self.sb.next.next = head
        self.le += 1


    def addAtTail(self, val):
        """
        在尾部插入节点
        """
        tmp = self.sb
        for i in range(self.le):
            tmp = tmp.next
        tmp.next = ListNode(val)
        self.le += 1


    def addAtIndex(self, index, val):
        """
        在指定索引的位置插入节点
        """
        if  index < 0 or index > self.le :
            return -1
        pre = self.sb
        for i in range(index):
            pre  = pre.next
        tmp = pre.next
        pre.next = ListNode(val)
        pre.next.next = tmp
        self.le += 1


    def deleteAtIndex(self, index):
        """
        指定index的位置删除节点
        """
        if index < 0 or index >= self.le:
            return
        pre = self.sb
        for  i in range(index) :
            pre = pre.next
        pre.next = pre.next.next
        self.le -= 1
  1. Determining whether a cycloalkyl list

Classic double pointer thinking three questions: Is there a list interpretation of the intersection ring, chain and ring, find the length of the loop.
Define two pointers, from the beginning, a two-step each pass,
a step, there are two intersecting rings,
disjoint take two steps first to the tail pointer, then the interpretation acyclic.

class Solution(object):
    def hasCycle(self, head):
        if head is None or head.next is None:
            return False
        fast ,slow = head,head
        while fast is not  None and fast.next is not None:
            fast = fast.next.next
            slow = slow.next
            if slow == fast:
                return True
        return False
  1. Analyzing the entry point of the ring

After the meet cursor speed, the fast re-pointing to the head node pointer,
two pointers starts walking while each walking step. When meet again,
that is the entry point of the ring.


class Solution(object):
    def detectCycle(self, head):
        if head == None or head.next == None:
            return None
        fast = head.next.next
        slow = head.next
        while fast != None and fast.next != None:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                break
        if fast == None or fast.next == None:
            return None
        fast = head
        while fast != slow:
            fast = fast.next
            slow = slow.next
        return fast
  1. Solving loop length
    determined meeting point, continue to move a pointer, each step, recording the number of walking,
    the other pointer does not move in situ, to meet the length is the number again.
    Very simple, the brain make it.
  pass

So the question is, the front two algorithms correct it, how to use mathematics to prove it?
Chain has proven algorithm ring :
proof:
1. There is provided a pointer when walked slowly ring entry point position, the distance Ll representatives head to the entry point, the pointer is slow walking distance, which is certainly quick pointer to the ring, from the entrance set point L2 of.
2. I representative of the number of steps to catch up with slow pointer pointer to go faster.
Total number of steps slow the code pointer 3. S1, S2 of the code pointer fast total number of steps.
4. C represents a cycloalkyl perimeter.
If the fast and slow pointer Pointer met, then it must meet (S1+i-L1)mod C = (S2+2i-L1)mod C, is subtracted by subtracting the number of steps L1 to the ring before, the i-step slow pointer chasing pointer actually go so fast step 2i. Therefore, to meet certain will meet this condition.
Excluded influence the number of steps before the ring, only to see the ring with respect to the entry point from the position after the ring, are: S1 = L1, S2 - L1 = NC + L2, where N is the number of rings has been much surround ring. Into the above equation i mod C = (NC+L2+2i) mod Cis further order was: (L2 + i) mod C = 0When, N 0 at understood, L2 < C, I must be an integer in the range of solution, it must meet the speed of the pointer.
Entry point algorithm ring Proof:
According to equation (4) => (4) => (mn-1) L2 + L2 = s => (mn-1) L2 + P1 + P2 = L1 + P1 <=> (mn -1) + P2 = L2 of Ll
(the first intersection point Pl is defined to meet the length of chasing points, P2 is the length of the meeting point to the first point of intersection, i.e., P1 + P2 = L2)
this equation indicates that the list It does not include the length of the loop equal to the length of the meeting point to the first point of intersection of the ring plus the length of an integer multiple.

  1. Seeking two intersection points list
    two pointers, pointing to two head of the list, when constantly move forward,
    as to who the tail, then head back to another list. Intersecting the list,
    first to the tail of the list must be short, long head back to the list,
    when the pointer is also a long list of departure to the end,
    it has gone through is just one more step to the difference between the number of nodes in the length of the list,
    at this time, the long chain pointer back to the head of the short chain,
    both aligned position, to move forward in this final encounter, namely the intersection point.
class Solution(object):
    def getIntersectionNode(self, headA, headB):
        p1 ,p2 = headA,headB
        while p1 != p2:
            p1 = headB if p1 == None else p1.next
            p2 = headA if p2 == None else p2.next
        return p1
  1. The reciprocal of the n-th node deletes single chain of
    two pointers, a go ahead n steps, and then again go with two hands,
    if the tail pointer reaches the go, then go after the node pointer for deletion precursor node.
    Penultimate n, in fact, the first positive number Ln + 1, L is the length of the list,
    so Ln is just to delete the precursor node.
    Go ahead n steps, after the walk is Ln, and
    this is precisely what the second pointer in a node of Ln.
class Solution(object):
    def removeNthFromEnd(self, head, n):
        pre ,last = head,head
        for i in range(n):
            pre = pre.next
        if pre == None:
            return head.next
        while pre.next != None:
            pre = pre.next
            last = last.next
        last.next = last.next.next
        return head

Pointer operations
this problem is to examine pointer checking boundary condition of operation, some of the coding capability requirements.

  1. Single chain reversing
    two pointers implemented Version c:

class Solution(object):
    def reverseList(self, head):
        """
        使用三个指针,完成单链表操作。
        """
        if head == None:
            return None
        pre = None
        next = head.next
        while head != None:
            head.next = pre
            pre = head
            head = next
            if next != None:
                next = next.next
        return pre
  1. All the elements to val remove the list of
    considerations boundary conditions, exceptions, the first cycle is the key
    to traverse the precursor delete Val methods investigated by the linked list of nodes 0,1,2,3 get,
    unable to adapt to the head node as well as the head node is a continuous need to remove the Val.

class Solution(object):
    def removeElements(self, head, val):
        if head == None:
            return None   
        while head != None and head.val == val:
            if head.next == None:
                return None
            else:
                head = head.next
        pre = head
        while pre.next != None:
            if pre.next.val == val:
                pre.next = pre.next.next
            else:
                pre = pre.next
        return head
  1. Parity list
    next to each other by means of two pointers, staggered forward, to achieve independent traversing smart parity node, then own series, and combined.
    The difficulty lies in the relationship between the pointer no mistake, you can use drawing techniques assist thinking, problem lists test programming capability, to be tolerant, patient and check this is the key.
class Solution(object):

    def oddEvenList(self, head):
        if head is None:
            return head
        odd = head
        even = head.next
        if even is None:
            return head
        odd_prev = odd
        even_prev = even
        even_head = even
        while even is not None and even.next is not None:
            odd = even.next
            even = odd.next
            odd_prev.next = odd
            even_prev.next = even
            odd_prev = odd
            even_prev = even
        odd.next = even_head
        return head
  1. Palindromic chain
    speed pointer to find the midpoint, the second half of the list reverse, neutral position and over again traverse the list, which comparison value is determined by one palindromic.
    The focus here is in the appropriate abstract encoding process can be simplified code logic, greatly enhance the accuracy and readability of the coding.
class Solution(object):
    def isPalindrome(self, head):
        if head is None or head.next is None:
            return True
        mid = self.getMid(head)
        mid.next = self.getFanZhuan(mid.next)
        p,q = head,mid.next
        while q is not None and p.val == q.val:
            q = q.next
            p = p.next
        self.getFanZhuan(mid.next)
        return q == None
    def getMid(self,head):
        fast,slow = head.next,head
        while fast is not None and fast.next is not None:
            fast = fast.next.next
            slow = slow.next
        return slow
    def getFanZhuan(self,head):
        if head is None or head.next is None:
            return head
        pre,curr,next = None,head,head.next
        while curr is not None:
            curr.next = pre
            pre = curr
            curr = next
            next = None if next is None else next.next
        return pre
  1. Design doubly linked list
    doubly linked list of more complex design than the single list of some, but understand if the use of sentinel in the list of words, it is still very easy, but this question I actually did three days, well I seven every morning half will do a question. should spend a total of 40 minutes, or I was too dishes, and there is such a problem when the design data structure, to write multiple methods, when we review the code, but also consider the multiple functions with each other the impact of call,
    which is the class level "invariant", requires in-depth thinking the role of each action, careful understanding of pre- and post-conditions for each behavior, as well as the entire object lifecycle must maintain a What kind of constant state Yes.
class MyLinkedList(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.head = ListNode(-1)
        self.tail = ListNode(-1)
        self.head.next = self.tail
        self.tail.prev = self.head
        self.length = 0


    def get(self, index):
        """
        Get the value of the index-th node in the linked list. If the index is invalid, return -1.
        :type index: int
        :rtype: int
        """
        if index < 0 or index >= self.length:
            return -1
        return self.getNode(index).val


    def getNode(self,index):
        frist = self.head.next
        for i in range(index):
            frist = frist.next
        return frist                                                                                


    def addAtHead(self, val):
        """
        Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
        :type val: int
        :rtype: void
        """
        frist = self.head.next
        node = ListNode(val)
        self.head.next = node
        node.prev = self.head
        node.next = frist
        frist.prev = node
        self.length += 1


    def addAtTail(self, val):
        """
        Append a node of value val to the last element of the linked list.
        :type val: int
        :rtype: void
        """
        last = self.tail.prev
        node = ListNode(val)
        self.tail.prev = node
        node.next = self.tail
        last.next = node
        node.prev = last
        self.length += 1


    def addAtIndex(self, index, val):
        """
        Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
        :type index: int
        :type val: int
        :rtype: void
        """
        if index < 0 or index > self.length:
            return
        if index == self.length:
            self.addAtTail(val)
            return
        old = self.getNode(index)
        node = ListNode(val)
        pre = old.prev
        pre.next = node
        node.prev = pre
        node.next = old
        old.prev = node
        self.length += 1


    def deleteAtIndex(self, index):
        """
        Delete the index-th node in the linked list, if the index is valid.
        :type index: int
        :rtype: void
        """
        if index < 0 or index >= self.length:
            return
        node = self.getNode(index)
        pre = node.prev
        next = node.next
        pre.next = next
        next.prev = pre
        node.next = None
        node.prev = None
        self.length -= 1
  1. Splicing two ordered lists
    this question is the key to handling of exceptions, the list may have entered two are empty, it may vary in length. Both need to be addressed separately
class Solution(object):
    def mergeTwoLists(self, l1, l2):
        if l1 is None and l2 is None:
            return None
        elif l1 is None:
            return l2
        elif l2 is None:
            return l1
        sb ,headA,headB = ListNode(-1),l1,l2
        headSB = sb
        while headA  and  headB :
            if headA.val > headB.val:
                sb.next = headB
                headB = headB.next
            elif headA.val < headB.val:
                sb.next = headA
                headA = headA.next
            else:
                sb.next = headA
                headA = headA.next
                sb = sb.next
                sb.next = headB
                headB = headB.next
            sb = sb.next
        if headA:
            sb.next = headA
        elif headB:
            sb.next = headB
        return headSB.next
  1. The two figures represent the sum of the list in reverse order
    this problem using Sentinel simplifies the code, while paying attention to the handling of the carry,
    is very well done.
class Solution(object):
    def addTwoNumbers(self, l1, l2):
        rem = 0
        dummy = ListNode(0)
        p = dummy
        while l1 or l2 or rem:
            s = (l1.val if l1 else 0)  + (l2.val if l2 else 0) + rem
            rem = s/10
            p.next = ListNode(s%10)
            p = p.next
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next
        return dummy.next
  1. Flat multistage doubly linked list
    detailed explanation see here
    this emphasis on the problem, the handling of a pointer, you can draw assisted think,
    traverse the list subject, no child will continue to traverse the list.
    The entire procedure is completed in one cycle.
    There is a linked list traversal sub-chained give the sub-list head pointer and the tail of the next sub-tail node list points to the next pointer of the current main chain, next if not empty, it is prev pointer to the tail of the linked list node, and then update the list of sub-head node again, so that the current head node pointer next master list traversal node to the sub-list, and the sub-list head node prev pointer in turn point to it, and point it to the sub pointer assigned to child none, the next current pointer directly to the combined tail pointer of the linked list, thereby reducing the number of its traverse. Reciprocating iteration, according to the specific code to be understood that the drawing.
    This problem more complicated pointer, drawing the assignment analysis is to write bug freecritical.
class Solution(object):
        if not head:
            return None
        p = head
        while p:
            if not p.child:
                p = p.next
                continue

            p1 = p.child
            p2 = p.child
            while p2.next:
                p2 = p2.next

            p2.next = p.next
            if p.next:
                p.next.prev = p2
            p.next = p1
            p1.prev = p
            p.child = None
            p = p1

        return head
  1. Copy pointer with random list of
    this question is the key to the understanding of random pointer, copy node when replication of random pointer is relative, must ensure that a random node pointer relatively unchanged.
    Details click here
class Solution(object):
    def copyRandomList(self, head):
        if not head:
            return None
        p = head
        while p:
            tmp = RandomListNode(p.label)
            tmp.next = p.next
            p.next = tmp
            p = tmp.next
        p = head
        while p:
            if p.random:
                p.next.random = p.random.next
            p = p.next.next
        n,o = head.next,head
        new = n
        while n:
            o.next = n.next
            o = o.next
            if not o:
                break
            n.next = o.next
            n = n.next
        return new
  1. Rotating the list
    the best solution to this problem can be done in a constant space, linear time
    to reverse the whole, find the split point, two of the portions are in reverse order.
    Note that, when the reverse order to specify a tail pointer, because a continuous chain

class Solution(object):
    def rotateRight(self, head, k):

        if head is None:
            return None
        if k == 0:
            return head
        count = 0
        end = None
        tmp = head
        while tmp:
            tmp = tmp.next
            count += 1
        head = self.nx(head,end)
        k = k % count
        tmp = head
        while k != 0:
            tmp = tmp.next
            k -= 1
            end = tmp
        new_head = self.nx(head,end)
        head.next = self.nx(end,None)
        return new_head


    def nx(self,head,end):
        if head is None:
            return None
        pre,curr,next = None,head,head.next
        while curr != end:
            curr.next = pre
            pre = curr
            curr = next
            next = next.next if next else None
        return pre
  1. Ordered list convert binary search tree
    details
    this question is essentially linear relationship between the structure and the tree structure of study,
    how to store a binary search tree with linear structure? Linear table can be ordered, linear table can be an array, a linked list may be. If this is so, how to use the table in turn ordered linear structure binary search tree? Dichotomy is the key, the dichotomy is a linear mapping relation table and ordered binary search, then how to take dichotomy midpoint?
    An array index can be calculated index, the list can use a pointer speed, ok problem has been solved at this time, look at the code.
class Solution(object):
    def sortedListToBST(self, head):
        return self.insterC(head,None)
    def insterC(self,head,tail):
        if head is tail:
            return None
        if head.next is tail:
            return TreeNode(head.val)
        fast = mid = head
        while fast is not tail and fast.next is not tail:
                mid = mid.next
                fast = fast.next.next
        tree = TreeNode(mid.val)
        tree.left = self.insterC(head,mid)
        tree.right = self.insterC(mid.next,tail)
        return tree
  1. Twenty-two exchange the list of nodes
    for this problem is similar to the list in reverse order of ideas, but as long as the correct understanding of the relationship between the linked list pointers, attention predecessor, the current node, the three subsequent transformation. Note that the code inspection, inspection of boundary conditions, analyze exceptions can write bug free, with emphasis on patience, there must be tolerant.
    Detail

class Solution(object):
    def swapPairs(self, head):
        if head is None:
            return head
        sb = ListNode(-1)
        sb.next = head
        a = sb
        b = head
        c = head.next
        while c:
            a.next = c
            b.next = c.next
            c.next = b
            a = b
            b = b.next
            if b is None:
                break
            c = b.next
        return sb.next
  1. Sort list
    on this question is essentially the list of merge sort of realization, subject of the request O (nlong), linked list to achieve the advantages is that you can complete the merge sort merge under constant space, the disadvantage is the midpoint of the query can not think of an array as complete in constant time , so its performance is slower than an array of some, but also in the same order of magnitude, and does not require continuous storage space, as well as extra space, in some cases also a good choice.
    Detail
class Solution(object):
    def sortList(self, head):
        if head is None or head.next is None :
            return head

        mid =  self.getMid(head)
        left = self.sortList(head)
        right = self.sortList(mid)
        return self.merge(left,right)


    def getMid(self,head):
        m,k = head,head
        sb = ListNode(-1)
        sb.next = head
        while k and k.next:
            k = k.next.next
            m = m.next
            sb = sb.next
        sb.next = None
        return m


    def merge(self,a,b):
        sb = ListNode(-1)
        curr = sb
        while a and b:
            if a.val >= b.val:
                curr.next = b
                b = b.next
            else:
                curr.next = a
                a = a.next
            curr = curr.next
        if a:
            curr.next = a
        elif b:
            curr.next = b
        return sb.next
  1. Rearrangements list
    details
    this question is the key to understanding the problem correctly, write a few test cases found that the taste is a combination of three common behaviors linked list, access to the midpoint of the list, the list in reverse order, cross-merge list.
class Solution(object):
    def reorderList(self, head):
        if not head or not head.next:
            return
        if not head.next.next:
            return

        mid = self.get_mid(head)
        head1 =  self.nx(mid)
        head =  self.marge(head,head1)

    def get_mid(self,head):
        pre = ListNode(-1)
        pre.next = head
        fast,slow = head,head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            pre = pre.next
        pre.next = None
        return slow

    def nx(self,head):
        pre, cur, next = None,head,head.next
        while cur:
            cur.next = pre
            pre = cur
            cur = next
            if next:
                next = next.next
        return pre

    def marge(self,head1,head2):
        dummy = ListNode(-1)
        d = dummy
        p, q = head1,head2
        while p and q:
            d.next = p
            p = p.next
            d = d.next

            d.next = q
            q = q.next
            d = d.next
        if q:
            d.next = q
        elif p:
            d.next = p
        return dummy.next
  1. List the components
    key to understanding the concept of problem-solving questions in the definition of the components, using the map key characteristics and to determine the counting strategy to solve problems, the key is this question correctly understand the new concepts and identify the algorithm in the classic mode - a collection of search.
class Solution:
    def numComponents(self, head, G):
        if head is None or len(G) == 0:
            return 0
        count = 0
        cur = head
        GMap = {}
        for v in G:
            GMap[v] = 0
        while cur:
            if cur.val in GMap and (cur.next is None or cur.next.val not in GMap):
                count += 1                
            cur = cur.next
        return count
  1. Partition list 01
    divided into two steps solved to find the first division rule.
    The second rule cutting press.
    The rules are simple meaning of the questions is to first split the remainder shared equally then
    this problem is to find the law, its mathematical expression and a good package operating behavior.
class Solution:
    def splitListToParts(self, root, k):
        p = root
        size = 1
        while p and p.next:
            size += 1
            p = p.next
        mod = size % k
        num = int(size / k)
        res = []

        tmp = root
        while k != 0:
            if mod != 0:
                root = self.splitListNodeByLen(tmp,num+1)
                mod -= 1
            else:
                root = self.splitListNodeByLen(tmp,num)
            res.append(tmp)
            tmp = root
            k -= 1
        return res


    def splitListNodeByLen(self,root,l):
        if not root or l <= 0:
            return root
        pre = None
        while l > 0:
            pre = root
            root = root.next
            l -= 1
        pre.next = None
        return root
  1. Two numbers together II
    to this problem is even adding an upgraded version of the table, the table is no longer even need to reverse the discretion of disintegration pattern that is the first general to specific approach, this question my solution is relatively poor, do not learn from best practices , I just wanted to come out, since there was no starting from the low, but also operational problems, think of using a stack of such direct aids to deal with.
    But the additional complexity introduced during and after thinking about how to optimize.
class Solution:
    def addTwoNumbers(self, l1, l2):
        s1, s2 = [], []
        tmp1 ,tmp2 = l1, l2
        while tmp1:
            s1.append(tmp1.val)
            tmp1 = tmp1.next
        while tmp2:
            s2.append(tmp2.val)
            tmp2 = tmp2.next
        c = 0
        node = ListNode(-1)
        root = node
        while len(s1) != 0 and len(s2) != 0:
            num = s1[-1] + s2[-1] + c
            s1 = s1[:len(s1)-1]
            s2 = s2[:len(s2)-1]
            if num >= 10:
                node.val = num - 10
                c = 1
            else:
                node.val = num
                c = 0
            if len(s1) == 0 and len(s2) == 0:
                if c == 1:
                    node.next = ListNode(-1)
                    node = node.next
                    node.val =  c
                break
            node.next = ListNode(-1)
            node = node.next

        while len(s1) != 0:
            num = s1[-1] + c
            if num >= 10:
                node.val = num - 10
                c = 1
            else:
                node.val = num
                c = 0
            s1 = s1[:len(s1)-1]
            if len(s1) == 0:
                if c == 1:
                    node.next = ListNode(-1)
                    node = node.next
                    node.val = c
                break
            node.next = ListNode(-1)
            node = node.next

        while len(s2) != 0:
            num = s2[-1] + c
            if num >= 10:
                node.val = num - 10
                c = 1
            else:
                node.val = num
                c = 0
            s2 = s2[:len(s2)-1]
            if len(s2) == 0:
                if c == 1:
                    node.next = ListNode(-1)
                    node = node.next
                    node.val = c
                break
            node.next = ListNode(-1)
            node = node.next
        return self.nx(root)

    def nx(self,root):
        if root is None:
            return None
        pre = None
        next = root.next
        while root:
            root.next = pre
            pre = root
            root = next
            if next:
                next = next.next
        return pre
  1. Delimited list 02
    this problem is fast row in the partition table even realize.
class Solution:
    def partition(self, head, x):
        h1,h2 = ListNode(-1),ListNode(-1)
        dummy = ListNode(-1)
        dummy.next = head
        pre = dummy
        tmp1,tmp2 = h1,h2
        while pre and pre.next:
            tmp = pre.next
            pre.next = None
            pre = tmp
            if tmp.val >= x:
                tmp1.next = tmp
                tmp1 = tmp1.next
            else:
                tmp2.next = tmp
                tmp2 = tmp2.next
        tmp2.next = h1.next
        return h2.next
  1. List II reverse
    this problem pointer drawing more aid more efficient.
class Solution:
    def reverseBetween(self, head, m, n):
        count = 0
        dummy = ListNode(-1)
        pre = dummy
        pre.next = head
        while count < m-1:
            pre = pre.next
            count += 1
        last = pre
        while count < n:
            last = last.next
            count += 1
        cur = pre.next
        next = last.next
        self.reverse(cur, last)
        pre.next = last
        head = dummy.next
        cur.next = next
        return head
    def reverse(self, cur,last):
        last.next = None;
        pre = None
        next = cur.next
        while cur:
            cur.next = pre
            pre = cur
            cur = next
            if next:
                next = next.next
  1. Two numbers together
    using Sentinel mode
class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """

        """
        rem = 0
        dummy = ListNode(0)
        p = dummy
        while l1 or l2 or rem:
            s = (l1.val if l1 else 0)  + (l2.val if l2 else 0) + rem
            rem = s/10
            p.next = ListNode(s%10)
            p = p.next
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next
        return dummy.next
  1. Plus One Linked List (even Table 1 plus operation)
    leetCode payment questions, very simple but very clever. I did not think the original
    idea is to traverse the list to find the first one from the right is not the number 9, if no such number, a description of all numbers are 9, then create a new node value of 0 in the header, processing for adding 1, then all the numbers to the right are set to 0. for example:

Such as 1-> 2-> 3, then the first number is not a 9 to 3, adding 1 to 3, 4 becomes the right node does not, so no processing, returns 1-> 2-> 4.

Another example 8-> 9-> 9, first find the number 9 is not 8, the processing for adding 1 becomes 9, and the latter figure are set to 0, the result obtained 9-> 0-> 0 .

Let's look at the case of 9-> 9-> 9, can not find the number 9 is not, then again in front of a new node is 0, the processing for adding 1 becomes 1, the latter figure are set to 0, to give 1-> 0-> 0-> 0.

class Solution {
public:
    ListNode* plusOne(ListNode* head) {
        ListNode *cur = head, *right = NULL;
        while (cur) {
            if (cur->val != 9) right = cur;
            cur = cur->next;
        }
        if (!right) {
            right = new ListNode(0);
            right->next = head;
            head = right;
        }
        ++right->val;
        cur = right->next;
        while (cur) {
            cur->val = 0;
            cur = cur->next;
        }
        return head;
    }
};
  1. Design Phone Directory (phone design dictionary)
    here , he said very clearly, I do not say that again, mainly on the design of the data structure, in fact, want this issue to whether the most common structure to meet the requirements based on experience, try a combination of inadequate data structures, the key is to define what information you need to know to make you one step closer to the correct answer, it takes practice and summary.

  2. Convert Binary Search Tree to Sorted Doubly Linked
    List to a binary search tree, converted into a double loop table.
    Very classic a question, LeetCode charges, OJ no way to do, just go the local environment. So go with wrote a solution.

This problem using the idea of divide and conquer, recursive implementation. Mode can be regarded as the original problem: the left sub-tree root and ring combined to form a ring, and then combined to form a ring with a right subtree. Thus,
the sub-question is: 1. "left subtree root right subtree" ring, 2 merge.
Recursive base apparently the root node is empty, return directly.
Recursive part is: left and right ring
every thing is done recursively: a root ring, with left and right root three rings, two merging operation is to merge into a circular list of function attached table.

type TreeNode struct {
    Left  *TreeNode
    Right *TreeNode
    Val   int
}
func BST2DLL(root *TreeNode) *TreeNode {
    if root == nil{
        return nil
    }
    aLast  := BST2DLL(root.Left)
    bLast := BST2DLL(root.Right)
    root.Left = root
    root.Right = root
    aLast = Append(aLast,root)
    aLast = Append(aLast,bLast)
    return aLast
}
func Append(a,b *TreeNode) *TreeNode  {
    if a == nil{
        return b
    }
    if b == nil{
        return a
    }
     aLast := a.Left
     bLast := b.Left
     Join(aLast, b)
     Join(bLast, a)
    return a
}
func Join(a, b *TreeNode) {
    a.Right = b
    b.Left = a
}

30. A the Insert INTO A Cyclic circulating the Sorted List ordered linked list insert node point
of this question, the analysis is to examine a variety of conditions, if during the first empty list, is inserted between the maximum and minimum values, less than the minimum or greater than the maximum. The different situations can think clearly. According to the number of axes.
Here in great detail
31. k th group inverted list
by using pointers sentinel reduction operation, using k as a counter control pre, left, right boundary pointer operation. The pointer moves counter to the correct position, inverted list. Clumsy but effective method is relatively simple Haha, after a time optimization, I am still as much rinse title, experience more of the type of data to collect more basic training model.

class Solution:
    def reverseKGroup(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        if k <= 0 or not head or not head.next:
            return head
        dummy = ListNode(-1)
        dummy.next = head
        cur = head
        pre = dummy
        while cur:
            left,right = cur,cur
            for i in range(k-1):
                cur = cur.next
                if cur is None:
                    return dummy.next
                right = cur
            self.nx(pre,left,right)
            cur = left
            pre = left
            cur = cur.next
        return dummy.next
    def nx(self,pre,l,r):
        if not pre or not l or not r or l == r:
            return l
        p ,cur,next = pre,l,l.next
        tmp = r.next
        while cur != tmp:
            cur.next = p
            p = cur
            cur = next
            if next:
                next = next.next
        pre.next = p
        l.next = tmp

32. Merge K sort the list
this question can be very subtle, but I am here to give an intuitive solution of violence, have the opportunity to continue to optimize. This problem can be understood as the largest selection of each node from the list, from which they removed to form a new use of sentinel node, then the list will be updated continuously down generations, finally ending when the list is empty.

class Solution:
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        dummy = ListNode(-1)
        cur = dummy
        while len(lists) != 0:
            index = self.min(lists)
            if not lists[index]:
                del lists[index]
                continue
            cur.next = lists[index]
            if lists[index] and lists[index].next:
                lists[index] = lists[index].next
            else:
                del lists[index]
            cur = cur.next
        return dummy.next
    def min(self,lists):
        m = lists[0]
        index = 0
        i = 1
        while i<len(lists):
            if lists[i] and m and m.val > lists[i].val:
                m = lists[i]
                index = i
            i += 1
        return index

33. The node of the list to delete
and rather clever, you have only given node, there is no pointer predecessor node. Clever use of the assignment of thinking to solve.

class Solution:
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        tmp = node.next
        node.next = node.next.next
        tmp.next = None
        node.val = tmp.val

34. The list of intermediate nodes
would have been in the order of this problem on the front, later I discovered that actually did not write, add it here. Many times before mentioned, the intermediate node, the pointer speed die

class Solution(object):
    def middleNode(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head and not head.next:
            return head
        slow,fast = head,head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
        return slow

Guess you like

Origin www.cnblogs.com/jueyoq/p/11258220.html