Single list summarizes the typical problems

1, equal to a given value to delete the list  ** val **  all nodes. 

Analysis of ideas:

Define two auxiliary pointers prev and cur, can be deleted when prev.next.data = val

Mainly do not forget to deal with the first node

 public void removeAllKey(int key) {
        ListNode prev = this.head;
        ListNode cur = this.head.next;
        while(cur != null) {
            if (prev.next.data == key) {
                prev.next = cur.next;
                cur = cur.next;
            } else {
                prev = cur;
                cur = cur.next;
            }
        }
        //处理第一个节点--最后处理
        if (this.head.data == key) {
            this.head = this.head.next;
        }
    }

 

2. Reverse a singly-linked list.

 
① define the secondary pointer cur, prev, curNext. Cur let go backwards, cur.next = prev
                                                                                    prev = cur
                                                                                    cur = curNext
② till the end will find curNext is empty, cur points to the node is the new head.
 
note:
A. Next header field set to take the original node is empty
 
 
 public ListNode reverseList() {
        if(this.head == null) {
            return null;
        }
        ListNode cur = this.head;
        ListNode prev = null;
        ListNode newHead = null;
        while (cur != null) {
            ListNode curNext = cur.next;
            if (curNext == null) {
                newHead = cur;
            }
            cur.next = prev;
            prev = cur;
            cur = curNext;
        }
        return newHead;
    }
3. Given the head node having a head non-empty single linked list, returns the list of intermediate nodes. If there are two intermediate nodes, the second intermediate node is returned.
 
Analysis of ideas: speed pointer law. (Only traverse the list again)
 
   public ListNode middleNode() {
//        ListNode cur = this.head;
//        int length = getlength()/2;
//        for (int i = 0; i < length; i++) {
//            cur = cur.next;
//        }
//        return cur;
        ListNode fast = this.head;
        ListNode slow = this.head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
4. Enter a linked list, the linked list output penultimate k nodes.
 
Analysis of ideas:
Let go fast pointer k-1 step, and then let the fast and slow pointer while the pointer to go. Node to the finish, where the fast-slow-pointer pointer is an intermediate node.

 

Note: first determining whether a valid k , most efficient way is to take the step up to the number of nodes -1, so fast while the pointer is determined to be walking, fast.next = null; k illegal instructions to return null.

 
 public ListNode FindKthToTail(int k) {
        if (k <= 0 || this.head == null) {
            return null;
        }
        ListNode fast = this.head;
        ListNode slow = this.head;
        for (int i = 0; i < k-1; i++) {
            if (fast.next == null) {
                return null;
            }
            fast = fast.next;
        }
        while(fast.next != null) {
            fast = fast.next;
            slow = slow.next;

        }
        return slow;
    }
5. The two ordered lists into a new list is ordered and returns. The new list is by all nodes in a given mosaic composed of two lists.
 
Analysis of ideas:
To merge when ordered list headA and headB. Create a virtual node newHead, the data headA and headB nodes are compared, the smaller data is added newHead list head node.
 
note:
To determine if a list is empty, the list is added directly to the other
 
 public static ListNode mergeTwoLists1(ListNode headA, ListNode headB){
        ListNode newHead = new ListNode(-1);
        ListNode tmp = newHead;
        while (headA != null && headB != null) {
            if (headA.data < headB.data) {
                tmp.next = headA;
                headA = headA.next;
                tmp = tmp.next;
            } else {
                tmp.next = headB;
                headB = headB.next;
                tmp = tmp.next;
            }
        }
       //如果a为空
        if (headA == null) {
            tmp.next = headB;
        } else {
            tmp.next = headA;
        }
        return newHead.next;
    }

6, write code to the given value x is divided into two parts for the reference will list all smaller than the x node is greater than or equal to the row x previous node.

Thinking Analysis:
① First, there must be two references beginStart and beginEnd, afterStart and afterEnd
② when the data list node k h ratio, beginStart into the node pointed to by the linked list node when the data is larger than k, into afterStart points to the node.
Put the time to pay attention to whether the first release.
③ to link the beginEnd and afterStart 

Looks like the end, in fact, missed two questions:
. If the A list, in all less than k, then return bs no problem. . However, if all the elements in the list is greater than k, bs description is empty, as can be directly returned, plus a determination.
b. When we return bs time, you will find printed lists termination condition is null, but when the list is done and, ae.next not necessarily empty, so we want ae.next last set is empty. So be feasible Hey ~

  

 public ListNode partition(int x){
        ListNode bs = null;
        ListNode be = null;
        ListNode as = null;
        ListNode ae = null;
        ListNode cur = this.head;
        while (cur != null) {
            if (cur.data < x) {
                //判断是否为第一次加入
                if (bs == null) {
                    bs = cur;
                    be = cur;
                } else {
                    be.next = cur;
                    be = be.next;
                }
            } else {
                //判断是否为第一次加入
                if (as == null) {
                    as = cur;
                    ae = cur;
                } else {
                    ae.next = cur;
                    ae = ae.next;
                }
            }
            cur = cur.next;
        }
       //连在一起
        if (be.next != null) {
            be.next = as;
        }
        //判断是否k是否小于所以节点
        if (bs == null) {
            return as;
        }
        if (as != null) {
            ae.next = null;
        }
        return bs;
}

7. In a sorted linked list nodes duplicate, delete the duplicate node list, the node does not retain repeated, returns the head pointer list.

Thinking Analysis:
① find duplicate nodes, define a single auxiliary variable cur traversal list, if the node cur.data = DESCRIPTION cur.next.data have duplicate data. However, note repeated more than one node, so use cycle is determined.
② remove duplicate node

Note:
. A judge must determine when each judge cur.data == cur.next.data cur.next is null. Otherwise it will cause a null pointer exception.
. b If the last repeating node is also a node, then to tmp.next = null;

  public ListNode deleteDuplication(){
        ListNode cur = this.head;
        ListNode newHead = new ListNode(-1);
        ListNode tmp = newHead;
        while (cur != null) {
            //重复的节点
            if(cur.next != null && cur.data == cur.next.data) {
                //每一次都需要判断cur.next
                while (cur.next != null && cur.data == cur.next.data) {
                    cur = cur.next;
                }
                cur = cur.next;
            } else {
                tmp.next = cur;
                tmp = tmp.next;
                cur = cur.next;
            }
        }
        //最后一个节点如果也是重复的,需要将tmp.next置为空
        tmp.next = null;
        return newHead.next;
    }

 8. palindrome list.

Palindrome is counting down and the same number have come out with a positive sequence of numbers. Such as 12321, 1221
How to determine the palindrome list it?
 
Analysis of ideas:
① find the list of intermediate nodes
② reverse list
③fast / slow forward head next to go
 
note:
a. To determined that even figures
b. To pay attention to reverse a linked list fast and fast.next empty case
 
 
    //单链表判断回文数
    public boolean chkPalindrome() {
        //为空
        if (this.head == null) {
            return false;
        }
        //一个数
        if (head.next == null) {
            return true;
        }
        //1、找到单链表的中间节点
        ListNode fast = this.head;
        ListNode slow = this.head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        //2、反转单链表
        ListNode cur = slow.next;
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.next = slow;
            slow = cur;
            cur = curNext;
        }
        //3、fast/slow往前    head往后走
        while (this.head != slow) {
            if (this.head.data != slow.data) {
                return false;
            }
            //偶数个数
            if (this.head.next == slow) {
                return true;
            }
            this.head = this.head.next;
            slow = slow.next;
        }
        return true;
    }

