Lintcode: remove node from binary search tree

Given a root of Binary Search Tree with unique value for each node. Remove the node with given value. If there is no such a node with given value in the binary search tree, do nothing. You should keep the tree still a binary search tree after removal.
题目不难,代码比较长。

public class Solution {
    public TreeNode removeNode(TreeNode root, int value) {
        TreeNode dummy = new TreeNode(-1), cur = root, pre = dummy;
        dummy.right = root;
        while (cur != null) {
            if (cur.val == value) {
                if (pre.right == cur) {
                    pre.right = makeNew(cur);
                } else {
                    pre.left = makeNew(cur);
                }
                break;
            } else if (cur.val < value) {
                pre = cur;
                cur = cur.right;
            } else {
                pre = cur;
                cur = cur.left;
            }
        }
        return dummy.right;
    }
    
    private TreeNode makeNew(TreeNode node) {
        if (node.left == null && node.right == null) {
            return null;
        }
        if (node.left == null || node.right == null) {
            return node.left == null ? node.right : node.left;
        }
        TreeNode left = node.left.right;
        TreeNode leftMost = node.right; //the left most node of right child
        while (leftMost.left != null) {
            leftMost = leftMost.left;
        }
        leftMost.left = left;//appen left's right tree to right's left most node
        node.left.right = node.right;
        return node.left;
    }
}

Lintcode: k sum

用一个三位数组记录信息,第一维表示index,即从array的第0个元素到当前这个元素,第二维表示用了几个数,第三维表示能取到的和。这个数组store[i][j][k]表示的就是从第0个元素到当前元素i,取j个元素,其和为k,有集中取法。
这个办法的问题在于如果target很大的话会很浪费空间。不知道有没有更好的办法。可能用hashtable取代最后一维可以节省一些空间。

public class Solution {
    public int  kSum(int A[], int k, int target) {
        int[][][] store = new int[A.length][k+1][target+1];
        for (int i = 0; i < A.length; i++) {
        	for (int number = 1; number <= k; number++) {
	    		for (int t = 0; t <= target; t++) {
	    			store[i][number][t] = i > 0 ? store[i-1][number][t] : 0;
	    			if (number == 1 && t == A[i]) {
	    				store[i][number][t]++;
	    			}
	    			if (t - A[i] >= 0 && i > 0) {
	    				store[i][number][t] += store[i-1][number-1][t-A[i]];
	    			}
	    		}
	    	}
        }
        return store[A.length - 1][k][target];
    }
}

Lintcode: Minimum Adjustment Cost

Given an integer array, adjust each integers so that the difference of every adjcent integers are not greater than a given number target.

If the array before adjustment is A, the array after adjustment is B, you should minimize the sum of |A[i]-B[i]|


public class Solution {
    public int MinAdjustmentCost(ArrayList<Integer> A, int target) {
        int[][] store = new int[A.size()][101];
        for (int i = 0; i < A.size(); i++) {
            for (int j = 0; j <= 100; j++) {
                store[i][j] = i == 0 ? Math.abs(j - A.get(i)) : Integer.MAX_VALUE;
            }
        }   
        for (int i = 1; i < A.size(); i++) {
            for (int j = 0; j <= 100; j++) {
                for (int k = j - target; k <= j + target && k <= 100; k++) {
                    if (k >= 0 && store[i-1][k] < Integer.MAX_VALUE) {
                        store[i][j] = Math.min(store[i][j], store[i-1][k] + Math.abs(j - A.get(i)));
                    }
                }
            }
        }
        int result = Integer.MAX_VALUE;
        for (int j = 0; j <= 100; j++) {
            result = Math.min(result, store[A.size()-1][j]);
        }
        return result;
    }
}

4sum

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:
Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
The solution set must not contain duplicate quadruplets.


Solution 1:递归解法超时,忘记了数组已经排好序,最里层2sum的时候直接用两个指针即可

public class Solution {
    public List<List<Integer>> fourSum(int[] num, int target) {
        Arrays.sort(num);
        List<List<Integer>> res = sub(num, target, 0, 4);
        return res == null ? new ArrayList<List<Integer>>() : res;
    }
 
    private List<List<Integer>> sub(int[] num, int target, int index, int numbers) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if (target == 0 && numbers == 0) {
            result.add(new ArrayList<Integer>());
            return result;
        }
        if (numbers < 0 || (index >= num.length || num[index] > target)) {
            return null;
        }
         
