(lintcode全部题目解答之)九章算法之算法班题目全解(附容易犯的错误)

---------------------------------------------------------------

本文使用方法:所有题目,只需要把标题输入lintcode就能找到。主要是简单的剖析思路以及不能bug-free的具体细节原因。

----------------------------------------------------------------

-------------------------------------------

第九周:图和搜索。

-------------------------------------------

3,------permutation(全排列)

答案:

class Solution {
    /**
     * @param nums: A list of integers.
     * @return: A list of permutations.
     */
    public static ArrayList<ArrayList<Integer>> permute(ArrayList<Integer> nums)  {
        ArrayList<ArrayList<Integer>> res = new ArrayList();
        if (nums == null || nums.size() == 0) {
            return res;
        }
        ArrayList<Integer> list1 = new ArrayList();
        list1.add(nums.get(0));
        res.add(list1);
        for (int i = 1; i < nums.size(); i++){
            ArrayList<ArrayList<Integer>> res2 = new ArrayList();
            for (ArrayList<Integer> tmp : res) {
                for (int j = 0; j <= tmp.size(); j++) {
                    ArrayList<Integer> list2 = new ArrayList(tmp);
                    list2.add(j, nums.get(i));
                    res2.add(list2);
                }
            }
            res = new ArrayList(res2);
        }
        return res;
    }
}
View Code

 4,---------permutationII(全排列)

答:

class Solution {
    /**
     * @param nums: A list of integers.
     * @return: A list of unique permutations.
     */
    public static ArrayList<ArrayList<Integer>> permuteUnique(ArrayList<Integer> nums) {
        // write your code here
        HashSet<ArrayList<Integer>> res = new HashSet();
        ArrayList<ArrayList<Integer>> ans = new ArrayList();
        if (nums == null || nums.size() == 0) {
            return ans;
        }
        ArrayList<Integer> list1 = new ArrayList();
        list1.add(nums.get(0));
        res.add(list1);
        for (int i = 1; i < nums.size(); i++){
            HashSet<ArrayList<Integer>> res2 = new HashSet();
            for (ArrayList<Integer> tmp : res) {
                for (int j = 0; j <= tmp.size(); j++) {
                    ArrayList<Integer> list2 = new ArrayList(tmp);
                    list2.add(j, nums.get(i));
                    res2.add(list2);
                }
            }
            res = new HashSet(res2);
        }
        for (ArrayList list : res){
            ArrayList<Integer> list3 = new ArrayList(list);
            ans.add(list3);
        }
        return ans;
    }
}
View Code

 

-------------------------------------------

第八周:数据结构。

-------------------------------------------

1,------------min stack(最小栈)

答案:注意错误点,当是Integer的时候不要用“==”。

public class MinStack {
    Stack<Integer> stack = new Stack();
    Stack<Integer> minStack = new Stack();
    public MinStack() {
        // do initialize if necessary
    }
    public void push(int number) {
        // write your code here
        stack.push(number);
        if (minStack.isEmpty() || number <= minStack.peek()) {
            minStack.push(number);
        }
    }
    public int pop() {
        // write your code here
        if (stack.peek().equals(minStack.peek())) {
            minStack.pop();
        }
        return stack.pop();
    }
    public int min() {
        // write your code here
        return minStack.peek();
    }
}
View Code

 

 2,---------implement a queue by two stacks(用两个栈实现一个队列)

答案:1,这里有一个很好的结构就是,在class里面做出一定的定义,然后new的时候在结构函数里面。

public class Queue {
    private Stack<Integer> stack1;
    private Stack<Integer> stack2;

    public Queue() {
        stack1 = new Stack();
        stack2 = new Stack();
       // do initialization if necessary
    }
    public void push(int element) {
        // write your code here
        stack1.push(element);
    }

    public int pop() {
        // write your code here
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }

    public int top() {
        // write your code here
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.peek();
    }
}
View Code

 3,----------largest rectangle in histogram(在直方图中最大的矩形)

 答案:

public class Solution {
    /**
     * @param height: A list of integer
     * @return: The area of largest rectangle in the histogram
     */
    public static int largestRectangleArea(int[] height) {
        if (height == null || height.length == 0) {
            return 0;
        }
        int res = 0;
        int len = height.length;
        int left = 0;
        int right = 0;
        int num = 0;
        for (int i = 0; i < len; i++) {
            left = i;
            right = i;
            num = 1;
            while (--left >= 0 && height[left] >= height[i]) {
                num++;
            }
            while (++right < len && height[right] >= height[i]) {
                num++;
            }
            res = Math.max(res, num * height[i]);
        }
        return res;
    }
}
View Code

 4,-----------

5,-----------rehashing(重哈希)

 答案:

/**
 * Definition for ListNode
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    /**
     * @param hashTable: A list of The first node of linked list
     * @return: A list of The first node of linked list which have twice size
     */
    public ListNode[] rehashing(ListNode[] hashTable) {
        // write your code here
        int capacity = hashTable.length;
        ListNode[] res = new ListNode[2 * capacity];
        for (int i = 0; i < capacity; i++) {
            ListNode a = hashTable[i];
            while (a != null) {
                int index = 0;
                if (a.val >= 0) {
                    index = a.val % (2 * capacity);
                } else {
                    index = (a.val % (2 * capacity) + (2 * capacity)) % (2 * capacity);
                }
                if (res[index] == null) {
                    res[index] = new ListNode(a.val);
                } else {
                    ListNode tmp = res[index];
                    while (tmp.next != null) {
                        tmp = tmp.next;
                    }
                    tmp.next = new ListNode(a.val);
                }
                a = a.next;
            }
        }
        return res;
    }
}
View Code

 6,-----------

7,-----------median number(中位数)

答案:

    public static int[] medianII(int[] nums) {
        if (nums == null || nums.length == 0) {
            return null;
        }
        int len = nums.length;
        int[] res = new int[len];
        ArrayList<Integer> list = new ArrayList();
        for (int i = 0; i < len; i++) {
            list.add(nums[i]);
            Collections.sort(list);
            res[i] = list.get((list.size() - 1) / 2);
        }
        return res;
    }
View Code

 8,---------ugly number(丑数)

答案:

    public static long kthPrimeNumber(int k) {
        Queue<Long> q1 = new PriorityQueue();
        Queue<Long> q2 = new PriorityQueue();
        Queue<Long> q3 = new PriorityQueue();
        q1.offer((long) 3);
        q2.offer((long) 5);
        q3.offer((long) 7);
        long res = 0;
        for (int i = 0; i < k; i++) {
            if (q1.peek() < q2.peek()) {
                if (q1.peek() < q3.peek()) {
                    res = q1.poll();
                    if (!q1.contains(res * 3)) {
                        q1.offer(res * 3);
                    }
                    if (!q1.contains(res * 5)) {
                        q1.offer(res * 5);
                    }
                    if (!q1.contains(res * 7)) {
                        q1.offer(res * 7);
                    }
                } else {
                    res = q3.poll();
                    if (!q3.contains(res * 7)) {
                        q3.offer(res * 7);
                    }
                }
            } else {
                if (q2.peek() < q3.peek()) {
                    res = q2.poll();
                    if (!q2.contains(res * 5)) {
                        q2.offer(res * 5);
                    }
                    if (!q2.contains(res * 7)) {
                        q2.offer(res * 7);
                    }
                } else {
                    res = q3.poll();
                    if (!q3.contains(res * 7)) {
                        q3.offer(res * 7);
                    }
                }
            }    
        }
        return res;
    }
