1. 程式人生 > >LintCode連結串列題總結

LintCode連結串列題總結

由於連結串列本身結構的單一性,連結串列的題目很少會有很大的變種,基本都是圍繞幾個基本的考點出題目。所以連結串列的題目比較好掌握,但是連結串列的題目又不太容易一次就AC通過,由於邊界情況未考慮、空指標(比如head.next不存在但是卻給head.next賦值了,就會丟擲nullpointer的錯誤)、越界等邊界情況,我們需要在測試用例的時候多考慮邊界條件。在模擬計算的時候一定要用紙和筆把中間的操作過程給畫出來,這樣比較容易形成思路。

在LintCode的ladder1中,連結串列那一章有如下這一些題目:



基本上把這些題目做完,連結串列的題目就差不多十拿九穩了。

我們來一道一道看看這幾道題的解法。

這道題是要刪除連結串列的倒數第n個節點,也就是從連結串列末尾開始計數。是一道典型的雙指標/快慢指標解法題,就預先將2個指標設定相互之間的距離為n,然後同時遍歷連結串列,當fast快指標的下一個節點是null的時候,slow慢指標的下一個元素就是要刪除的節點了。然後把slow的next設定為要刪除的節點的下一個節點就OK了。但是需要考慮幾個特殊情況,a)當輸入的n小於等於0的時候 || 當輸入的n大於連結串列長度的時候 || 連結串列為空 || 連結串列只有一個節點的時候,返回null;b)當n等於連結串列長度(即要刪除的是第一個節點的時候),返回head的next就好。(這道題如果用加dummy節點的做法來做的話,程式碼會簡潔一些。)

這道題對連結串列進行分割槽,對於輸入的x,連結串列中所有value小於x的節點都在x的左邊,所有value大於x的節點都在x的右邊。這道題我的解法很直白,就是直接新鍵2個dummy節點,分別用於存放連結串列中小於x的節點和連結串列中大於等於x的節點。然後把這兩個list合併起來,返回就好。(注意考慮連結串列為空返回null)

這道題要在有序連結串列中刪除重複的元素,所有的重複元素都要刪除。思路也很簡單,就是遍歷連結串列,記得用dummy節點。從頭結點掃描到尾節點,中間如果一旦找到重複的就開始一個子迴圈,子迴圈裡面做刪除操作(即將當前的next指向下一個節點的next)。(注意考慮連結串列為空 || 連結串列只有一個元素 返回null)

這道題要把一個有序連結串列轉換為平衡二叉搜尋樹。我的程式碼如下:

    private TreeNode buildTree(ListNode begin, ListNode end) {
        if (begin == end) {
            return null;
        }
        ListNode fast = begin, slow = begin;
        while (fast.next != end && fast.next.next != end) {
            slow = slow.next;
            fast = fast.next.next;
        }
        
        fast = slow.next;
        
        TreeNode root = new TreeNode(slow.val);
        root.left = buildTree(begin, slow);
        root.right = buildTree(fast, end);
        
        return root;
    }
    public TreeNode sortedListToBST(ListNode head) {  
        if (head == null) {
            return null;
        }
        if (head.next == null) {
            return new TreeNode(head.val);
        }
        return buildTree(head, null);
    }
還是得用遞迴來做這種題目,遞迴函式的2個引數為開始節點和結束節點。遞迴函式裡面,如果當前區間長度為0就返回null。然後開始尋找區間的中點,找到中點後,就把它設定為當前的root根節點。然後當前root的left節點和right節點分別再呼叫遞迴函式進行。可能有點點繞,可以先在紙上自己多模擬幾遍,然後就可以懂了。

這道題就是要對一個連結串列進行深拷貝,不過這不是一個簡單的連結串列,每個連結串列節點除了有next指標外,還有一個random指標指向隨機的元素。思路就是對於next節點先做一次拷貝,存放在原節點後面。然後再對random指標進行拷貝(說是拷貝,其實是改變random指標所指的節點)。然後再對原連結串列進行split操作就可以了。可以對照著程式碼在紙上畫一畫模擬操作就更加明白了:


