1. 程式人生 > 實用技巧 >LeetBook 謹記錄個人的學習過程

LeetBook 謹記錄個人的學習過程

LeetBook 演算法題 題集,謹記錄個人的學習過程

在本人學習的過程中 ,
遇到大量的 使用哨兵節點 俗稱偽頭 或者 偽尾。
,還有雙指標 ,


簡化新增刪除操作 ,
ListNode newNode = new ListNode(0,head);

1.設計連結串列 (單向連結串列)

public class ListNode {
  int val;
  ListNode next;
  ListNode(int x) { val = x; }
}

class MyLinkedList {
  int size;
  ListNode head;  
  public MyLinkedList() {
    size = 0;
    head = new ListNode(0);
  }

  public int get(int index) {
    if (index < 0 || index >= size) {
        return -1;
    }

    ListNode curr = head;
    for(int i = 0; i < index + 1; ++i) curr = curr.next;
    return curr.val;
  }

  public void addAtHead(int val) {
    addAtIndex(0, val);
  }

  public void addAtTail(int val) {
    addAtIndex(size, val);
  }

  public void addAtIndex(int index, int val) {
    if (index > size) {
         return;
    }

    if (index < 0) {
        return;
    }

    ++size;
    ListNode pred = head;
    for(int i = 0; i < index; ++i) {
        pred = pred.next;
    }

    ListNode toAdd = new ListNode(val);
    toAdd.next = pred.next;
    pred.next = toAdd;
  }

  public void deleteAtIndex(int index) {
    if (index < 0 || index >= size) {
        return;
    }

    size--;
    ListNode pred = head;
    for(int i = 0; i < index; ++i) {
        pred = pred.next;
    }

    pred.next = pred.next.next;
  }
}

環形連結串列 (給定一個連結串列,判斷連結串列中是否有環。)

public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) {
            return false;
        }
        ListNode show = head;
        ListNode pNode = head.next;
        while (show != pNode) {
            if (pNode == null || pNode.next == null) {
                return false;
            }
            show = show.next;
            pNode = pNode.next.next;
        }
        return true;
    }
}

環形連結串列 (給定一個連結串列,返回連結串列開始入環的第一個節點。 如果連結串列無環,則返回 null。)

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode pNode = head;
        Set<ListNode> seen = new HashSet<ListNode>();
        while (pNode != null) {
            if (seen.contains(pNode)) {
                return pNode;
            } else {
                seen.add(pNode);
            }
            pNode = pNode.next;
        }
        return null;
    }
}

相交連結串列 (找到兩個單鏈表相交的起始節點。)

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode pNodeA = headA;
        ListNode pNodeB = headB;
        while (pNodeA != pNodeB) {
            pNodeA = (pNodeA == null) ? headB : pNodeA.next;
            pNodeB = (pNodeB == null) ? headA : pNodeB.next;
        }
        return pNodeA;
    }
}

刪除連結串列的倒數第N個節點 (刪除連結串列的倒數第 n 個節點,並且返回連結串列的頭結點。)

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode first = head;
        ListNode newNode = new ListNode(0,head);    //啞節點 ,next指標域 指向連結串列的頭節點 
        ListNode pNode = newNode;

        for (int i = 1; i <= n; ++i) {
            first = first.next;
        }
        while (first != null) {
            first = first.next;
            pNode = pNode.next;
        }
        pNode.next = pNode.next.next;
        return newNode.next;
    }
}

用於解決連結串列中雙指標問題的模板

// Initialize slow & fast pointers
ListNode slow = head;
ListNode fast = head;
/**
 * Change this condition to fit specific problem.
 * Attention: remember to avoid null-pointer error
 **/
while (slow != null && fast != null && fast.next != null) {
    slow = slow.next;           // move slow pointer one step each time
    fast = fast.next.next;      // move fast pointer two steps each time
    if (slow == fast) {         // change this condition to fit specific problem
        return true;
    }
}
return false;   // change return value to fit specific problem

反轉連結串列

1 > 3 > 2 > null --> 2 > 2 > 1 > null

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode pNode = head;
        while (pNode != null) {
            ListNode newNode = pNode.next;
            pNode.next = prev;
            prev = pNode;
            pNode = newNode;
        }
        return prev;
    }
}

移除連結串列元素 (刪除連結串列中等於給定值 val 的所有節點。)

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode seen = new ListNode(0);
        seen.next = head;
        ListNode newNode = seen;
        ListNode pNode = head;
        while (pNode != null) {
            if (pNode.val == val) {
                newNode.next = pNode.next;
            } else {
                newNode = pNode;
            }
            pNode = pNode.next;
        }
        return seen.next;
    }
}

奇偶連結串列 (給定一個連結串列 ,按順序將 奇數節點編號 和 偶數節點編號 放在一起)

1>2>4>5>8 -- > 1>4>8>2>5

class Solution {
    public ListNode oddEvenList(ListNode head) {
        if (head == null) {
            return head;
        }
        ListNode evevNode = head.next;
        ListNode newNode = head;
        ListNode pNode = evevNode;
        while (pNode != null && pNode.next != null) {
            newNode.next = pNode.next;
            newNode = newNode.next;
            pNode.next = newNode.next;
            pNode = pNode.next;
        }
        newNode.next = evevNode;
        return head;
    }
}

迴文連結串列 (判斷是否為迴文連結串列)

1>2>2>1

class Solution {
    public boolean isPalindrome(ListNode head) {
        Stack<Integer> cruu = new Stack<>();
        ListNode pNode = head;
        while (pNode != null) {
            cruu.push(pNode.val);
            pNode = pNode.next;
        }
        while (head != null) {
            if (head.val != cruu.pop()) {
                return false;
            }
            head = head.next;
        }
        return cruu.isEmpty();
    }
}

合併兩個有序連結串列

從小到大
1:1>2>3>4>5>null
2:2>3>5>7>null
變成 :1>2>2>3>3>4>5>5>7>null

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode newNode = new ListNode(-1);
        ListNode pNode = newNode;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                pNode.next = l1;
                l1 = l1.next;
            } else {
                pNode.next = l2;
                l2 = l2.next;
            }
            pNode = pNode.next;
        }
        // 有序的連結串列 ,最後只會剩一個沒有連線  
        // pNode的下一個節點引用 指向  如果 l1 == null  就指向 l2 ,否則  指向 l1 .
        pNode.next = (l1 == null) ? l2 : l1;
        return newNode.next;
    }
}