View Code

 9,-------merge K sorted arrays(合并k个有序的数组)

 答案:

    public static List<Integer> mergekSortedArrays(int[][] arrays) {
        List<Integer> res = new ArrayList();
        int height = arrays.length;
        int[] index = new int[height];
        boolean flag = true;
        while (flag) {
            flag = false;
            int min = Integer.MAX_VALUE;
            int minIndex = 0;
            for (int i = 0; i < height; i++) {
                if (arrays[i] != null && index[i] < arrays[i].length && arrays[i][index[i]] < min) {
                    minIndex = i;
                    min = arrays[i][index[i]];
                    flag = true;
                }
            }
            if (!flag) {
                break;
            }
            res.add(min);
            index[minIndex]++;
        }
        return res;
    }
View Code

10,-----------

 

-------------------------------------------

第七周:数组。

-------------------------------------------

1,---------------merge sorted array I(归并两个有序的数组)

答案:注意1,要判断有一个是否已经copy完了。其次要注意是A还是B。

    public void mergeSortedArray(int[] A, int m, int[] B, int n) {
        // write your code here
        // error :b < 0
        int a = m - 1;
        int b = n - 1;
        for (int i = m + n - 1; i >= 0; i--) {
            if (b < 0) {
                A[i] = A[a--];
            } else if (a < 0) {
                A[i] = A[b--];
            } else if (A[a] > B[b]) {
                A[i] = A[a--];
            } else {
                A[i] = B[b--];
            }
        }
    }
View Code

 2,------------merge sorted array II (归并两个有序的数组)

答案:

    public int[] mergeSortedArray(int[] a, int[] b) {
        // Write your code here
        int m = a.length;
        int n = b.length;
        int[] result = new int[m + n];
        int len1 = 0;
        int len2 = 0;
        for (int i = 0; i < m + n; i++) {
            if (len1 >= m) {
                result[i] = b[len2++];
            } else if (len2 >= n) {
                result[i] = a[len1++];
            } else if (a[len1] < b[len2]) {
                result[i] = a[len1++];
            } else {
                result[i] = b[len2++];
            }
        }
        return result;
    }
View Code

 3,------------median of two sorted Arrays(找两个有序数组的中位数)

答案:需要改进,这是暴力解法。没有logn

    public double findMedianSortedArrays(int[] a, int[] b) {
        // write your code here
        int n = a.length + b.length;
        int[] tmp = mergeSortedArray(a, b);
        if (n % 2 == 0) {
            return (tmp[n / 2 - 1] + tmp[n / 2]) / 2.0;
        } else {
            return (double) tmp[n / 2];
        }
    }
    public static int[] mergeSortedArray(int[] a, int[] b) {
        // Write your code here
        int m = a.length;
        int n = b.length;
        int[] result = new int[m + n];
        int len1 = 0;
        int len2 = 0;
        for (int i = 0; i < m + n; i++) {
            if (len1 >= m) {
                result[i] = b[len2++];
            } else if (len2 >= n) {
                result[i] = a[len1++];
            } else if (a[len1] < b[len2]) {
                result[i] = a[len1++];
            } else {
                result[i] = b[len2++];
            }
        }
        return result;
    }
View Code

 4,-------best time to buy and sell stock I(买卖股票最佳时机)

答案:

    public int maxProfit(int[] prices) {
        // write your code here
        int max = 0;
        int[] dp = new int[prices.length];
        for (int i = 0; i < prices.length; i++) {
            for (int j = i - 1; j >= 0; j--) {
                if (prices[j] < prices[i]) {
                    dp[i] = Math.max(dp[i], prices[i] - prices[j]);
                }
                max = Math.max(max, dp[i]);
            }
        }
        return max;
    }
View Code

II

答案:

    public int maxProfit(int[] prices) {
        // write your code here
        int maxProfit = 0;
        for (int i = 1; i < prices.length; i++) {
            if (prices[i] - prices[i - 1] > 0) {
                maxProfit += prices[i] - prices[i - 1];
            }
        }
        return maxProfit;
    }
View Code

III,

答案:思路:就是通过left,right来判断,就是到了这个点,前面最大能有多少利益,后面又有多少。

    public static int maxProfit(int[] a) {
        if (null == a || a.length == 0) {
            return 0;
        }
        int len = a.length;
        int[] left = new int[len];
        int[] right = new int[len];
        int min = a[0];
        left[0] = 0;
        for (int i = 1; i < len; i++) {
            min = Math.min(min, a[i]);
            left[i] = Math.max(left[i - 1], a[i] - min);
        }
        int max = a[len - 1];
        right[len - 1] = 0;
        for (int i = len - 2; i >= 0; i--) {
            max = Math.max(max, a[i]);
            right[i] = Math.max(right[i + 1], max - a[i]);
        }
        int res = 0;
        for (int i = 0; i < len; i++) {
            res = Math.max(res, left[i] + right[i]);
        }
        return res;
    }
View Code

5,---maximum subarray(最大子数组)

(I)答案:

    public int maxSubArray(int[] nums) {
        // write your code
        if (null == nums || nums.length == 0) {
            return 0;
        }
        int len = nums.length;
        int[] dp = new int[len];
        dp[0] = nums[0];
        int max = nums[0];
        for (int i = 1; i < len; i++) {
            if (dp[i - 1] > 0) {
                dp[i] = dp[i - 1] + nums[i];
            } else {
                dp[i] = nums[i];
            }
            max = Math.max(max, dp[i]);
        }
        return max;
    }
View Code

 

 

-------------------------------------------

第六周:链表。

-------------------------------------------

1,---------remove duplicates from sorted list II(从有序的链表中移除重复元素)

(1)答案和思路:注意的地方就是记得判断null。

public class Solution {
    /**
     * @param ListNode head is the head of the linked list
     * @return: ListNode head of the linked list
     */
    public static ListNode deleteDuplicates(ListNode head) {
        // write your code here
        if (null == head) {
            return head;
        }
        ListNode preHead = new ListNode(-1);
        preHead.next = head;
        ListNode pre = preHead;
        ListNode cur = head;
        while (cur != null && cur.next != null) {
            if (cur.val != cur.next.val) {
                cur = cur.next;
                pre = pre.next;
                continue;
            }
            while (cur.next != null && cur.val == cur.next.val) {
                cur = cur.next;
            }
            pre.next = cur.next;
            cur = cur.next;
        }
        return preHead.next;
    }
}
View Code

(2)一刷bug-free;

 

2,-----------reverse linked list II(翻转链表)

(1)

翻转链表1:就是建一个preHead,每次来都插进去。用temp记一下preHead.next;注意的地方是要先把head = head.next。不然一会head.next改变了

public class Solution {
    /**
     * @param head: The head of linked list.
     * @return: The new head of reversed linked list.
     */
    public ListNode reverse(ListNode head) {
        // write your code here
        if (null == head || head.next == null) {
            return head;
        }
        ListNode preHead = new ListNode(0);
        while (head != null) {
            ListNode temp = preHead.next;
            preHead.next = head;
            head = head.next;
            preHead.next.next = temp;
        }
        return preHead.next;
    }
}
View Code

翻转链表II:注意不要用next做判断,因为它是会变的。

 

 

3,-------partition list(分割链表)

答案:

    public static ListNode partition(ListNode head, int x) {
        if (null == head) {
            return head;
        }
        ListNode preHead = new ListNode(0);
        preHead.next = head;
        ListNode left = preHead;
        ListNode right = preHead;
        while (left.next != null) {
            if (left.next.val < x) {
                left = left.next;
                continue;
            }
            right = left;
            while (right.next != null && right.next.val >= x) {
                right = right.next;
            }
            if (right.next == null) {
                break;
            }
            ListNode tmp = right.next;
            right.next = right.next.next;
            ListNode tmp2 = left.next;
            left.next = tmp;
            tmp.next = tmp2;
            left = left.next;
        }
        head = preHead.next;
        return head;
    }
View Code

 

5,--------reorder list(重排链表)