程式碼如下:

    private void copyNext(RandomListNode head) {
        while (head != null) {
            RandomListNode tmp = new RandomListNode(head.label);
            tmp.next = head.next;
            tmp.random = head.random;
            head.next = tmp;
            head = head.next.next;
        }
    }
    private void copyRandom(RandomListNode head) {
        while (head != null) {
            if (head.next.random != null) {
                head.next.random = head.random.next;
            }
            head = head.next.next;
        }
    }
    private RandomListNode splitList(RandomListNode head) {
        RandomListNode newHead = new RandomListNode(0);
        newHead.next = head;
        RandomListNode toReturn = newHead;
        while (newHead.next != null) {
            newHead.next = newHead.next.next;
            newHead = newHead.next;
        }
        // newHead.next = null;
        return toReturn.next;
    }
    public RandomListNode copyRandomList(RandomListNode head) {
        if (head == null) {
            return null;
        }
        copyNext(head);
        copyRandom(head);
        return splitList(head);
    }

我的思路就是不斷地兩兩之間merge,這樣進行k-1次兩兩之間的merge操作就可以了。

這道題對連結串列進行重新排序,原連結串列為:L0 → L1 → … → Ln-1 → Ln;要將它變為:L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …

我的思路就是先對原連結串列進行反轉,然後再逐個的把原連結串列和反轉連結串列進行合併。合併不需要遍歷完整個連結串列,只需要遍歷到一半就好,所以還需要一個函式來計算一下連結串列長度。

對連結串列進行排序,建議最好分別用歸併排序和快排實現一次。歸併排序簡單一點,快排稍微難一點。這道題一下子還是挺難寫出來的,建議多看看程式:http://www.jiuzhang.com/solutions/sort-list/

這道題對連結串列進行區間內的反轉。比如給定 1->2->3->4->5->NULL, m = 2 並且 n = 4, 需要返回 1->4->3->2->5->NULL

和反轉全部連結串列的程式碼區別就在於需要找到反轉開始的地方和結束的地方。程式碼如下:

public ListNode reverseBetween(ListNode head, int m , int n) {
        if (head == null || head.next == null) {
            return head;
        }
        
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        head = dummy;
        
        for (int i = 1; i < m; i++) {
            if (head == null) {
                return null;
            }
            head = head.next;
        }
        
        ListNode newHead = head;
        head = head.next;
        ListNode tail = head;
        ListNode prev = null;
        
        for (int i = m; i <= n; i++) {
            ListNode tmp = head.next;
            newHead.next = head;
            head.next = prev;
            prev = head;
            head = tmp;
        }
        tail.next = head;
        
        return dummy.next;
    }


找到一個連結串列中迴圈開始的節點。

Like the picture shows below: assume linked list has cycle,the length of cycle is Y,the length outside cycle is X

two pointers, one goes one step per time, another goes two steps per time. If they went t times and meet at the K node

for pointer 1: t = X+nY+K

for pointer 2: 2t = X+mY+K (m,n is unknown)

From above equation, we could get:

2X + 2nY + 2K = X + mY + K

=> X+K = (m-2n)Y

It is clear that the relationship between X and K is complementary based on Y. Which is to say, if pointer 1 goes X steps from start node and pointer 2 goes X steps form K node. They will meet at the start place of cycle. Complexity is O(n)

數學證明如上所示,所以如果用快慢指標,然後快慢指標在某個點相遇了之後,我從頭結點走k步,同時慢指標也走k步,他兩將在迴圈開始的地方相遇。

程式碼如下所示:

    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)
        		break;
        }
        if(fast == null || fast.next == null)
        	return null;
        slow = head;
        while(slow != fast){
        	slow = slow.next;
        	fast = fast.next;
        }
        return fast;
    }

