1. 程式人生 > >LeetCode算法題-C#代碼實現-鏈表

LeetCode算法題-C#代碼實現-鏈表

get rev link 有序 n) 代碼 str 前驅 sort

19. Remove Nth Node From End of List

刪除倒數第N個結點

解題思路

聲明兩個指針,快指針先移動n次,然後快慢指針同時移動,直到快指針為null。

此時慢指針指向了倒數第n個結點的前驅結點,然後刪除慢指針後繼結點即可。

需要註意的是當刪除倒數第n(n與鏈表長度相同)時,快指針會直接移動到null。

此時需要單獨處理,直接將head指向head的後繼結點即可。

public ListNode RemoveNthFromEnd(ListNode head, int n) {
        ListNode zero=new ListNode(0);
        zero.next
=head; ListNode fast=zero; ListNode slow=zero; //若鏈表只有一個結點,直接清空 if(head.next==null){ head=null; return head; }//將快指針放向前移動n次 for(int i=1;i<=n+1;i++) fast=fast.next; //如果快指針已經為空,說明清除的是第一個結點,直接將head指向其後繼結點
if(fast==null){ head=head.next; return head; } //循環遍歷鏈表直到快指針到達尾部 while(fast!=null){ fast=fast.next; slow=slow.next; } //此時slow的後繼結點為要刪除的倒數第n個結點 slow.next=slow.next.next; return
zero.next; }

21. Merge Two Sorted Lists

合並兩個有序鏈表

解題思路

使用遞歸方法調用自身,讓結點一直遞歸到兩個鏈表中其中一個比另一個尾部的結點大的結點。

到最後一次調用自身,會觸發兩個if中的一個,返回鏈表剩余的結點。

每次返回鏈表的首節點都會成為上一個結點的後繼結點,不斷返回後,就實現了兩個鏈表有序的合並。

public ListNode MergeTwoLists(ListNode l1, ListNode l2) {
        if(l1==null)return l2;
        if(l2==null)return l1;
        ListNode newList=null;
        //遞歸調用自身,遞歸到兩鏈表中最後剩的最大的鏈表,賦值為前一個小值的next
        if(l1.val<=l2.val){
                newList=l1;
                newList.next=MergeTwoLists(l1.next,l2);
        }
        else{
                newList=l2;
                newList.next=MergeTwoLists(l1,l2.next);
        }
        return newList;
}

141. Linked List Cycle

檢查鏈表中是否有環

解題思路

使用快慢指針,快指針一次步進慢指針的n倍,如果存在環,二者會不斷循環,最終會有追上且二者相等的情況。

如果不存在環,快指針或快指針的後繼結點肯定會等於null,返回false。

public bool HasCycle(ListNode head) {
        //快慢指針檢測單鏈表中是否存在環
        if(head==null||head.next==null)return false;
        //快指針一次前進n倍慢指針的步數
        ListNode fastNode=head.next;
        ListNode slowNode=head;
        //如果存在環,二者一定會碰上,得到相等的情況
        while(fastNode!=slowNode){
                if(fastNode==null||fastNode.next==null)return false;
                fastNode=fastNode.next.next;
                slowNode=slowNode.next;
        }
        return true;
}

206. Reverse Linked List

反轉鏈表

解題思路

反轉鏈表的核心就是讓等待被提到前面的結點標記為當前結點,讓等待別的結點到自己前面的結點稱為前驅結點,記錄下當前結點的後繼結點。

然後將當前結點提到前驅結點前,第一次循環時,鏈表會斷開。然後更新當前結點、前驅結點。

之後的循環每次都是先記錄下當前結點的後繼結點作為下一次循環的當前結點,再執行提前和更新操作。

public ListNode ReverseList(ListNode head) {
        if(head==null)return head;
        ListNode pre=head;
        ListNode cur=head.next;
        ListNode temp;
        while (cur!= null)
        {
                //第一次循環時將第二個結點提到第一個節點前,此時鏈表斷開。
                //之後的循環就是不斷將後部分的首結點提到前部分的首位。
                //同時更新pre、cur和temp指針為前部分的首結點、後部分的首結點和後部分首結點的後繼結點。 
                temp=cur.next;//設置後繼結點指針
                cur.next=pre;//將當前結點提到前驅結點前
                pre=cur;//設置前驅結點指針
                cur=temp;//設置當前結點指針
        }
        head.next=null;
        return pre;
}

876. Middle of the Linked List

獲取鏈表的中間結點

解題思路

獲取其中間結點我也是使用了快慢指針,讓快慢指針都以後繼結點為head出發。

快指針步進為慢指針的二倍,快指針或快指針的後繼結點為null就返回慢指針,慢指針即為中間結點。

public ListNode MiddleNode(ListNode head) {
        ListNode zero = new ListNode(0);
        zero = head;
        //快指針和慢指針以head為next開始
        ListNode fast = zero;
        ListNode slow = zero;
        if (head.next == null)
                return head;
        while (true)
        {
                //快慢指針步進
                fast = fast.next.next;
                slow = slow.next;
                //直到快指針為null或快指針的後繼結點為null,返回慢指針指向的結點
                if (fast == null||fast.next == null)
                        return slow;
        }
}

LeetCode算法題-C#代碼實現-鏈表