        for (int i = index; i < num.length; i++) {
            List<List<Integer>> lists = sub(num, target - num[i], i+1, numbers-1);
            if (lists != null && lists.size() > 0) {
                for (List<Integer> list : lists) {
                    list.add(0, num[i]);
                    result.add(list);
                }
            }
            int tmp = i + 1;
            while (tmp < num.length && num[tmp] == num[i]) {
                tmp++;
            }
            i = tmp - 1;
        }
        return result;
    }
}

Solution 2:
注意最里层对于重复数字的处理,只有当num[start] + num[end] == twoSumTarget满足时,才跳过剩下的重复数字,否则e.g. target= 4, 对于[2,2,4],如果先跳过重复数字的话[2,2]会miss

public class Solution {
    public List<List<Integer>> fourSum(int[] num, int target) {
        Arrays.sort(num);
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        for (int i = 0; i < num.length; i++) {
            for (int j = i + 1; j < num.length; j++) {
                int twoSumTarget = target - num[i] - num[j];
                int start = j + 1, end = num.length - 1;
                while (start < end) {
                    if (num[start] + num[end] == twoSumTarget) {
                        List<Integer> list = new ArrayList<Integer>();
                        list.add(num[i]);
                        list.add(num[j]);
                        list.add(num[start]);
                        list.add(num[end]);
                        result.add(list);
                        int tmp = start + 1;
                        while (tmp < end && num[tmp] == num[start]) {
                            tmp++;
                        }
                        start = tmp;
                        tmp = end - 1;
                        while (tmp > start && num[tmp] == num[end]) {
                            tmp--;
                        }
                        end = tmp;
                    } else if (num[start] + num[end] < twoSumTarget) {
                        start++;
                    } else {
                        end--;
                    }
                }
                int tmp = j + 1;
                while (tmp < num.length && num[tmp] == num[j]) {
                    tmp++;
                }
                j = tmp - 1;
            }
            int tmp = i + 1;
            while (tmp < num.length && num[tmp] == num[i]) {
                tmp++;
            }
            i = tmp - 1;
        }
        return result;
    }
}

Solution 3:另外一种解法是利用3sum

public class Solution {
    public List<List<Integer>> fourSum(int[] num, int target) {
        Arrays.sort(num);
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        for (int i = 0 ;i < num.length - 3; i++) {
        	List<List<Integer>> tmp = threeSum(num, i + 1, target - num[i]);
            if (tmp != null && !tmp.isEmpty()) {
                for (List<Integer> list : tmp) {
                    list.add(0, num[i]);
                    result.add(list);
                }
            }
            while (i + 1 < num.length && num[i+1] == num[i]) {
                i++;
            }
        }
        return result;
    }
    private List<List<Integer>> threeSum(int[] num, int index, int target) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        for (int i = index; i < num.length - 2; i++) {
            int sum = target - num[i];
            int start = i+1, end = num.length - 1;
            while (start < end) {
                if (num[start] + num[end] == sum) {
                    List<Integer> list = new ArrayList<Integer>();
                    list.add(num[i]);
                    list.add(num[start]);
                    list.add(num[end]);
                    result.add(list);
                    while (start + 1 < end && num[start+1] == num[start]) {
                        start++;
                    }
                    while (end - 1 > start && num[end-1] == num[end]) {
                        end--;
                    }
                    start++;
                    end--;
                } else if (num[start] + num[end] < sum) {
                    while (start + 1 < end && num[start+1] == num[start]) {
                        start++;
                    }
                    start++;
                } else {
                    while (end - 1 > start && num[end-1] == num[end]) {
                        end--;
                    }
                    end--;
                }
            }
            while (i + 1 < num.length && num[i+1] == num[i]) {
                i++;
            }
        }
        return result;
    }
}

Lintcode: Median II

Numbers keep coming, return the median of numbers at every time a new number added.
Median is the number that in the middle of a sorted array. If there are n numbers in a sorted array A, the median is A[(n-1)/2].
用到了heap,i.e. Java里是priorityqueue,平时很少用到,需要练习。