需要注意的是,如果我們將快慢指標初始化為fast = slow.next的話,那麼為了處理迴圈開始的地方是頭結點head的情況,程式碼應該如下這麼寫才對:
    public ListNode detectCycle(ListNode head) {  
        if (head == null || head.next == null) {
            return null;
        }
        
        ListNode fast = head.next, slow = head;
        
        while (slow != fast) {
            if (fast == null || fast.next == null) {
                return null;
            }
            fast = fast.next.next;
            slow = slow.next;
        }
        
        while (head != slow.next) {
            slow = slow.next;
            head = head.next;
        }
        return head;
    }

讀者可以在紙上畫畫,細細體味其中的奧妙。

比較簡單,找到連結串列的中點,用快慢指標掃描,當快指標到達連結串列末尾時,返回慢指標就可以了。

比較簡單,刪除連結串列中所有等於給定val的節點,遍歷一次連結串列,如果發現有節點的val等於指定val,就刪除它(previous的next指向下一個)。需要用到dummy節點。

比較簡單,刪除無序連結串列中的重複元素,需要用到HashSet和dummy節點。如果元素在HashSet中出現了就刪除,未出現就加入HashSet。

比較簡單,成對的交換連結串列中的節點,每兩兩之間交換位置。1->2->3->4 變為 2->1->4->3。需要用到dummy節點,然後遍歷連結串列,兩兩之間互換元素。

比較簡單,給定連結串列中的某個節點,要求只刪除它。由於沒法從頭遍歷整個連結串列,所以無從得知那個節點前面的節點是啥。所以只有把要刪除的節點的val設定為下一個節點的val,然後再把它給remove掉。

對連結串列進行插入排序,需要用到dummy節點。注意到插入排序的精髓就是當前的連結串列一定是有序的,然後需要插入的新節點就從前往後遍歷,找到它合適的位置插入,如此迴圈往復。

對連結串列的節點進行加法運算,Given 7->1->6 + 5->9->2. That is, 617 + 295. Return 2->1->9. That is 912. Given 3->1->5 and 5->9->2, return 8->0->8

增加一個carry進位變數,然後同時遍歷兩個連結串列進行模擬加法運算,最後如果兩個連結串列遍歷完後有剩餘,再把剩餘的節點加上去就好。程式碼如下:

    public ListNode addLists(ListNode l1, ListNode l2) {
        if (l1 == null || l2 == null) {
            return null;
        }
        
        ListNode head = new ListNode(0);
        ListNode p = head;
        
        int carry = 0;
        while (l1 != null && l2 != null) {
            int sum = l1.val + l2.val + carry;
            carry = sum / 10;
            sum = sum % 10;
            p.next = new ListNode(sum);
            p = p.next;
            l1 = l1.next;
            l2 = l2.next;
        }
        
        while (l1 != null) {
            int sum = l1.val + carry;
            carry = sum / 10;
            sum = sum % 10;
            p.next = new ListNode(sum);
            p = p.next;
            l1 = l1.next;
        }
        
        while (l2 != null) {
            int sum = l2.val + carry;
            carry = sum / 10;
            sum = sum % 10;
            p.next = new ListNode(sum);
            p = p.next;
            l2 = l2.next;
        }
        
        if (carry != 0) {
            p.next = new ListNode(carry);
        }
        
        return head.next;
    }

比較簡單,返回連結串列的倒數第n個節點。用快慢指標法,快慢指標初始化為相距n,然後同時遍歷連結串列。當快指標到達末尾的時候,返回慢指標即可。

比較簡單,對兩個有序連結串列進行合併。用到dummy節點,然後逐個遍歷2個節點,小的放在前,大的放在後。如果後面還有剩餘,就再把剩餘的元素加進連結串列來。

