個人面試準備過程--LeetCode(更新中)

斐波那契數

public long fibonacci(int n){
    int[] res = {0, 1};
    if(n < 2){
        return res[n];
    }
    
    long fibNMinusOne = 1;
    long fibNMinusTwo = 0;
    long fibN = 0;
    for(int i = 2; i < n; i++){
        fibN = fibNMinusOne + fibNMinusTwo;
        fibNMinusTwo = fibNMinusOne;
        fibNMinusOne = fibN;
    }
    return fibN;
}

Minimum Depth of Binary Tree 求樹的最小深度

遞歸法

public class Solution{
    public int minDepth(TreeNode root) {
        if(root == null){
            return 0;
        }
        
        return getMin(root);
    }
    
    public int getMin(TreeNode root){
        if(root == null){
            return Integer.MAX_VALUE;
        }
        
        if(root.left == null && root.right == null){
            return 1;
        }
        
        return Math.min(getMin(root.left), getMin(root.right)) + 1;
    }
}

迭代法

public class Solution{
        public int minDepth(TreeNode root){
            if(root == null){
                return 0;
            }
            
            Queue<TreeNode> queue = new LinkedList<>();
            Queue<TreeNode> counts = new LinkedList<>();
            
            queue.add(root);
            counts.add(1);
            
            while(!queue.isEmpty()){
                TreeNode cur = queue.remove();
                int count = counts.remove();
                
                if(cur.left != null){
                    queue.add(cur.left);
                    counts.add(count + 1);
                }
                
                if(cur.right != null){
                    queue.add(cur.right);
                    counts.add(count + 1);
                }
                
                if(cur.left == null && cur.right == null){
                    return count;
                }
            }
            
            return 0;
        }
    }

 翻轉整數

簡單題須要注意的是細節和邊界條件,本題須要注意:html

  1. Integer.MIN_VALUE比Integer.MAX_VALUE的絕對值大1git

  2. 符號問題數組

  3. 翻轉後整型越界問題dom

public int reverse(int x) {
        if(x ==  Integer.MIN_VALUE){
                return 0;
        }

        int n = Math.abs(x);

        int res = 0;

        while(n != 0){
        // 翻轉後整數越界 Integer.MAX_VALUE=2147483647
                if(res > (Integer.MAX_VALUE - n % 10) / 10){
                        return 0;
                }

                res = res * 10 + n % 10;
                n /= 10;
        }

        return x > 0 ? res : -res;
    }

鏈表的環

141. Linked List Cycle

public boolean hasCycle(ListNode head) {
    if(head == null || head.next == null){
        return false;
    }
    
    ListNode fast = head;
    ListNode slow = head;
    
    while(fast != null && fast.next != null){
        fast = fast.next.next;
        slow = slow.next;
        
        if(fast == slow){
            return true;
        }
    }    
    return false;
}

141 如何找到環的第一個節點?Linked List Cycle II!

05171805-64db9f059a1641e7afaf3dd8223c4fe7.jpg

  • slow到起點後,通過n-x步相遇spa

  • 設相遇點到圈起點距離是b3d

  • slow走的距離是a + b指針

  • fast走的距離是a + b + k n = 2 (a + b),從而a + b = k * n,k爲常數code

  • 如何找圈的起點?
    把slow拉回起點,fast從相遇點繼續走,每次走一步。a步後,slow到圈起點,fast恰好也到圈起點!htm

  • 如何找圈長?
    相遇後,fast再走一圈,並統計長度就是圈長blog

    public ListNode detectCycle(ListNode head) {
        if(head == null || head.next == null){
            return null;
        }
        
        ListNode fast = head;
        ListNode slow = head;
        
        while(true){
            if(fast == null || fast.next == null){
                return null;
            }
            
            fast = fast.next.next;
            slow = slow.next;
            
            if(fast == slow){
                break;
            }
        }
        
        fast = head;
        while(fast != slow){
            fast = fast.next;
            slow = slow.next;
        }
        
        return fast;
    }

    總結:當while(fast != null || fast.next != null)轉成本題的條件時,變成

    while(true){
        if(fast == null || fast.next == null){
            //走你
        }
    }