public class Solution {
    public int[] medianII(int[] nums) {
        PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
        class maxComparator implements Comparator<Integer> {
            public int compare(Integer a, Integer b) {
                return Integer.compare(b, a);
            }
        }
        PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(nums.length, new maxComparator());
        int[] result = new int[nums.length];
        
        for (int i = 0; i < nums.length; i++) {
            if (minHeap.size() < maxHeap.size()) {
                if (nums[i] < maxHeap.peek()) {
                    minHeap.offer(maxHeap.poll());
                    maxHeap.offer(nums[i]);
                } else {
                    minHeap.offer(nums[i]);
                }
            } else {
                if (minHeap.size() > 0 && nums[i] > minHeap.peek()) {
                    maxHeap.offer(minHeap.poll());
                    minHeap.offer(nums[i]);
                } else {
                    maxHeap.offer(nums[i]);
                }
            }
            result[i] = maxHeap.peek();
        }
        return result;
    }
}

Lintcode: max tree

Given an integer array with no duplicates. A max tree building on this array is defined as follow:

The root is the maximum number in the array
The left subtree and right subtree are the max trees of the subarray divided by the root number.
Construct the max tree by the given array.
还是用到了ordered stack。对于每个数,他的左右右节点是在他与第一个比他大的数之间,比他小的最大数,因此维护一个递减stack就可以得到。

public class Solution {
    public TreeNode maxTree(int[] A) {
        Stack<TreeNode> stack = new Stack<TreeNode>();//decreasing stack
        for (int i = 0; i < A.length; i++) {
            TreeNode newNode = new TreeNode(A[i]);
            TreeNode pre = null;
            while (!stack.isEmpty() && stack.peek().val < A[i]) {
                TreeNode cur = stack.pop();
                if (pre != null) {
                    cur.right = pre;
                }
                pre = cur;
                newNode.left = pre;
            }
            stack.push(newNode);
        }
        TreeNode preNode = null;
        while (!stack.isEmpty()) {
            TreeNode curNode = stack.pop();
            curNode.right = preNode;
            preNode = curNode;
        }
        return preNode;
    }
}

Lintcode: heapify

Given an integer array, heapify it into a min-heap array.
For a heap array A, A[0] is the root of heap, and for each A[i], A[i * 2 + 1] is the left child of A[i] and A[i * 2 + 2] is the right child of A[i].
基础题,一定要熟练掌握

public class Solution {
    public void heapify(int[] A) {
        for (int i = A.length / 2; i >= 0; i--) {
        	heapify(A, i);
        }
    }

    private void heapify(int[] A, int i) {
    	if (i > A.length) {
    		return;
    	}
    	int left = i * 2 + 1 < A.length ? A[i*2+1] : Integer.MAX_VALUE;
    	int right = i * 2 + 2 < A.length ? A[i*2+2] : Integer.MAX_VALUE;
    	if (left < right && left < A[i]) {
    		A[i*2+1] = A[i];
    		A[i] = left;
    		heapify(A, i*2+1);
    	} else if (right <= left && right < A[i]) {
    		A[i*2+2] = A[i];
    		A[i] = right;
    		heapify(A, i*2+2);
    	}
    }
}

Leetcode SQL: Nth Highest Salary

要熟练掌握declare, set等语句。
Solution 1:用group by

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
declare m int;
set m = n - 1;
  RETURN (
      # Write your MySQL query statement below.
      select salary from Employee 
      group by salary 
      order by salary desc limit m, 1
  );
END

Solution 2: 用distinct

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
declare m int;
set m = n - 1;
  RETURN (
      # Write your MySQL query statement below.
      select distinct salary from Employee 
      order by salary desc limit m, 1
  );
END

Leetcode SQL: Second Highest Salary

Write a SQL query to get the second highest salary from the Employee table.

+—-+——–+
| Id | Salary |
+—-+——–+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+—-+——–+
For example, given the above Employee table, the second highest salary is 200. If there is no second highest salary, then the query should return null.
Solution 1:

select max(salary) from Employee
where salary < (select max(salary) from Employee);

Continue reading

Leetcode SQL: combine two tables

之前全用的小写,发现不能通过,后来发现Linux下mysql是区分大小写的,具体规则:
MySQL在Linux下数据库名、表名、列名、别名大小写规则是这样的:

  1、数据库名与表名是严格区分大小写的;

  2、表的别名是严格区分大小写的;

  3、列名与列的别名在所有的情况下均是忽略大小写的;

  4、变量名也是严格区分大小写的;
主要考察的是left join。注意:left join 和 left outer join是一样的。

select p.firstname, p.lastname, a.city, a.state 
from person p left outer join address a 
on p.personid = a.personid