比較簡單,刪除有序連結串列裡的重複元素。如果下一個元素與當前元素相等,就把當前元素的next指標往後移,如此迴圈往復,直到掃描到尾節點為止。

反轉連結串列,用到dummy節點程式碼量會簡潔一點。就是不斷地把元素加到dummy節點的後邊。注意銜接前後的程式碼判斷。

指定位置,交換連結串列中的2個節點,注意是交換節點不是交換value。看起來簡單,操作起來需要考慮一下邊界情況,首先遍歷連結串列找到2個節點的位置,m節點和n節點以及他們的前繼節點的位置。如果m節點或者n節點找不到的話,就返回null。找到這兩個節點後,First change next of previous pointers, then change next of current pointers。程式碼如下:

    public ListNode swapNodes(ListNode head, int v1, int v2) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        head = dummy;
        
        ListNode p1 = null, p2 = null, preP1 = null, preP2 = null;
        
        // find the pos of 2 nodes
        ListNode p = head;
        while (p != null) {
            if (p.next != null && p.next.val == v1) {
                preP1 = p;
                p1 = p.next;
            }
            if (p.next != null && p.next.val == v2) {
                preP2 = p;
                p2 = p.next;
            }
            p = p.next;
        }
        
        if (p1 == null || p2 == null) {
            return dummy.next;
        }
        
        // swap 2 nodes
        // first change the next of preP, then change the next of 2 nodes
        preP1.next = p2;
        preP2.next = p1;
        
        ListNode tmp = p1.next;
        p1.next = p2.next;
        p2.next = tmp;

        return dummy.next;
    }

這道題是 17)167. Add Two Numbers 的變種,基本思路與這道題一樣,只不過需要和反轉連結串列的函式配合來解決。

判斷連結串列是不是迴文串,就先把連結串列反轉,然後再從頭到尾遍歷,看反轉連結串列和原連結串列是否一樣。如果一樣就是迴文串,若不一樣就不是迴文串。

將二分搜尋樹轉換為雙向連結串列。思路就是用中序遍歷+Queue佇列,中序遍歷完的結果儲存在佇列中,然後再把佇列中的元素逐個拿出來建立雙向連結串列。程式碼如下:

    private void inorder(TreeNode root, Queue<Integer> q) {
        if (root != null) {
            inorder(root.left, q);
            q.offer(root.val);
            inorder(root.right, q);
        }
        return;
    }
    public DoublyListNode bstToDoublyList(TreeNode root) {  
        if (root == null) {
            return null;
        }
        Queue<Integer> q = new LinkedList<Integer>();
        inorder(root, q);
        DoublyListNode head = new DoublyListNode(q.poll());
        DoublyListNode p = head;
        while (q.isEmpty() == false) {
            DoublyListNode tmp = new DoublyListNode(q.poll());
            p.next = tmp;
            tmp.prev = p;
            p = p.next;
        }
        return head;
    }

對連結串列進行移位,Given 1->2->3->4->5 and k = 2, return 4->5->1->2->3。利用快慢指標,找到分叉點的位置,把他們斷開,然後再重新合併起來。

判斷連結串列中是否有迴圈。就用快慢指標。如果兩個指標相等了,就代表存在迴圈。

以k個元素為小組,分別對小組內的元素進行反轉。Given this linked list: 1->2->3->4->5 For k = 2, you should return: 2->1->4->3->5 For k = 3, you should return: 3->2->1->4->5

