【LeetCode】初級演算法:連結串列

widiot1發表於2018-05-11

題目可以在LeetCode檢視

1. 刪除連結串列的結點

用時:0ms

class Solution {
    public void deleteNode(ListNode node) {
        node.val=node.next.val;
        node.next=node.next.next;
    }
}

2. 刪除連結串列的倒數第N個節點

用時:10ms

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode curNode=head;
        ListNode nNode=head;
        int count=1;
        while(curNode.next!=null){
            // 如果刪除末尾結點,則判斷當前結點是否是倒數第二個結點
            if(n==1&&curNode.next.next==null){
                curNode.next=null;
                return head;
            }
            // 如果和當前結點中間的結點數為n,則移動nNode
            if(count==n){
                nNode=nNode.next;
            }else{
                ++count;
            }
            curNode=curNode.next;
        }
        // 如果只有一個結點
        if(nNode==head&&n==1){
            return null;
        }
        // 刪除該結點
        nNode.val=nNode.next.val;
        nNode.next=nNode.next.next;
        return head;
    }
}

3. 反轉連結串列

用時:0ms

class Solution {
    public ListNode reverseList(ListNode head) {
        // 用時:0ms
        // // 如果是空連結串列或者單結點則直接返回
        // if(head==null||head.next==null){
        //     return head;
        // }
        // // 反轉框包含三個結點
        // ListNode pre=null;
        // ListNode cur=head;
        // ListNode nxt=head.next;
        // while(true){
        //     // 反轉結點
        //     cur.next=pre;
        //     pre=nxt.next;
        //     nxt.next=cur;
        //     // 如果當前反轉框是最後一個
        //     if(pre==null){
        //         return nxt;
        //     }
        //     // 移動反轉框
        //     cur=pre.next;
        //     // 連線上一個反轉框的nextNode
        //     pre.next=nxt;
        //     // 如果下個反轉框為一個結點
        //     if(cur==null){
        //         return pre;
        //     }
        //     // 如果下個反轉組為兩個結點
        //     if(cur.next==null){
        //         cur.next=pre;
        //         return cur;
        //     }
        //     // 否則繼續移動反轉框
        //     nxt=cur.next;
        // }
        
        // 如果是空連結串列或者單結點則直接返回
        if(head==null||head.next==null){
            return head;
        }
        return recursive(null,head,head.next);
    }
    
    public ListNode recursive(ListNode pre,ListNode cur,ListNode nxt){
        // 反轉結點
        cur.next=pre;
        pre=nxt.next;
        nxt.next=cur;
        // 如果當前反轉框是最後一個
        if(pre==null){
            return nxt;
        }
        // 移動反轉框
        cur=pre.next;
        // 連線上一個反轉框的nextNode
        pre.next=nxt;
        // 如果下個反轉框為一個結點
        if(cur==null){
            return pre;
        }
        // 如果下個反轉組為兩個結點
        if(cur.next==null){
            cur.next=pre;
            return cur;
        }
        // 否則繼續移動反轉框
        nxt=cur.next;
        return recursive(pre,cur,nxt);
    }
}

4. 合併兩個有序連結串列

用時:12ms

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode newHead=null;
        ListNode newPre=null;
        ListNode newCur=null;
        // 如果有一個連結串列為空,則返回另一個
        if(l1==null){
            return l2;
        }else if(l2==null){
            return l1;
        }
        // 先將兩者之間較小的合併
        while(l1!=null&&l2!=null){
            if(l1.val>=l2.val){
                newCur=new ListNode(l2.val);
                l2=l2.next;
            }else{
                newCur=new ListNode(l1.val);
                l1=l1.next;
            }
            // 儲存頭結點
            if(newHead==null){
                newHead=newCur;
            }
            if(newPre!=null){
                newPre.next=newCur;
            }
            newPre=newCur;
        }
        
        // 再將剩下的合併
        while(l1!=null){
            newCur=new ListNode(l1.val);
            newPre.next=newCur;
            newPre=newPre.next;
            l1=l1.next;
        }
        while(l2!=null){
            newCur=new ListNode(l2.val);
            newPre.next=newCur;
            newPre=newPre.next;
            l2=l2.next;
        }
        
        return newHead;
    }
}

5. 迴文連結串列

用時:2ms

class Solution {
    public boolean isPalindrome(ListNode head) {
        if(head==null||head.next==null){
            return true;
        }
        int len=0;
        ListNode curNode=head;
        // 計算連結串列長度
        while(curNode!=null){
            ++len;
            curNode=curNode.next;
        }
        // 找到中間結點
        ListNode cntNode=head;
        for(int i=1;i<len/2;++i){
            cntNode=cntNode.next;
        }
        // 反轉右邊子連結串列
        ListNode reverseHead=cntNode.next;
        cntNode.next=null;
        if(reverseHead.next!=null){
            reverseHead=recursive(null,reverseHead,reverseHead.next);
        }
        // 逐個比較
        curNode=head;
        ListNode reverseCurNode=reverseHead;
        for(int i=0;i<len/2;++i){
            if(curNode.val!=reverseCurNode.val){
                return false;
            }
            curNode=curNode.next;
            reverseCurNode=reverseCurNode.next;
        }
        return true;
    }

    public ListNode recursive(ListNode pre,ListNode cur,ListNode nxt){
        // 反轉結點
        cur.next=pre;
        pre=nxt.next;
        nxt.next=cur;
        // 如果當前反轉框是最後一個
        if(pre==null){
            return nxt;
        }
        // 移動反轉框
        cur=pre.next;
        // 連線上一個反轉框的nextNode
        pre.next=nxt;
        // 如果下個反轉框為一個結點
        if(cur==null){
            return pre;
        }
        // 如果下個反轉組為兩個結點
        if(cur.next==null){
            cur.next=pre;
            return cur;
        }
        // 否則繼續移動反轉框
        nxt=cur.next;
        return recursive(pre,cur,nxt);
    }
}

6. 環形連結串列

用時:1ms

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode slow=head;
        ListNode fast=head;
        // 快慢車問題,快的總會追上慢的
        while(fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
            if(slow==fast){
                return true;
            }
        }
        return false;
    }
}

相關文章