答案:

    public static void reorderList(ListNode head) {
        // write your code here
        // error1 : input null
        if (null == head) {
            return;
        }
        ListNode node = head;
        while (node.next != null) {
            ListNode cur = node;
            while (cur.next.next != null) {
                cur = cur.next;
            }
            ListNode tmp = cur.next;
            cur.next = null;
            ListNode tmp2 = node.next;
            node.next = tmp;
            tmp.next = tmp2;
            node = node.next.next;
            if (node == null) {
                break;
            }
        }
    }
View Code

 6,-------------链表有无环判断(Linked list cycle)

答案:

    public boolean hasCycle(ListNode head) {
        // write your code here
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }
View Code

 7,------------rotate list(右移动链表)

注意,如果k % length == 0 要特判断。

答案:

    public ListNode rotateRight(ListNode head, int k) {
        // write your code here
        if (head == null ) {
            return head;
        }
        ListNode preHead = new ListNode(0);
        preHead.next = head;
        int length = 0;
        ListNode pre = preHead;
        while (pre.next != null) {
            length++;
            pre = pre.next;
        }
        int n = k % length;
        if (n == 0) {
            return head;
        }
        for (int i = 0; i < length - n; i++) {
            ListNode tmp = preHead.next;
            preHead.next = preHead.next.next;
            pre.next = tmp;
            tmp.next = null;
            pre = pre.next;
        }
        head = preHead.next;
        return head;
    }
View Code

8,--------------Merge k sorted list(归并k个有序链表)

答案:

    public ListNode mergeKLists(List<ListNode> lists) {
        // write your code here
        // error1 : input []
        if (lists == null || lists.size() == 0) {
            return null;
        }
        int min = Integer.MAX_VALUE;
        int flag = -1;
        boolean b = true;
        ListNode pre = new ListNode(0);
        ListNode cur = pre;
        while (b) {
            b = false;
            int i = 0;
            for (ListNode list : lists) {
                if (list != null && list.val < min) {
                    flag = i;
                    min = list.val;
                    b = true;
                }
                i++;
            }
            if (!b) {
                break;
            }
            cur.next = new ListNode(min);
            lists.set(flag, lists.get(flag).next);
            cur = cur.next;
            min = Integer.MAX_VALUE;
        }
        return pre.next;
    }
View Code

 

 9,------------copy list with random pointer(复制带有随机指针的链表)

答案:

    public static RandomListNode copyRandomList(RandomListNode head) {
        // write your code here
        RandomListNode cur = head;
        while (cur != null) {
            RandomListNode tmp = new RandomListNode(cur.label);
            RandomListNode next = cur.next;
            cur.next = tmp;
            tmp.next = next;
            cur = cur.next.next;
        }
        cur = head;
        while (cur != null) {
            if (cur.random == null) {
                cur.next.random = null;
            } else {
                cur.next.random = cur.random.next;
            }
            cur = cur.next.next;
        }
        RandomListNode head2 = head.next;
        RandomListNode cur2 = head2;
        while (cur2.next != null) {
            cur2.next = cur2.next.next;
            cur2 = cur2.next;
        }
        return head2;
    }
View Code

 14,--------Remove Nth Node From End of List(删除链表中倒数第n个值)

答案:

    ListNode removeNthFromEnd(ListNode head, int n) {
        // write your code here
        int length = 0;
        ListNode preHead = new ListNode(0);
        preHead.next = head;
        ListNode cur = head;
        while (cur != null) {
            length++;
            cur = cur.next;
        }
        ListNode pre = preHead;
        for (int i = 0; i < length - n; i++) {
            pre = pre.next;
        }
        pre.next = pre.next.next;
        head = preHead.next;
        return head;
    }
View Code

 15,--------------Linked List cycle(找链表循环的起点)

答案:

    public ListNode detectCycle(ListNode head) {
        // write your code here
        ListNode fast = head;
        ListNode slow = head;
        boolean isHave = false;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                isHave = true;
                break;
            }
        }
        if (!isHave) {
            return null;
        }
        slow = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return fast;
    }
View Code

 

-------------------------------------------

第五周:动态规划二

-------------------------------------------

1,------------ 分割回文串 IIPalindrome Partitioning II

(1)答案:第i个字符串的分割dp[i] = 他到前面某一个是回文然后加上前面那一段所需要的最少分割 +1。

public class Solution {
    /**
     * @param s a string
     * @return an integer
     */
    public int minCut(String s) {
        // write your code here
        if (null == s || s.length() == 0) {
            return 0;
        }
        int length = s.length();
        int[] dp = new int[length + 1];
        for (int i = 0; i <= length; i++) {
            dp[i] = i - 1;
        }
        for (int i = 1 ; i <= length; i++) {
            for (int j = i; j >  0; j--) {
                if (isPalindrome(s, j - 1, i - 1)) {
                    dp[i] = Math.min(dp[i], dp[j - 1] + 1);
                }
            }
        }
        return dp[length];
    }
    public static boolean isPalindrome(String s, int start, int end) {
        if (null == s || s.length() == 0) {
            return true;
        }
        while (start < end) {
            // if (!s.get(start).equals(s.get(end))) {
            if (s.charAt(start) != s.charAt(end)) {
                return false;
            }
            start++;
            end--;
        }
        return true;
    }
}
View Code

 

 (2)一刷没有AC。

(3)二刷:bug-free;

2,----------------Word Break(单词切分)

(1)答案:注意要考虑单词的长度