算是反轉連結串列的變種題,程式碼如下:

    private boolean canGo(ListNode head, int k) {
        int count = 0;
        ListNode p = head;
        while (p != null) {
            count++;
            p = p.next;
            if (count >= k) {
                return true;
            }
        }
        return false;
    }
    public ListNode reverseKGroup(ListNode head, int k) {
        if (k == 1) {
            return head;
        }
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
        
        while (canGo(head, k) == true) {
            ListNode last = null;
            for (int i = 1; i <= k && head != null; i++) {
                ListNode tmp = head.next;
                tail.next = head;
                head.next = last;
                last = head;
                head = tmp;
            }
            for (int i = 1; i <= k && tail != null; i++) {
                tail = tail.next;
            }
        }
        
        if (head != null) {
          tail.next = head; 
        }
        
        return dummy.next;
    }

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3
找到兩個連結串列的交叉點。先計算兩個連結串列的長度,然後把較長的那個連結串列的遍歷指標初始化為head + (長 - 短),然後再同時遍歷兩個連結串列,如果這兩個遍歷指標相等,就代表那個節點是交叉點。程式碼如下:
    private int calLength(ListNode head) {
        int count = 0;
        while (head != null) {
            count++;
            head = head.next;
        }
        return count;
    }
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int aLength = calLength(headA);
        int bLength = calLength(headB);
        int toGo = Math.abs(aLength - bLength);
        if (aLength > bLength) {
            for (int i = 0; i < toGo; i++) {
                headA = headA.next;
            }
        } else {
            for (int i = 0; i < toGo; i++) {
                headB = headB.next;
            }
        }
        
        while (headA != null && headB != null) {
            if (headA == headB) {
                return headA;
            }
            headA = headA.next;
            headB = headB.next;
        }
        return null;
    }  

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

  • 題目大意:為LRU Cache設計一個數據結構,它支援兩個操作:

   1)get(key):如果key在cache中,則返回對應的value值,否則返回-1

   2)set(key,value):如果key不在cache中,則將該(key,value)插入cache中(注意,如果cache已滿,則必須把最近最久未使用的元素從cache中刪除);如果key在cache中,則重置value的值。

  • 解題思路:題目讓設計一個LRU Cache,即根據LRU演算法設計一個快取。在這之前需要弄清楚LRU演算法的核心思想,LRU全稱是Least Recently Used,即最近最久未使用的意思。在作業系統的記憶體管理中,有一類很重要的演算法就是記憶體頁面置換演算法(包括FIFO, LRU, LFU等幾種常見頁面置換演算法)。事實上,Cache演算法和記憶體頁面置換演算法的核心思想是一樣的:都是在給定一個限定大小的空間的前提下,設計一個原則如何來更新和訪問其中的元素。下面說一下LRU演算法的核心思想,LRU演算法的設計原則是:如果一個數據在最近一段時間沒有被訪問到,那麼在將來它被訪問的可能性也很小。也就是說,當限定的空間已存滿資料時,應當把最久沒有被訪問到的資料淘汰。

我們可以利用連結串列和HashMap來實現,連結串列用於存放資料,連結串列尾部代表最近使用過的資料,連結串列頭部是很久都沒有用過的資料。如果讀寫的資料在連結串列中存在(命中),就把那個節點移動到連結串列尾部。這樣一來在連結串列尾部的節點就是最近訪問過的資料項。

由於在連結串列中遍歷查詢太費時間了,我們採取用空間換時間的策略,加上HashMap,查詢的時候在HashMap中查詢,直接對應到那個節點來進行操作,這樣就可以極大的加快我們訪問的速度。

當需要get(獲取)資料的時候,如果資料在HashMap中不存在(即在連結串列中不存在),那麼就返回-1。如果存在的話,就把那個節點移動到尾部,然後再返回它的值。

當需要set(設定)資料的時候,如果資料在HashMap中存在,就更新一下它的值,然後把那個節點移動到連結串列尾部。如果資料在HashMap中不存在,那就首先判斷一下是否容量已經達到上限了,如果容量達到上限,就先把頭結點刪了(否則就沒有足夠的空間可以用來插入資料);確保空間足夠的話,然後再把新建的節點插入到連結串列尾部,並同時新增進HashMap中。

程式碼如下:

public class Solution {
    private class Node {
        int key;
        int value;
        Node prev;
        Node next;
        