9. Enter the two lists, find their first common node.

思路分析:
①将pL指向长链表,pL指向短的链表
②让长链表先走差值步
③分别一步一步走,如果节点相同就为相交

注意:
注意计算完长度后pS、pL重新赋值,还有最后循环退出的条件

    public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null) {
            return null;
        }
        ListNode pL = headA;//永远指向长的单链表
        ListNode pS = headB;//永远指向短的单链表
        int lenA = 0;
        int lenB = 0;
        //求的lenA  lenB
        while (pL != null) {
            lenA++;
            pL = pL.next;
        }
        while (pS != null) {
            lenB++;
            pS = pS.next;
        }
        //pl、ps为空了
        pL = headA;
        pS = headB;
        //差值-》最长的单链表先走len步
        int len = lenA-lenB;
        if(len < 0) {
            pL = headB;
            pS = headA;
            len = lenB-lenA;
        }
        //让pL先走len步
        for (int i = 0; i < len; i++) {
            pL = pL.next;
        }
        //开始一起走  (pL  != pS ) {一人一步走}
        while (pL != pS) {
            pL = pL.next;
            pS = pS.next;
        }
//        if (pL == null) {
//            return null;
//        }
//        return pL;
        return pL;
    }

 

10. 给定一个链表,判断链表中是否有环。 
 

判断链表是否有环可以使用快慢指针法,快的每次走两步,慢的每次走一步。若快的和慢的相遇则有环。

 //判断链表是否有环
    public boolean hasCycle() {
        ListNode fast = this.head;
        ListNode slow = this.head;
        while (fast != null && fast.next != null)  {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                break;
            }
        }
        if (fast == null || fast.next ==null) {
            return false;
        }
        return true;
    }

 //创造一个环
    public void creteLoop() {
        ListNode cur = this.head;
        while (cur.next != null) {
            cur = cur.next;
        }
        cur.next = this.head.next;
    }

 

11. 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

当slow=fast时,将slow指向头节点。slow和fast同时往后走,当slow和fast相等时的节点就是链表开始入环的第一个节点。

 public ListNode detectCycle() {
        ListNode fast = this.head;
        ListNode slow = this.head;
        while (fast != null && fast.next != null)  {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                break;
            }
        }
        if (fast == null || fast.next ==null) {
            return null;
        }
        slow = this.head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }

证明:画图

12、给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的深拷贝。 

思路分析:
①老新进行进行交替链接
②修改random
③将老新节点打开

 public Node copyRandomList(Node head) {
        if(head == null) {
            return null;
        }
        Node cur = head;
        //1、老新进行进行交替链接
        while(cur != null) {
            Node node = new Node(cur.val, cur.next, null);
            Node tmp = cur.next;
            cur.next = node;
            cur = tmp;
        }
        //2、修改random
        cur = head;
        while(cur != null) {
            if(cur.random != null) {
                cur.next.random = cur.random.next;
                cur = cur.next.next;
            } else {
                cur = cur.next.next;
            }
        }
        //3、将老新节点打开
        cur = head;
        Node newHead = cur.next;
        while(cur.next != null) {
            Node tmp = cur.next;
            cur.next = tmp.next;
            cur = tmp;
        }
        return newHead;
    }

 

最近做了挺多单链表的题,感觉虽然有的题目思路并不是特别难,但是一不小心就会造成空指针异常,因此做单链表的题要考虑全面,包括单链表的头、尾以及单链表是否为空,next是否为空。。。。

 

发布了51 篇原创文章 · 获赞 14 · 访问量 2321

Guess you like

Origin blog.csdn.net/qq_41185460/article/details/102996216