public class Solution {
    /**
     * @param s: A string s
     * @param dict: A dictionary of words dict
     */
    public boolean wordBreak(String s, Set<String> dict) {
        // write your code here
        if (s == null || s.length() == 0) {
            return true;
        }
        if (dict == null) {
            return false;
        }
        int length = s.length();
        int maxWordLength = 0;
        for (String str : dict) {
            maxWordLength = Math.max(maxWordLength, str.length());
        }
        boolean[] dp = new boolean[length + 1];
        dp[0] = true;
        for (int i = 1; i <= length; i++) {
            for (int j = i; j > 0 && i - j <= maxWordLength; j--) {
                if (dp[j - 1] && dict.contains(s.substring(j - 1, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[length];
    }
}
View Code

(2)一刷LTE了,原因是没有考虑单词的长度。

(3)二刷没有bug-free,是因为j--错写成j++. 

3,---------Longest Common Subsequence最长公共子序列

注意:个数是从0个开始。

(1)答案和思路:1,就是取第一个字符串前i个,第二个字符串前j个写递推式。

    public int longestCommonSubsequence(String A, String B) {
        // write your code here
        // error1 : 忘记判断空了
        if (A == null || A.length() == 0 || B == null || B.length() == 0) {
            return 0;
        }
        int[][] dp = new int[A.length() + 1][B.length() + 1]; // error3:int[][] dp = new int[A.length()][B.length()];
        for (int i = 1; i <= A.length(); i++) {
            for (int j = 1; j <= B.length(); j++) {
                if (A.charAt(i - 1) == B.charAt(j - 1)) {// error4 :if (A.charAt(i) == B.charAt(j)) {
                    dp[i][j] = Math.max(Math.max(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1] + 1);
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[A.length()][B.length()];
    }
View Code

(2)一刷没有AC。

(3)二刷bug-free; 

5,------------Edit Distance(编辑距离)

 (1)答案:

    public int minDistance(String word1, String word2) {
        // write your code here
        // error1: 忘记判断空了
        if ((word1 == null || word1.length() == 0) && (word2 == null || word2.length() == 0)) {
            return 0;
        }
        int m = word1.length();
        int n = word2.length();
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 0; i < m + 1; i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j < n + 1; j++) {
            dp[0][j] = j;
        }
        for (int i = 1; i < m + 1; i++) {
            for (int j = 1; j < n + 1; j++) {
                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1]);
                } else {
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + 1);
                }
            }
        }
        return dp[m][n];
    }
View Code

(2)bug-free; 

6,----------distinct subsequences(不同的子序列)

(1)答案和思路: 前i,前j思路。

    public int numDistinct(String s, String t) {
        // write your code here
        if (t == null) {
            return 1;
        }
        if (s == null) {
            return 0;
        }
        int m = s.length();
        int n = t.length();
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 0; i < m + 1; i++) {
            dp[i][0] = 1;
        }
        for (int i = 1; i < m + 1; i++) {
            for (int j = 1; j < n + 1; j++) {
                if (s.charAt(i - 1) == t.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[m][n];
    }
View Code

 (2)没有bug-free,因为错写了charAt(i)应该是i - 1;

(3)二刷bug-free

 7,---------Interleaving String(交叉字符串)

 (1)答案和思路:也就是前i,j思路

public class Solution {
    /**
     * Determine whether s3 is formed by interleaving of s1 and s2.
     * @param s1, s2, s3: As description.
     * @return: true or false.
     */
    public boolean isInterleave(String s1, String s2, String s3) {
        // write your code here
        if (s1 == null || s2 == null || s3 == null) {
            return false;
        }
        int len1 = s1.length();
        int len2 = s2.length();
        int len3 = s3.length();
        if (len1 + len2 != len3) {
            return false;
        }
        boolean[][] dp = new boolean[len1 + 1][len2 + 1];
        dp[0][0] = true;
        for (int i = 1; i < len1 + 1; i++) {
            if (s1.charAt(i - 1) == s3.charAt(i - 1)) {
                dp[i][0] = true;
            } else {
                break;
            }
        }
        for (int j = 1; j < len2 + 1; j++) {
            if (s2.charAt(j - 1) == s3.charAt(j - 1)) {
                dp[0][j] = true;
            } else {
                break;
            }
        }
        for (int i = 1; i < len1 + 1; i++) {
            for (int j = 1; j < len2 + 1; j++) {
                dp[i][j] = dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(i + j - 1) || dp[i][j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1);
            }
        }
        return dp[len1][len2];
    }
}
View Code

(2)一刷没有做对。

(3)二刷bug-free

 

 

-------------------------------------------

第四周:动态规划一(动态规划三要素:1,求最大最小值;2,判断是否可行;3,统计方案个数;)

不使用动态规划:求具体方案个数,不是序列而是集合。因为dp要求顺序不能变。

-------------------------------------------

1,-----------Triangle( 数字三角形

(1)答案:

    public static int minimumTotal(int[][] triangle) {
        int[][] res = new int[triangle.length][triangle[triangle.length - 1].length];
        for (int j = 0; j < triangle[triangle.length - 1].length; j++) {
            res[triangle.length - 1][j] = triangle[triangle.length - 1][j];
        }
        for (int i = triangle.length - 2; i >= 0; i--) {
            for (int j = 0; j < triangle[i].length; j++) {
                res[i][j] = triangle[i][j] + Math.min(res[i + 1][j], res[i + 1][j + 1]);
            }
        }
        return res[0][0];
    }
View Code

 (2)一刷没有做对是因为注意dp过程中到底是加dp的值还是triangle的值。此外dp比较麻烦可以考虑从后往前。

(3)二刷所犯错误:i--误写成i++;

 

3,-------------Longest Consecutive Sequence 最长连续序列

答案:(1)这是自己写的,已经先排序了。要找更优化的答案:

    public static int longestConsecutive(int[] num) {
        int length = 1;
        Arrays.sort(num);
        int max = 1;
        for (int i = 1; i < num.length; i++) {
            if (num[i] - num[i - 1] == 1) {
                max++;
            } else if (num[i] - num[i -1] == 0) {
                continue;
            } else { 
                length = Math.max(length, max);
                max = 1;
            }
        }
        return Math.max(length, max);
    }
View Code

(2)

4,------------Minimum Path Sum最小路径和

(1)答案:注意length千万别再写错了。此外注意千万别忘记了加上这一格的值。

    public int minPathSum(int[][] grid) {
        // write your code here
        int[][] dp = new int[grid.length][grid[0].length];
        dp[0][0] = grid[0][0];
        for (int j = 1; j < grid[0].length; j++) {
            dp[0][j] = dp[0][j - 1] + grid[0][j];
        }
        int sum2 = dp[0][0];
        for (int i = 1; i < grid.length; i++) {
            dp[i][0] = dp[i - 1][0] + grid[i][0];
        }
        for (int i = 1; i < grid.length; i++) {
            for (int j = 1; j < grid[0].length; j++) {
                dp[i][j] = grid[i][j] + Math.min(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        return dp[grid.length - 1][grid[0].length - 1];
    }
View Code

(2)bug-free; 

 

5,-----------Unique Paths(不同的路径

(1)答案:一定要注意i,j位置。bug=free;

    public int uniquePaths(int m, int n) {
        // write your code here 
        int[][] dp = new int[m][n];
        for (int i = 0; i < m; i++) {
            dp[i][0] = 1;
        }
        for (int j = 0; j < n; j++) {
            dp[0][j] = 1;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }
View Code

(2)一刷bug-free; 

6,------------Climbing Stairs(爬楼梯)

(1)答案:不要忘记特判断。

    public int climbStairs(int n) {
        // write your code here
        if (n <= 1) {
            return 1;
        }
        int[] dp = new int[n];
        dp[0] = 1;
        dp[1] = 2;
        for (int i = 2; i < n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n - 1];
    }
View Code

 (2)一刷:3次才能AC。所犯错误是:首先,台阶是0的时候应该返回0; 其次是注意下标i从2开始递推。

(3)二刷:bug-free;

 7,---------------Jump Game(跳跃游戏)

(1)答案:注意单词的拼写。length;

    public boolean canJump(int[] A) {
        // wirte your code here
        boolean[] result = new boolean[A.length];
        result[0] = true;
        for (int i = 0; i < A.length; i++) {
            if (!result[i]){
                return false;
            }
            for (int j = i + 1; j < A.length && j < i + 1 + A[i]; j++) {
                result[j] = true;
            }
        }
        return result[A.length - 1];
    }
View Code

 (2)bug-free;

 

8,-------------Jump Game II跳跃游戏 II

(1)答案:思路是,dp[0] = 0;然后从1开始,找他前面能到他的min+1;能到等价于:a[j] >= i - j;

    public int jump(int[] A) {
        // write your code here
        int[] dp = new int[A.length];
        dp[0] = 0;
        for (int i = 1; i < A.length; i++) {
            int min = Integer.MAX_VALUE;
            for (int j = 0; j < i; j++) {
                if (A[j] >= i - j) {
                    min = Math.min(min, dp[j]);
                }
            }
            dp[i] = min + 1;
        }
        return dp[A.length - 1];
    }
View Code

(2)bug-free; 

9,------------Unique Paths II不同的路径 II

(1)答案:

    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        // write your code here
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[][] dp = new int[m][n];
        for (int i = 0; i < m; i++) {
            if (obstacleGrid[i][0] != 1) {
                dp[i][0] = 1;
            } else {
                break;
            }
        }
        for (int j = 0; j < n; j++) {
            if (obstacleGrid[0][j] != 1) {
                dp[0][j] = 1;
            } else {
                break;
            }
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j] != 1) {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m - 1][n - 1];
    }
View Code

 (2)一刷AC需要2次,所犯错误是:在初始化第一列/行的时候不仅仅是有障碍物的设为0而是他以后的都设置为0,因为不可达到了。

(3)二刷bug-free;

10,---------------------Longest Increasing Subsequence最长上升子序列

答案:

    public int longestIncreasingSubsequence(int[] nums) {
        // write your code here
        // error1: 忘记判断空了
        // error2: 1 1 1 1 1 1 1
        if (null == nums || nums.length == 0) {
            return 0;
        }
        int res = 0;
        int[] dp = new int[nums.length];
        for (int i = 0; i < dp.length; i++) {
            dp[i] = 1;
            for (int j = i - 1; j >= 0; j--) {
                if (nums[j] <= nums[i]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }
View Code

 

-------------------------------------------

第三周:二叉树和分治法

-------------------------------------------

碰到二叉树的问题的时候,就想想整棵树在该问题上的结果和左右儿子在该问题上的结果之间的联系是什么。

1,------------------Binary Tree Preorder Traversal(二叉树的前序遍历

(1)用递归:bug-free;

 

import java.util.ArrayList;
public class Solution {
    /**
     * @param root: The root of binary tree.
     * @return: Preorder in ArrayList which contains node values.
     */
    public ArrayList<Integer> preorderTraversal(TreeNode root) {
        // write your code here
        ArrayList<Integer> preorder = new ArrayList();
        preorderTraversal(root, preorder);
        return preorder;
    }
    public static void preorderTraversal(TreeNode root, ArrayList<Integer> preorder) {
        if (null == root) {
            return;
        }
        preorder.add(root.val);
        preorderTraversal(root.left, preorder);
        preorderTraversal(root.right, preorder);
    }
}
View Code

 

(2)非递归(必考):

 

2,--------------------Binary Tree Inorder Traversal(二叉树的中序遍历)

(1)用递归:bug-free;

    public ArrayList<Integer> inorderTraversal(TreeNode root) {
        // write your code here
        ArrayList<Integer> res = new ArrayList();
        inorderTraversal(root, res);
        return res;
    }
    public static void inorderTraversal(TreeNode root, ArrayList<Integer> list) {
        if (root == null) {
            return;
        }
        inorderTraversal(root.left, list);
        list.add(root.val);
        inorderTraversal(root.right, list);
    }
View Code

 (2)非递归(必考):

3,---------------Binary Tree Postorder Traversal(二叉树的后序遍历

(1)用递归:bug-free;

    public ArrayList<Integer> postorderTraversal(TreeNode root) {
        // write your code here
        ArrayList<Integer> res = new ArrayList();
        postorderTraversal(root, res);
        return res;
    }
    public static void postorderTraversal(TreeNode root, ArrayList<Integer> list) {
        if (root == null) {
            return;
        }
        postorderTraversal(root.left, list);
        postorderTraversal(root.right, list);
        list.add(root.val);
    }
View Code

(2)非递归(必考): 

4,--------------------Maximum Depth of Binary Tree(二叉树的最大深度)

 答案:bug-free;

    public int maxDepth(TreeNode root) {
        // write your code here
        if (root == null) {
            return 0;
        }
        return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
    }
View Code

 5,--------------Balanced Binary Tree(平衡二叉树

(1)答案:

public class Solution {
    /**
     * @param root: The root of binary tree.
     * @return: True if this Binary tree is Balanced, or false.
     */
    public boolean isBalanced(TreeNode root) {
        // write your code here
        if (root == null) {
            return true;
        }
        return (Math.abs(height(root.right) - height(root.left)) <= 1) && isBalanced(root.left) && isBalanced(root.right);
    }
    public static int height(TreeNode root) {
        if (null == root) {
            return 0;
        }
        return Math.max(height(root.left), height(root.right)) + 1;
    }
}
View Code

(2)一刷需要2次才能AC。主要是错在,一些书写错误,少了函数名之类的。

(2)二刷:bug-free;

 

6,----------------Lowest Common Ancestor(最近公共祖先)

(1)答案:思路在代码中注释了

public class Solution {
    /**
     * @param root: The root of the binary search tree.
     * @param A and B: two nodes in a Binary.
     * @return: Return the least common ancestor(LCA) of the two nodes.
     */
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode a, TreeNode b) {
        // write your code here
        if (root == null || root == a || root == b) {
            return root;
        }
        TreeNode left = lowestCommonAncestor(root.left, a, b);
        TreeNode right = lowestCommonAncestor(root.right, a, b);
        if (left != null && right != null) {
            return root;
        } else if (left != null) {
            return left;
        } else {
            return right;
        }
    }
}
View Code

 

(2)一刷需要三次才能AC: 首先是没搞懂怎么弄。 其次是||与&&的错用。

(3)二刷:bug-free;

7,----------------Binary Tree Maximum Path Sum二叉树中的最大路径和

(1)思路:思路:这里的最大路劲和,其实可以这么理解,1,过root的;2,不过root的。这里又分为两种,就是过left的,过right的,然后递归就可以了。可以认为是这条路径总是要从某一个结点开始往下走的

public class Solution {
    /**
     * @param root: The root of binary tree.
     * @return: An integer.
     */
    static int max = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        // write your code here
        // 思路:这里的最大路劲和,其实可以这么理解,1,过root的;2,不过root的。这里又分为两种,就是过left的,过right的,然后递归就可以了。可以认为是这条路径总是要从某一个结点开始往下走的。
        if (null == root) {
            return 0;
        }
        path(root);
        return max;
    }
    public static int path(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftPath = path(root.left);
        int rightPath = path(root.right);
        int curMax = root.val + Math.max(0, Math.max(leftPath, rightPath));
        max = Math.max(max, Math.max(curMax, root.val + leftPath + rightPath));
        return curMax;
    }
}
View Code

 

(2)一刷没做对。

(2)Binary Tree Maximum Path Sum II 二叉树中的最大路径和

第二种情况,这里比较easy,因为要求过root:

(1)答案:注意遇到了树的题目,首先考虑他和他的左右子树之间有什么联系。

    public int maxPathSum2(TreeNode root) {
        // Write your code here
        if (null == root) {
            return 0;
        }
        int leftSum = maxPathSum2(root.left);
        int rightSum = maxPathSum2(root.right);
        return root.val + Math.max(0, Math.max(leftSum, rightSum));
    }
View Code

(2)一刷没做对;

 

8,------------------Binary Tree Level Order Traversal二叉树的层次遍历

(1)答案:注意,其实每一层就是当前queue还有的都是上一层的,所以用好queue.size来做循环。此外注意queue的add是offer。pop是poll。打好基础知识。

public class Solution {
    /**
     * @param root: The root of binary tree.
     * @return: Level order a list of lists of integer
     */
    public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
        // write your code here
        ArrayList<ArrayList<Integer>> levelOrder = new ArrayList();
        if (null == root) {
            return levelOrder;
        }
        Queue<TreeNode> queue = new LinkedList();
        queue.add(root);
        while (!queue.isEmpty()) {
            ArrayList<Integer> list = new ArrayList();
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode top = queue.poll();
                if (top.left != null) {
                    queue.add(top.left);
                }
                if (top.right != null) {
                    queue.add(top.right);
                }
                list.add(top.val);
            }
            levelOrder.add(list);
        }
        return levelOrder;
    }
}
View Code

(2) 一刷需要两次AC:注意一下,queue.size()是一直在改变的,所以,循环条件不能用它,而应该是先记下来上一层的size。

(3)二刷bug-free;

9,--------------------Binary Tree Level Order Traversal II(二叉树的层次遍历 II

(1) 答案:注意,和上一题的差别就在于利用了list的add插入。

 import java.util.ArrayList;
 import java.util.LinkedList;
public class Solution {
    /**
     * @param root: The root of binary tree.
     * @return: buttom-up level order a list of lists of integer
     */
    public ArrayList<ArrayList<Integer>> levelOrderBottom(TreeNode root) {
        // write your code here
        ArrayList<ArrayList<Integer>> levelOrder = new ArrayList();
        if (null == root) {
            return levelOrder;
        }
        Queue<TreeNode> queue = new LinkedList();
        queue.add(root);
        while (!queue.isEmpty()) {
            ArrayList<Integer> list = new ArrayList();
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode top = queue.poll();
                list.add(top.val);
                if (top.left != null) {
                    queue.add(top.left);
                }
                if (top.right != null) {
                    queue.add(top.right);
                }
            }
            levelOrder.add(0, list);
        }
        return levelOrder;
    }
}
View Code

(2) 一刷的时候bug-free;

 

10,---------------Binary Tree Zigzag Level Order Traversal二叉树的锯齿形层次遍历

答案。需要逆序的那一层就利用add(位置,值)。然后用flag来控制是否逆过来。

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
    /**
     * @param root: The root of binary tree.
     * @return: A list of lists of integer include
     *          the zigzag level order traversal of its nodes' values
     */
    public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
        // write your code here
        ArrayList<ArrayList<Integer>> traversal = new ArrayList();
        if (root == null) {
            return traversal;
        }
        Queue<TreeNode> queue = new LinkedList();
        int level = 0;
        queue.add(root);
        while (!queue.isEmpty()) {
            ArrayList<Integer> list = new ArrayList();
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode top = queue.poll();
                if (top.left != null) {
                    queue.add(top.left);
                }
                if (top.right != null) {
                    queue.add(top.right);
                }
                if (level % 2 == 0) {
                    list.add(top.val);
                } else {
                    list.add(0, top.val);
                }
            }
            traversal.add(list);
            level++;
        }
        return traversal;
    }
}
View Code

(2)一刷的时候bug-free;

 11,---------------------(验证二叉查找树)

答案:注意,int不够了。

    public boolean isValidBST(TreeNode root) {
        // write your code here
        return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }
    public static boolean isValidBST(TreeNode root, long left, long right) {
        if (root == null) {
            return true;
        }
        return (root.val > left && root.val < right) && isValidBST(root.left, left, root.val) && isValidBST(root.right, root.val, right);
    }
View Code

 12,-------- Inorder Successor in Binary Search Tree(中序后继)

(1)答案:这是search tree;利用好search tree的性质。

public class Solution {
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        // write your code here
        if (root == null) {
            return null;
        }
        TreeNode successor = null;
        while (root != null) {
            if (root != p && root.val > p.val) {
                successor = root;
                root = root.left;
            } else {
                root = root.right;
            }
        }
        return successor;
    }
}
View Code

 (2)一定要仔细阅读题目,这是search tree;利用好search tree的性质。

 (3)二刷:bug-free;

 13,---------------------Binary Search Tree Iterator 二叉查找树迭代器

答案:

public class BSTIterator {
    //@param root: The root of binary tree.
    ArrayList<TreeNode> list = new ArrayList<TreeNode>();
    int flag = 0;
    public BSTIterator(TreeNode root) {
        // write your code here
        list = inorderTraversal(root);
    }

    //@return: True if there has next node, or false
    public boolean hasNext() {
        // write your code here
        if (list == null || flag >= list.size()) {
            return false;
        }
        return true;
    }
    //@return: return next node
    public TreeNode next() {
        // write your code here
        if (list == null || flag >= list.size()) {
            return null;
        }
        return list.get(flag++);
    }
    public static ArrayList<TreeNode> inorderTraversal(TreeNode root) {
        // write your code here
        ArrayList<TreeNode> res = new ArrayList();
        inorderTraversal(root, res);
        return res;
    }
    public static void inorderTraversal(TreeNode root, ArrayList<TreeNode> list) {
        if (root == null) {
            return;
        }
        inorderTraversal(root.left, list);
        list.add(root);
        inorderTraversal(root.right, list);
    }
}
View Code

 14,-----------------Search Range in Binary Search Tree二叉查找树中搜索区间

答案:

    public ArrayList<Integer> searchRange(TreeNode root, int k1, int k2) {
        // write your code here
        ArrayList<Integer> res = new ArrayList();
        searchRange(root, k1, k2, res);
        return res;
    }
    public static void searchRange(TreeNode root, int k1, int k2, ArrayList<Integer> res) {
        if (root == null) {
            return;
        }
        if (root.val <= k2 && root.val >= k1) {
            searchRange(root.left, k1, k2, res);
            res.add(root.val);
            searchRange(root.right, k1, k2, res);
        } else if (root.val > k2) {
            searchRange(root.left, k1, k2, res);
        } else {
            searchRange(root.right, k1, k2, res);
        }
    }
View Code

 

 

-------------------------------------------

 第二周:二分查找:

-------------------------------------------

 

1,Classical Binary Search(二分查找)

答案:bug-free;

    public static int findPosition(int[] nums, int target) {
        if(nums == null || nums.length == 0) {
            return -1;
        }
        int start = 0;
        int end = nums.length - 1;
        while (start <= end){
            int mid = start + (end - start) / 2;
            if (nums[mid] == target){
                return mid;
            } else if (nums[mid] < target) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return -1;
    }
View Code

2,First Position of Target(找出现的第一个位置)

 答案:bug-free;

    public static int binarySearch(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int res = -1;
        int start = 0;
        int end = nums.length - 1;
        while (start <= end){
            int mid = start + (end - start) / 2;
            if (nums[mid] == target){
                res = mid;
                end = mid - 1;
            } else if (nums[mid] < target) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return res;
    }
View Code

3,Last Position of Target(找出现的最后一个位置)

答案: bug-free;

if(nums == null || nums.length == 0) {
            return -1;
        }
        int res = -1;
        int start = 0;
        int end = nums.length - 1;
        while (start <= end){
            int mid = start + (end - start) / 2;
            if (nums[mid] == target){
                res = mid;
                start = mid + 1;
            } else if (nums[mid] < target) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return res;
View Code

 4,sqrt(x)求平方根

(1)答案和思路:利用二分来做,注意的是,要特判0.而且注意start开始位置是1.结束位置是x,如果要让他是x/2结束,那么特判1.

class Solution {
    /**
     * @param x: An integer
     * @return: The sqrt of x
     */
    public int sqrt(int x) {
        if (x < 0) {
            return -1;
        }
        if (x <= 1) {
            return x;
        }
        int start = 1;
        int end = x / 2;
        int res = -1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (x / mid == mid) {
                return mid;
            } else if (x / mid < mid) {
                end = mid - 1;
            } else {
                res = mid;
                start = mid + 1;
            }
        }
        return res;
    }
}
View Code

(2)一刷AC所需次数2次:所犯错误有:1,没有特判0,导致分母为0; 2,start从0开始,导致分母为0;

(3)二刷:bug-free;

5,search a 2D matrix (矩阵里面查找元素)

(1)答案和思路:也是用二分来找找。注意的就是,这里会用到两次二分,所以,start,end,left,right什么的要分清楚了。

答案:

    public boolean searchMatrix(int[][] matrix, int target) {
        if (null == matrix || matrix.length == 0) {
            return false;
        }
        //find row
        int start = 0;
        int end = matrix.length - 1;
        int row = -1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (matrix[mid][0] == target) {
                return true;
            } else if (matrix[mid][0] < target) {
                row = mid;
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        if (row == -1) {
            return false;
        }
        start = 0;
        end = matrix[row].length - 1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (matrix[row][mid] == target) {
                return true;
            } else if (matrix[row][mid] < target) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return false;
    }
View Code

(2)一刷所需AC次数3次:所犯错误:1,end,right混淆。导致死循环。2,变量row,res混淆。

(3)二刷:bug-free;

 5,search insert position(搜索要插入的位置)

(1)答案和思路:注意的是无论大小都要记下index可以取的位置

(2)一刷要AC次数3次:所犯错误:1,当a == null || a.length == 0时候,记住不是返回-1,而是0;

(3)二刷:bug-free;

 6,Count of Smaller Number(统计比给定整数小的数的个数

(1)答案和思路:利用二分来做。注意的地方:如果a == null。那么不能return null;所以一定要注意特判地方不要随时返回-1;

import java.util.Arrays;

public class Solution {
   /**
     * @param A: An integer array
     * @return: The number of element in the array that 
     *          are smaller that the given integer
     */
    public ArrayList<Integer> countOfSmallerNumber(int[] a, int[] queries) {
        // write your code here
        ArrayList<Integer> res = new ArrayList();
        if (a == null || queries == null) {
            return res;
        }
        Arrays.sort(a);
        for (int i = 0; i < queries.length; i++) {
            res.add(binarySearch(a, queries[i]));
        }
        return res;
    }
    public static int binarySearch(int[] a, int target) {
        if (a == null || a.length == 0) {
            return 0;
        }
        int start = 0;
        int end = a.length - 1;
        int res = 0;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (a[mid] < target) {
                res = mid + 1;
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return res;
    }
}
View Code

 (2)一刷AC需要三次。所犯错误a==null,return res;

(3)二刷:没有bug-free。所犯错误,a==null || a.length == 0,不能return -1;

7,------------------Search for a Range(搜索区间)

 答案:bug-free;

public class Solution {
    /**
     *@param A : an integer sorted array
     *@param target :  an integer to be inserted
     *return : a list of length 2, [index1, index2]
     */
    public int[] searchRange(int[] a, int target) {
        // write your code here
        int[] res = new int[2];
        res[0] = -1;
        res[1] = -1;
        if (a == null || a.length == 0) {
            return res;
        }
        res[0] = findStartPosition(a, target);
        res[1] = findEndPosition(a, target);
        return res;
    }
    public static int findStartPosition(int[] a, int target) {
        if (a == null || a.length == 0) {
            return -1;
        }
        int start = 0;
        int end = a.length - 1;
        int res = -1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (a[mid] == target) {
                res = mid;
                end = mid - 1;
            } else if (a[mid] < target) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return res;
    }
    public static int findEndPosition(int[] a, int target) {
        if (a == null || a.length == 0) {
            return -1;
        }
        int start = 0;
        int end = a.length - 1;
        int res = -1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (a[mid] == target) {
                res = mid;
                start = mid + 1;
            } else if (a[mid] < target) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return res;
    }
}
View Code

 8,------------------First Bad Version(第一个错误的代码版本)

答案:注意start从1开始; bug-free;

    public int findFirstBadVersion(int n) {
        if (n < 0) {
            return -1;
        }
        int start = 0;
        int end = n;
        int res = -1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (SVNRepo.isBadVersion(mid)) {
                res = mid;
                end = mid - 1;
            } else {
                start = mid + 1;
            }
        }
        return res;
    }
View Code

 9,-----------------Search in a Big Sorted Array(在大数组中查找)

(1)答案和思路:利用二分。注意的地方有:1,不要错把continue用成了break。2,注意二分题目,找的往往是第一个位置

public class Solution {
    /**
     * @param reader: An instance of ArrayReader.
     * @param target: An integer
     * @return : An integer which is the index of the target number
     */
    public int searchBigSortedArray(ArrayReader reader, int target) {
        // write your code here
        if (reader == null) {
            return -1;
        }
        int start = 0;
        int end = Integer.MAX_VALUE;
        int res = -1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (reader.get(mid) == -1) {
                end = mid - 1;
                continue;
            }
            if (reader.get(mid) == target) {
                res = mid;
                end = mid - 1;
            } else if (reader.get(mid) < target) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return res;
    }
}
View Code

 (2)一刷AC需要次数:3次;所犯错误有:1,break;2,没有注意有重复元素。

(3)二刷:bug-free;

 10,-------------Find Minimum in Rotated Sorted Array(寻找旋转排序数组中的最小值

答案:注意end的位置是length - 1;bug-free;

    public static int findMin(int[] num) {
        int res = Integer.MAX_VALUE;
        if (num == null || num.length == 0) {
            return -1;
        }
        if (num[0] < num[num.length - 1]) {
            return num[0];
        } else {
            int start = 0;
            int end = num.length - 1; // error
            while (start <= end) {
                int mid = start + (end - start) / 2;
                if (num[mid] <= num[end]) {
                    res = Math.min(res, num[mid]);
                    end = mid - 1;
                } else {
                    start = mid + 1;
                }
            }
        }
        return res;
    }
View Code

 

 11,------------Search in Rotated Sorted Array(搜索旋转排序数组

答案:记住end从length - 1开始。bug-free;

public class Solution {
    /** 
     *@param A : an integer rotated sorted array
     *@param target :  an integer to be searched
     *return : an integer
     */
    public int search(int[] a, int target) {
        // write your code here
        if (a == null || a.length == 0) {
            return -1;
        }
        int start = 0;
        int end = a.length - 1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (a[mid] == target) {
                return mid;
            } else if (a[mid] <= a[end]) {
                if (target > a[mid] && target <= a[end]) {
                    start = mid + 1;
                } else {
                    end = mid - 1;
                }
            } else {
                if (target >= a[start] && target < a[mid]) {
                    end = mid - 1;
                } else {
                    start = mid + 1;
                }
            }
        }
        return -1;
    }
}
View Code

 

 12,---------------Find Peak Element 寻找峰值

答案:切记不要忽略了最重要的条件,不然代码好长好丑。bug-free;

class Solution {
    /**
     * @param A: An integers array.
     * @return: return any of peek positions.
     */
    public int findPeak(int[] a) {
        // write your code here
        if (a == null || a.length <= 2) {
            return -1;
        }
        int start = 1;
        int end = a.length -2;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (a[mid] > a[mid - 1] && a[mid] > a[mid + 1]) {
                return mid;
            } else if (a[mid] < a[mid - 1]) {
                end = mid - 1;
            } else {
                start = mid + 1;
            }
        }
        return -1;
    }
}
View Code

 

 

 13,-----------Recover Rotated Sorted Array(恢复旋转排序数组

(1)答案:注意最新答案,利用了二分查到到开始,然后利用逆序的逆序来解题。这是不重复元素的做法。是错的。

public class Solution {
    /**
     * @param nums: The rotated sorted array
     * @return: void
     */
    public static void recoverRotatedSortedArray(ArrayList<Integer> nums) {
        int index = findMin(nums);
        reverseList(nums, 0, index - 1);
        reverseList(nums, index, nums.size() - 1);
        reverseList(nums, 0, nums.size() - 1);
    }
    public static void reverseList(ArrayList<Integer> num, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            int temp = num.get(i);
            num.set(i, num.get(j));
            num.set(j, temp);
        }
    }
    public static int findMin(ArrayList<Integer> num) {
        int res = Integer.MAX_VALUE;
        int ans = 0;
        if (num == null || num.size() == 0) {
            return -1;
        }
        if (num.get(0) < num.get(num.size() - 1)) {
            return 0;
        } else {
            int start = 0;
            int end = num.size() - 1; // error
            while (start <= end) {
                int mid = start + (end - start) / 2;
                if (num.get(mid) <= num.get(end)) {
                    if (num.get(mid) < res) {
                        res = num.get(mid);
                        ans = mid;
                    }
                    end = mid - 1;
                } else {
                    start = mid + 1;
                }
            }
        }
        return ans;
    }
}
View Code

当含有重复元素的时候, 答案是这个:

import java.util.ArrayList;

public class Solution {
    /**
     * @param nums: The rotated sorted array
     * @return: void
     */
    public void recoverRotatedSortedArray(ArrayList<Integer> nums) {
        // write your code
        if (null == nums || nums.size() == 0) {
            return;
        }
        for (int i = 0; i < nums.size() - 1; i++) {
            if (nums.get(i) > nums.get(i + 1)) {
                reverseArrayList(nums, 0, i);
                reverseArrayList(nums, i + 1, nums.size() - 1);
                reverseArrayList(nums, 0, nums.size() - 1);
            }
        }
        
    }
    
    // reverse the ArrayList
    public static void reverseArrayList(ArrayList<Integer> a, int start, int end) {
        // swap the a.get(start) and the a.get(end)
        /** Error:
         *while (start < end) {
         *    a.get(start) = a.get(start) ^ a.get(end);
         *    a.get(end) = a.get(start) ^ a.get(end);
         *    a.get(start) = a.get(start) ^ a.get(end);
         *    start++;
         *    end--;
         * }
         */
         while (start < end) {
             a.set(start, a.get(start) ^ a.get(end));
             a.set(end, a.get(start) ^ a.get(end));
             a.set(start, a.get(start) ^ a.get(end));
             start++;
             end--;
         }
    }
}
View Code

(2)一刷不能bug-free,因为用了二分来做,是错的。

(3)二刷,bug-free;

 14.-------------Rotate String(旋转字符串

(1)答案

public class Solution {
    /**
     * @param str: an array of char
     * @param offset: an integer
     * @return: nothing
     */
    public void rotateString(char[] str, int offset) {
        if (null == str || str.length <= 1) {
            return;
        }
        offset = offset % str.length;
        reverseString(str, 0, str.length - offset - 1);
        reverseString(str, str.length - offset, str.length - 1);
        reverseString(str, 0, str.length - 1);
    }
    public static void reverseString(char[] str, int start, int end) {
        if (null == str || str.length == 0) {
            return;
        }
        while (start < end) {
            // Error:
            // str[start] = str[start] ^ str[end];
            // str[end] = str[start] ^ str[end];
            // str[start] = str[start] ^str[end];
            str[start] = (char) (str[start] ^ str[end]);
            str[end] = (char) (str[start] ^ str[end]);
            str[start] = (char) (str[start] ^ str[end]);
            start++;
            end--;
        }
    }
}
View Code

(2)1刷需要3次才能AC:因为,1:当字符串^时候结果得到的是整数,需要(char);

(2)2刷。bug-free;

 

-------------------------------------------

第一周:入门式。字符串,子集,排列

-------------------------------------------

 

1,strStr(字符串查找

(1)答案和思路:就是常规的一一对比,注意一下循环的结束位置即可。

import java.lang.String;

class Solution {
    /**
     * Returns a index to the first occurrence of target in source,
     * or -1  if target is not part of source.
     * @param source string to be scanned.
     * @param target string containing the sequence of characters to match.
     */
    public int strStr(String source, String target) {
        if (source == null || target == null) {
            return -1;
        }
        for (int i = 0; i < source.length() - target.length() + 1; i++) {
            int j = 0;
            for (j = 0; j < target.length(); j++) {
                if (source.charAt(i + j) != target.charAt(j)) {
                    break;
                }
            }
            if (j == target.length()) {
                return i;
            }
        }
        return -1;
    }
}
View Code

 

(2)AC所需次数:4.所犯错误有:String的length,应该是length(); 第一个字符串的终止位置应该是他的长度减去比较字符串的长度。所以注意不是<而是<=。import java.lang.String;

 (3) 二刷AC所需次数:bug-free;

2,Subsets(子集)

(1)答案和思路:每放入一个元素,除了保留已有的那些子集之外,在这些已有的每一个子集上加上新来的元素。

 

import java.util.ArrayList;
import java.util.Arrays;

class Solution {
    /**
     * @param S: A set of numbers.
     * @return: A list of lists. All valid subsets.
     */
    public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
        Arrays.sort(nums);
        ArrayList<ArrayList<Integer>> subsets = new ArrayList();
        ArrayList<Integer> subset = new ArrayList();
        subsets.add(subset);
        if (nums == null || nums.length == 0) {
            return subsets;
        }
        for (int i = 0; i < nums.length; i++) {
            ArrayList<ArrayList<Integer>> tempSubsets = new ArrayList(subsets);
            for (ArrayList<Integer> preSubset : subsets) {
                ArrayList<Integer> curSubset = new ArrayList(preSubset);
                curSubset.add(nums[i]);
                tempSubsets.add(curSubset);
            }
            subsets = new ArrayList(tempSubsets);
        }
        return subsets;
    }
}
View Code

 

(2)一刷AC所需次数:3次。所犯错误:加入新来的元素,在遍历的时候加,那样已经改变了原来的子集。所以要遍历出一个子集,然后new出一个子集,再add。 还有一个错误就是因为要保证子集的非降序,所以要先排序。

 (3) 二刷AC所需次数:2次。所犯错误:sort。

 

3,Subsets II(带重复元素的子集)

(1)答案和思路:与1不同的地方就是在add进去的时候,用一下contains。

import java.util.ArrayList;
import java.util.Collections;

class Solution {
    /**
     * @param S: A set of numbers.
     * @return: A list of lists. All valid subsets.
     */
    public ArrayList<ArrayList<Integer>> subsetsWithDup(ArrayList<Integer> s){
        ArrayList<ArrayList<Integer>> subsets = new ArrayList();
        ArrayList<Integer> subset = new ArrayList();
        subsets.add(subset);
        if (s == null || s.size() == 0) {
            return subsets;
        }
        Collections.sort(s);
        for (int num : s) {
            ArrayList<ArrayList<Integer>> tempSubsets = new ArrayList(subsets);
            for (ArrayList<Integer> preSubset : subsets) {
                ArrayList<Integer> curSubset = new ArrayList(preSubset);
                curSubset.add(num);
                if (!tempSubsets.contains(curSubset)) {
                    tempSubsets.add(curSubset);
                }
            }
            subsets = new ArrayList(tempSubsets);
        }
        return subsets;
    }
}
View Code

(2)一刷AC需要三次,所犯错误为:1,忘记排序;2,不会对list排序:import java.util.Collections; Collections.sort(list);3,tempSubsets 错写temp;

(3)二刷:bug-free;

 

4,Permutations(全排列)

(1)答案和思路:就是每次来一个数,就把他插入到已有的permutation中。

import java.util.ArrayList;

class Solution {
    /**
     * @param nums: A list of integers.
     * @return: A list of permutations.
     */
    public ArrayList<ArrayList<Integer>> permute(ArrayList<Integer> nums) {
        // write your code here
        ArrayList<ArrayList<Integer>> permutations = new ArrayList();
        ArrayList<Integer> permutation = new ArrayList();
        if (nums == null || nums.size() == 0) {
            return permutations;
        }
        permutations.add(permutation);
        for (int num : nums) {
            ArrayList<ArrayList<Integer>> tempPermutations = new ArrayList();
            for (ArrayList<Integer> prePermutation : permutations) {
                for (int i = 0; i <= prePermutation.size(); i++) {
                    ArrayList<Integer> curPermutation = new ArrayList(prePermutation);
                    curPermutation.add(i, num);
                    tempPermutations.add(curPermutation);
                }
            }
            permutations = new ArrayList(tempPermutations);
        }
        return permutations;
    }
}
View Code

 

(2)一刷AC需要两次:所犯错误:1,当输入null的时候全排列和子集是不一样的,子集是[[]]。全排列是[],也就是[null]。所以,在判断之前不能add任何东西。

(3)二刷:bug-free;

5,Permutations(带重复元素的全排列)

(1)答案和思路:在add之前进行一次判断就可以了。

import java.util.ArrayList;

class Solution {
    /**
     * @param nums: A list of integers.
     * @return: A list of permutations.
     */
    public ArrayList<ArrayList<Integer>> permuteUnique(ArrayList<Integer> nums) {
        // write your code here
        ArrayList<ArrayList<Integer>> permutations = new ArrayList();
        ArrayList<Integer> permutation = new ArrayList();
        if (nums == null || nums.size() == 0) {
            return permutations;
        }
        permutations.add(permutation);
        for (int num : nums) {
            ArrayList<ArrayList<Integer>> tempPermutations = new ArrayList();
            for (ArrayList<Integer> prePermutation : permutations) {
                for (int i = 0; i <= prePermutation.size(); i++) {
                    ArrayList<Integer> curPermutation = new ArrayList(prePermutation);
                    curPermutation.add(i, num);
                    if (!tempPermutations.contains(curPermutation)) {
                        tempPermutations.add(curPermutation);
                    }
                }
            }
            permutations = new ArrayList(tempPermutations);
        }
        return permutations;
    }
}
View Code

(2)一刷:bug-free;

 

你可能感兴趣的:((lintcode全部题目解答之)九章算法之算法班题目全解(附容易犯的错误))