本節參考 http://www.cnblogs.com/hidden...

160.Intersection of Two Linked Lists

相交的兩鏈表第一個交點,若是有環,此法失敗。
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    int lengthA = 0;
    int lengthB = 0;
    
    ListNode p = headA;
    ListNode q = headB;
    
    while(p != null){
        p = p.next;
        lengthA++;
    }
    
    while(q != null){
        q = q.next;
        lengthB++;
    }
    
    if(q != p){
        return null;
    }
    
    p = headA;
    q = headB;
    
    if(lengthA > lengthB){
        int delta = lengthA - lengthB;
        while(delta > 0){
            p = p.next;
            delta--;
        }
        while(q != p){
            p = p.next;
            q = q.next;
        }
        return q;
    }else{
        int delta = lengthB - lengthA;
        while(delta > 0){
            q = q.next;
            delta--;
        }
        while(q != p){
            p = p.next;
            q = q.next;
        }
        return q;
    }
}

138. Copy List with Random Pointer

難點,並不知道新鏈表的random指針指向何處
把大象裝冰箱總共分幾步?
1. 在舊鏈表的每一個結點後面,複製一個結點複本
2. 複製random域,爲何要在每一個結點後面複製複本,就在於,
a.next.random = a.random.next
舊random指向的地址的next,指向的就是新random的地址!
3. 拆分兩個鏈表
private void copyNext(RandomListNode head){
    while(head != null){
        RandomListNode newNode = new RandomListNode(head.label);
        newNode.next = head.next;
        head.next = newNode;
        newNode.random = head.random;
        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 = head.next;
    while(head != null){
        RandomListNode temp = head.next;
        head.next = temp.next;
        if(temp.next != null){
            temp.next = temp.next.next;
        }
        head = head.next;
    }
    return newHead;
}

public RandomListNode copyRandomList(RandomListNode head) {
    if(head == null){
        return null;
    }
    
    copyNext(head);
    copyRandom(head);
    return splitList(head);
}
總結:1. 新random地址如何經過複製結點傳遞
     2. while()條件,搞清楚明白。
  • copyNext中while的循環條件

一次循環中:

  1. newNode確定不爲null,由於是new出來的

  2. head.next指向newNode,所以,head.next不爲null

  3. newNode.random可能爲null,可是不影響循環

  4. head = head.next.next可能爲null,所以,循環條件應該爲head != null

  • copyRandom中while的循環條件

一次循環中:

  1. 此時,copyNext已經完成,鏈表的結點數確定爲偶數,head.next不可能爲null

  2. head = head.next.next可能爲null,所以循環條件應該爲head != null

  • splitList中while的循環條件

一次循環中:

  1. RandomListNode temp = head.next此時不會爲null

  2. temp.next 多是尾結點,因此可能爲null

  3. 若是不是尾結點,temp.next = temp.next.next必定不爲null

  4. head = head.next,head可能已經指向了尾結點,因此可能爲null

  5. 循環條件應該爲head != null

86. Partition List

鏈表的partition比數組更有優點,能夠直接新建鏈表
//x 爲pivot值
    public ListNode partition(ListNode head, int x) {
    ListNode h1 = null;
    ListNode t1 = null;
    
    ListNode h2 = null;
    ListNode t2 = null;
    
    while(head != null){
        if(head.val < x){
            if(h1 == null){
                h1 = head;
                t1 = head;
                
            }else{
                t1.next = head;
                t1 = t1.next;
            }
        }else{
            if(h2 == null){
                h2 = head;
                t2 = head;
               
            }else{
                t2.next = head;
                t2 = t2.next;
            }
        }
        head = head.next;
    }
    
    if(t1 != null){
        t1.next = h2;
    }
    
    if(t2 != null){
        t2.next = null;
    }
    
    return h1 != null ? h1 : h2;
}
鏈表題總結
  1. 細緻---多寫多練習

    • 哪些指針要修改

    • 修改鏈表前保存(防止鏈表斷掉)

    • 注意空指針

  2. 特色:能夠從新創建表頭

    • 翻轉

    • Partition

    • 注意:第一個元素,表尾

3. Longest Substring Without Repeating Characters

小窗移動的過程:1. 用i來控制小窗的左邊界,條件map[charAt[j]]==0控制右邊界
2. 若是發現map[charAt[j]] == 1,將左邊界右移,j先保持不動,走到條件map[charAt[j]]==0再次知足,j開始右移
3. answer經過 answer = Math.max(answer,j - i + 1)來控制,很是妙
public int lengthOfLongestSubstring(String s) {
    int answer = 0;
    int i = 0;
    int j = 0;
    int map = new int[256];
    for(i = 0; i < s.length(); i++){
        while(j < s.length && map[s.charAt(j)] == 0){
            map[s.charAt(j)] = 1;
            answer = Math.max(answer, j - i + 1);
            j++;
        }
        map[s.charAt(i)] = 0;
    }
    return answer;
}

數組相關

153.Find Minimum in Rotated Sorted Array

本題參考解法 : https://siddontang.gitbooks.i...
這題要求在一個輪轉了的排序數組裏面找到最小值,咱們能夠用二分法來作。

首先咱們須要知道,對於一個區間A,若是A[start] < A[stop],那麼該區間必定是有序的了。

假設在一個輪轉的排序數組A,咱們首先獲取中間元素的值,A[mid],mid = (start + stop) / 2。由於數組沒有重複元素,那麼就有兩種狀況:

  • A[mid] > A[start],那麼最小值必定在右半區間,譬如[4,5,6,7,0,1,2],中間元素爲7,7 > 4,最小元素必定在[7,0,1,2]這邊,因而咱們繼續在這個區間查找。

  • A[mid] < A[start],那麼最小值必定在左半區間,譬如[7,0,1,2,4,5,6],這件元素爲2,2 < 7,咱們繼續在[7,0,1,2]這個區間查找。

須要注意給定的數組可能並無翻轉

public int findMin(int[] nums) {
    if(nums == null || nums.length == 0){
        return Integer.MIN_VALUE;
    }
    int low = 0;
    int high = nums.length - 1;
    //nums[low] < nums[high]若是已經有序了,那麼退出循環,題目說明,數組中沒有重複數字
    while(low < high && nums[low] > nums[high]){
        int mid = (low + high) / 2;
        if(nums[mid] > nums[high]){
            low = mid + 1;
        }else{
            high = mid;
        }
    }
    return nums[low];
}

154. Find Minimum in Rotated Sorted Array II

與上題的區別在於,數組中的無序可能重複
public int findMin(int[] nums) {
    if(nums == null || nums.length == 0){
        return Integer.MIN_VALUE;
    }
    int low = 0;
    int high = nums.length - 1;
    
    while(low < high && nums[low] > nums[high]){
        int mid = (low + high) / 2;
        if(nums[mid] > nums[high]){
            low = mid + 1;
        }else if(nums[mid] < nums[high]){
            high = mid;
        }else{
            low++;
        }
    }
    return nums[low];
}

11.容納最多水問題 Container With Most Water

public int maxArea(int[] height) {
    int n = height.length;
    int best = 0;
    for(int i = 0, j = n - 1; i < j;){
        best = Math.max(Math.min(height[i], height[j]) * (j - i), best);
        if(height[i] < height[j]){
            i++;
        }else{
            j--;
        }
    }
    return best;
}

234. Palindrome Linked List

時間 O(n) 空間 O(n)

public boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null){
            return true;
        }
        
        ListNode cur = new ListNode(head.val);
        ListNode newHead = null;
        ListNode old = head;
        
        while(old != null){
            ListNode preCur = new ListNode(old.val);
            old = old.next;
            preCur.next = newHead;
            newHead = preCur;
        }
        
        while(newHead != null){
            if(newHead.val != head.val){
                return false;
            }
            newHead = newHead.next;
            head = head.next;
        }
        
        return true;
    }
相關文章
相關標籤/搜索