訓練營day04:鏈表2

24. 兩兩交換鏈表中的節(jié)點

https://leetcode.cn/problems/swap-nodes-in-pairs/description/
一道模擬題,我的第一版解法

// 雙指針不斷移動,交換數(shù)據(jù)
class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode left = head;
        ListNode right = head.next;
        ListNode preRight = null;
        head = right;
        while (left != null && right != null) {
            ListNode tmp = right.next;
            left.next = tmp;
            right.next = left;
            if (preRight != null) {
                preRight.next = right;
            }
            if (tmp == null) {
                break;
            } else {
                preRight = left;
                left = tmp;
                right = tmp.next;
            }
        }
        return head;
    }
}

卡哥更簡潔的解法

class Solution {
  public ListNode swapPairs(ListNode head) {
        ListNode dumyhead = new ListNode(-1); // 設置一個虛擬頭結(jié)點
        dumyhead.next = head; // 將虛擬頭結(jié)點指向head,這樣方便后面做刪除操作
        ListNode cur = dumyhead;
        ListNode temp; // 臨時節(jié)點,保存兩個節(jié)點后面的節(jié)點
        ListNode firstnode; // 臨時節(jié)點,保存兩個節(jié)點之中的第一個節(jié)點
        ListNode secondnode; // 臨時節(jié)點,保存兩個節(jié)點之中的第二個節(jié)點
        while (cur.next != null && cur.next.next != null) {
            temp = cur.next.next.next;
            firstnode = cur.next;
            secondnode = cur.next.next;
            cur.next = secondnode;       // 步驟一
            secondnode.next = firstnode; // 步驟二
            firstnode.next = temp;      // 步驟三
            cur = firstnode; // cur移動,準備下一輪交換
        }
        return dumyhead.next;  
    }
}

題后感:
1.和卡哥的解法邏輯上是一致的,但我的代碼不夠簡潔
2.鏈表題一定要畫圖,否則很容易繞暈
3.學會使用虛擬節(jié)點方法,在鏈表題中卡哥基本都用到了

19.刪除鏈表的倒數(shù)第N個節(jié)點

https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
該題用非常高頻使用的快慢指針的解法,比較簡單

// 第一版解法 - 沒有使用虛擬節(jié)點,需要處理只有一個元素的邊界情況
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if (n <= 0) {
            return head;
        }
        if (head.next == null && n == 1) {
            head = null;
            return head;
        }
        ListNode slow = head;
        ListNode fast = head;
        // 快走n步
        for (int i = 0; i <= n; i++) {
            fast = fast.next;
        }
        // 開始移動判斷,快指針不是最后一個元素
        while(fast != null) {
            slow = slow.next;
            fast = fast.next;
        }
        // 刪除元素
        slow.next = slow.next.next;
        return head;
    }
}
// 第二版解法 - 使用虛擬節(jié)點
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode fakeNode = new ListNode(0);
        fakeNode.next = head;

        ListNode slow = fakeNode;
        ListNode fast = fakeNode;
        // 快走n步
        for (int i = 0; i <= n; i++) {
            fast = fast.next;
        }
        // 開始移動判斷,快指針不是最后一個元素
        while(fast != null) {
            slow = slow.next;
            fast = fast.next;
        }
        // 刪除元素
        slow.next = slow.next.next;
        // !!!!注意最后返回值
        return fakeNode.next;
    }
}

面試題 02.07. 鏈表相交

https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int lenA = 0;
        int lenB = 0;
        ListNode curA = headA;
        ListNode curB = headB;
        while (curA != null) {
            lenA++;
            curA = curA.next;
        }
        while (curB!= null) {
            lenB++;
            curB = curB.next;
        }
        curA = headA;
        curB = headB;
        int step = 0;
        if (lenA - lenB >= 0) {
            step = lenA - lenB;          
        } else {
            step = lenB - lenA;
            curA = headB;
            curB = headA;
        }
        while(step > 0) {
            curA = curA.next;
            step--;
        }

        while (curA != null && curB != null) {
            if (curA == curB) {
                return curA;
            } 
            curA = curA.next;
            curB = curB.next;
        }

        return null; 
    }
}

這道題剛開始沒想到先計算長度差、長鏈表快走n步的方法,也想了很久,知道解法就好做??右采?。代碼邏輯基本一致。

142.環(huán)形鏈表II

https://leetcode.cn/problems/linked-list-cycle-ii/description/
判斷是否有環(huán),如果有環(huán),返回入環(huán)的第一個節(jié)點
(若干年前畢業(yè)找工作的時候《劍指offer》里看到過?)

// 看完解法之后的版本
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }
        // 判斷是否有環(huán)
        ListNode slow = head;
        ListNode fast = head;
        ListNode seeNode = null;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                seeNode = slow;
                break;
            }
        }
        // 找環(huán)入口
        if (seeNode == null) {
            return null;
        }
        ListNode tmpNode = head;
        while (tmpNode != null) {
            if (tmpNode == seeNode) {
                return tmpNode;
            }
            tmpNode = tmpNode.next;
            seeNode = seeNode.next;
        }

        return null;
    }
}
// 卡哥簡潔版
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {// 有環(huán)
                ListNode index1 = fast;
                ListNode index2 = head;
                // 兩個指針,從頭結(jié)點和相遇結(jié)點,各走一步,直到相遇,相遇點即為環(huán)入口
                while (index1 != index2) {
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}

題后感
1.快慢指針檢測有環(huán)這個解法是之前就知道的,但是求入口環(huán)不知道,沒想到還要列公式,不知道實際面試的時候難道還得自己推導一遍嗎?
2.自己看完題的解法之后第一個版本問題在判斷是否有環(huán)的條件上
初始化時,對slow及fast的賦值是在外面還是在里面,如果在while之外初始化的時候就賦值,那需要單獨判斷next的有效性,while條件里也要判斷,這個時候就有重復了,不簡潔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容