        public Node(int key, int value) {
            this.key = key;
            this.value = value;
            this.prev = null;
            this.next = null;
        }
    }
    private int capacity;
    private Node head = new Node(-1, -1);
    private Node tail = new Node(-1, -1);
    private HashMap<Integer, Node> hash = new HashMap<Integer, Node>();
    
    // @param capacity, an integer
    public Solution(int capacity) {
        this.capacity = capacity;
        head.next = tail;
        tail.prev = head;
    }

    private void moveToTail(Node current) {
        current.next = tail;
        current.prev = tail.prev;
        current.prev.next = current;
        current.next.prev = current;
    }
    // @return an integer
    public int get(int key) {
        if (!hash.containsKey(key)) {
            return -1;
        }
        
        // remove current
        Node current = hash.get(key);
        current.prev.next = current.next;
        current.next.prev = current.prev;
    
        // move to tail 
        moveToTail(current);
        return current.value;
    }

    // @param key, an integer
    // @param value, an integer
    // @return nothing
    public void set(int key, int value) {
        if (get(key) != -1) {
            hash.get(key).value = value;
            return;
        }
        
        if (hash.size() == capacity) {
            hash.remove(head.next.key);
            head.next = head.next.next;
            head.next.prev = head;
        }
        
        Node insert = new Node(key, value);
        hash.put(key, insert);
        moveToTail(insert);
    }
}


總結一下的話,連結串列的題目整體來說還是比較容易掌握的。注意一定要用紙上畫一畫、模擬一下操作,這樣形成的思路較為清晰。然後多注意考慮邊界情況。無非就是用到dummy節點、快慢指標、反轉連結串列、增刪查改建立、歸併之類的知識點。如果連結串列的結構需要改變的話,最好加上dummy節點來作為幫助,這樣寫出來的程式碼會更加簡潔。

相關推薦

LintCode連結串列總結

由於連結串列本身結構的單一性,連結串列的題目很少會有很大的變種,基本都是圍繞幾個基本的考點出題目。所以連結串列的題目比較好掌握,但是連結串列的題目又不太容易一次就AC通過,由於邊界情況未考慮、空指標(比如head.next不存在但是卻給head.next賦值了,就會丟擲nu

關於劍指offer上“二叉搜尋樹與雙向連結串列的理解

題目描述: 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。 一、遞迴的思路 對於函式TreeNode* Convert(TreeNode* root),傳入的是需要轉換的二叉樹的頭結點,返回的是已經轉換好的

Lintcode 連結串列求和 系列

問題1 描述 你有兩個用連結串列代表的整數,其中每個節點包含一個數字。數字儲存按照在原來整數中相反的順序,使得第一個數字位於連結串列的開頭。寫出一個函式將兩個整數相加,用連結串列形式返回和。 樣例 給出兩個連結串列 3->1->5->null 和 5->9->

資料結構|一道還蠻有意思的連結串列

最近在二刷資料結構,也偶爾去刷一下Leetcode上的演算法題,不過感覺自己還是太菜了,一道題經常憋半個小時一個小時,有時候也有用例死活過不去的情況(手動狗頭),還是要多學習多看書多刷題,有機會也會把自己的一些刷題心得放在上面。 前幾天把以前做過的一些資料結構題又拿出來看了一下,有這麼一道題

lintcode 連結串列倒數第n個節點

lintcode 連結串列倒數第n個節點 每日一練 加油 描述 找到單鏈表倒數第n個節點,保證連結串列中節點的最少數量為n。 樣例 給出連結串列 3->2->1->5->null和n = 2,返回倒數第二個節點的值1. 思路 第一個反應,先

c++ 雙向連結串列操作總結

第一、包含DoubleLinkNode 模板類和DoubleLinkList 模板類     #pragma once #include<iostream> using namespace std; template <typename T> class

部分連結串列

#include <stdio.h> BOOL Insert_Last(List *ls, Data data) { if (NULL == ls) return ERROR; Node *node = (Node *)malloc(sizeof(Node)/siz

Lintcode 連結串列求和系列

問題1 描述 你有兩個用連結串列代表的整數,其中每個節點包含一個數字。數字儲存按照在原來整數中相反的順序,使得第一個數字位於連結串列的開頭。寫出一個函式將兩個整數相加,用連結串列形式返回和。 樣例 給出兩個連結串列 3->1->5->null

LeetCode 所有連結串列

閒來練手,下面是LeetCode中的所有連結串列問題的答案。 定義單向連結串列的資料結構如下: public class ListNode { int val; ListNode next; public ListNode(int x) {

leetcode 騰訊筆試面試題之連結串列題目總結(持續更新。。。)

一、合併兩個有序連結串列(簡單) 將兩個有序連結串列合併為一個新的有序連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。  示例: 輸入:1->2->4, 1->3->4 輸出:1->1->2->3-&

超難連結串列

現有兩個單鏈表,一個長度為M,一條長度為N,可能有環也可能無環,若他們相交,則給出他們相交的第一個節點,否則返回null,要求空間複雜度O(1)、空間複雜度O(M+N)。 這題資訊量很大,需要拆分: 1.如何判斷單鏈表有無環: 有環連結串列的判定方式:只要他能在遍歷的過程中遍歷到一個節點

LintCode二分查詢總結

LC上二分查詢那一章有這麼些題: 二分查詢的題經常用於考,因為它雖然看似簡單,但其實要完全正確卻不容易,很容易寫出死迴圈的程式。一個二分查詢的程式可以很容易判斷出一個人功底扎不紮實。 這是一道非常經典的二分查詢題,給出一個有序陣列以及一個目標值target,要求返回

關於連結串列總結(C++迴圈實現)

0.目錄 1.連結串列的基本操作 1.1 結點定義 1.2 建立連結串列 1.3 銷燬連結串列 1.4 列印連結串列 1.5 獲取連結串列長度 2.結點的基本操作 2.1 刪除結點 2.2 查詢結點 3.面試題 3.1 反轉連結串列 3.2 合併兩

資料結構: 連結串列問題總結

資料結構: 連結串列問題總結 刷了幾個連結串列的題目,做一下總結. 題目來自 <程式設計師程式碼面試指南> 連結串列本身操作靈活,程式碼量少.很適合作為面試題考查. 連結串列的基本操作,如增刪改查. 本文用到連結串列用的是牛客網上的結構.如下所

連結串列學習總結

單鏈表(具體實現在上兩篇部落格) 1、單鏈表就是通過每個結點的指標指向下一個結點從而連線起來的結構,單鏈表示意圖如下: 2、單鏈表的初始化:(建構函式部分) 3、單鏈表插入結點:通過指定的位置pos進行結點的插入(當pos為0的時候,頭插;當pos為連結串列長度減1的時候,為

【LeetCode & 劍指offer刷連結串列4:22 刪除連結串列中倒數第k個結點(19. Remove Nth Node From End of List)

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) 19. Remove Nth Node From End of List Given a linked list, remove the   n -th node from th

【LeetCode & 劍指offer刷連結串列3:18 刪除連結串列中的結點(237. Delete Node in a Linked List)

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) Delete Node in a Linked List Write a function to delete a node (except the tail) in a s

【LeetCode & 劍指offer刷連結串列2:6 從尾到頭列印連結串列

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) 6 從尾到頭列印連結串列 題目描述 輸入一個連結串列,從尾到頭列印連結串列每個節點的值 /** *  struct

【LeetCode & 劍指offer刷連結串列11:Palindrome Linked List

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) Palindrome Linked List Given a singly linked list, determine if it is a palindrome. Example 1:

【LeetCode & 劍指offer刷連結串列9:Add Two Numbers

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) Add Two Numbers You are given two   non-empty   linked li