显示标签为“lintcode”的博文。显示所有博文
显示标签为“lintcode”的博文。显示所有博文

2015年5月19日星期二

Implement Queue by Two Stacks

As the title described, you should only use two stacks to implement a queue's actions.
The queue should support push(element)pop() and top() where pop is pop the first(a.k.a front) element in the queue.
Both pop and top methods should return the value of first element.
Example
For push(1), pop(), push(2), push(3), top(), pop(), you should return 12 and 2
Challenge
implement it by two stacks, do not use any other data structure and push, pop and top should be O(1) by AVERAGE
用两个stack来实现queue 第一个stack正向装入数字 然后pop出来 push到第二个stack中
每次判定stack2是否为empty(这样做可以防止后来加入的数字push到stack2中 这样顺序就乱了 所以要等stack2 是空的时候才再次网stack2里面push数字) 如果为empty继续push入stack1 pop出来的数 

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

    public Solution() {
       stack1 = new Stack<Integer>();
       stack2 = new Stack<Integer>();
    }
    public void push(int element) {
        stack1.push(element);
    }

    public int pop() {
        if (stack2.empty()) {
            while (!stack1.empty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }

    public int top() {
        if (stack2.empty()) {
            while (!stack1.empty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.peek();
    }
}

2015年5月17日星期日

Topological Sorting Show result

Given an directed graph, a topological order of the graph nodes is defined as follow:
  • For each directed edge A-->B in graph, A must before B in the order list.
  • The first node in the order can be any node in the graph with no nodes direct to it.
Find any topological order for the given graph.
Example
For graph as follow: 
The topological order can be:
[0, 1, 2, 3, 4, 5]
or
[0, 2, 3, 1, 5, 4]
or
....
首先明白两个概念: 入度 表示有向图里有多少箭头指向该点  出度 : 有多少箭头指出该点
解题: 先把入度为0的点加入result中, 然后裁掉该点--->该点所有邻结点的入度都-1; 然后再找出入度为0的点 加入result......


/**
 * Definition for Directed graph.
 * class DirectedGraphNode {
 *     int label;
 *     ArrayList<DirectedGraphNode> neighbors;
 *     DirectedGraphNode(int x) { label = x; neighbors = new ArrayList<DirectedGraphNode>(); }
 * };
 */
public class Solution {
    /**
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */    
    public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
        ArrayList<DirectedGraphNode> result = new ArrayList<DirectedGraphNode>();
        HashMap<DirectedGraphNode, Integer> map = new HashMap();
        for (DirectedGraphNode node : graph) {//找到所有点的入度值存入hash
            for (DirectedGraphNode neigh : node.neighbors) {
                if (map.containsKey(neigh)) {
                    map.put(neigh, map.get(neigh) + 1);
                } else {
                    map.put(neigh, 1);
                }
            }
        }
        Queue<DirectedGraphNode> queue = new LinkedList<DirectedGraphNode>();// 找到入度为0的点node存入queue
        for (DirectedGraphNode node : graph) {
            if (!map.containsKey(node)) {
                queue.offer(node);
                result.add(node);
            }
        }
        while (!queue.isEmpty()) {//把node的邻接点入度都-1, 找到入度为0的接点加入queue 
            DirectedGraphNode node = queue.poll();
            for (DirectedGraphNode n : node.neighbors) {
                map.put(n, map.get(n) - 1);
                if (map.get(n) == 0) {
                    queue.offer(n);
                    result.add(n);
                } 
            }
        }
        return result;
    }
}

2015年5月13日星期三

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]| 
Example
Given [1,4,2,3] and target=1, one of the solutions is [2,3,2,3], the adjustment cost is 2 and it's minimal. Return 2.
Note
You can assume each number in the array is a positive integer and not greater than 100
注意是positive number 所以j的起始值是1不是0 因为这个犯了好几次错....
state: dp[i][v] 表示前i个数, 第i个数调整为v 满足条件, 所需要的最小代价
function:如果i个数时j 那么第i-1个数k是要满足 Math.abs(j - k) < target的
dp[i][v] = Math.min(dp[i-1][k] +  Math.abs(j -A.get(i-1))) //第i个数时j 第i-1个数为k时候使代价最小

如果第i个数是j, 那么第i-1个数k只能在[lowerRange, UpperRange]之间,lowerRange=Math.max(0, j-target), upperRange=Math.min(99, j+target), 这样的话,transfer function可以写成: for (int p=lowerRange; p<= upperRange; p++) {   res[i][j] = Math.min(res[i][j], res[i-1][k] + Math.abs(j-A.get(i-1))); }
initial:dp[0][j]= 0
return: 满足条件的最小代价 Math.min(dp[m][j]) // 改变j的值找到最小的代价

public class Solution {

    public int MinAdjustmentCost(ArrayList A, int target) {
        int m = A.size();
        int[][] dp = new int[m+1][101];
        for (int j = 0; j < 101; j++) {
            dp[0][j] = 0;
        }
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= 100; j++) {
                dp[i][j] = Integer.MAX_VALUE;
                for (int k = 1; k <= 100; k++) {
                    if (Math.abs(j - k) > target) {
                        continue;
                    }
                 
                    dp[i][j] = Math.min(dp[i][j], dp[i-1][k] +  Math.abs(j -A.get(i-1)));
//Math.abs(j -A.get(i-1)))表示第i个数改为j所需代价
                }
            }
        }
        int result = Integer.MAX_VALUE;
        for (int j = 1 ; j <= 100; j++) {
            result = Math.min(result, dp[m][j]);
        }
        return result;
    }
}

k Sum

Given n distinct positive integers, integer k (k <= n) and a number target.
Find k numbers where sum is target. Calculate how many solutions there are?
Example
Given [1,2,3,4], k=2, target=5. There are 2 solutions:
[1,4] and [2,3], return 2.
state:dp[i][j][t] 前i个数取出j个和为t 所以j必须要小于i
function: dp[i][j][t] = dp[i-1][j][t] 如果t >= A中第i个数 dp[i][j][t] += dp[i-1][j-1][t-A[i-1]]
(1)我们可以把当前A[i - 1]这个值包括进来,所以需要加上D[i - 1][j - 1][t - A[i - 1]](前提是t - A[i - 1]要大于0)

(2)我们可以不选择A[i - 1]这个值,这种情况就是D[i - 1][j][t],也就是说直接在前i-1个值里选择一些值加到target.
initial: dp[i][0][0] = 0
return: dp[i][k][target]
public class Solution {

    public int kSum(int A[], int k, int target) {
        int m = A.length;
        int[][][] dp = new int[A.length + 1][k+1][target+1];
        for (int i = 0; i <= m; i++) {
            dp[i][0][0] = 1;
        }
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= k && j <= i; j++) {// j必须要比i小
                for (int n = 1; n <= target; n++) {
                    dp[i][j][n] = dp[i-1][j][n];
                    if (n >= A[i-1]) {// 是大于等于不是大于
                        dp[i][j][n] += dp[i-1][j-1][n- A[i-1]];
                    }
                    
                }
            }
        }
        return dp[m][k][target];
        
    }
}

2015年5月12日星期二

Backpack I & II

Given n items with size A[i], an integer m denotes the size of a backpack. How full you can fill this backpack? 
Example
If we have 4 items with size [2, 3, 5, 7], the backpack size is 11, we can select 2, 3 and 5, so that the max size we can fill this backpack is 10. If the backpack size is 12. we can select [2, 3, 7] so that we can fulfill the backpack.
You function should return the max size we can fill in the given backpack.

n个整数a[1..n],装m的背包
  • state: f[i][j] “前i”个数,取出一些能否组成和为j
  • function: f[i][j] = 如果不取最后第i个数f[i-1][j]  or 如果考虑第i个数 那么首先A[i] < j 成立的话 f[i-1][j - a[i]]
  • intialize: f[X][0] = true; f[0][1..m] = false
  • answer: 能够使得f[n][X]最大的X(0<=X<=m)
public class Solution {
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @return: The maximum size
     */
    public int backPack(int m, int[] A) {
        boolean [][] dp = new boolean[A.length + 1][m+1];
        for (int j = 0; j <= m; j++) {
            dp[0][j] = false;
        }
        for (int i = 0; i <= A.length; i++) {
            dp[i][0] = true;
        }
        for (int i =1; i <= A.length; i++) {
            for (int j = 1; j <= m; j++) {
                dp[i][j] = dp[i - 1][j];//不取第i个数
                if (j >= A[i-1] && dp[i-1][j - A[i-1]]) {//取第i个数 A[i-1]表示第i个数
                    dp[i][j] = true;
                }
            }
        }
        for (int k = m; k >=0; k--) {
            if (dp[A.length][k]) {
                return k;
            }
        }
        return 0;
    }
}

Given n items with size A[i] and value V[i], and a backpack with size m. What's the maximum value can you put into the backpack?
Example
Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. The maximum value is 9.
  • state: f[i][j] “前i”个数,放入大小为j的背包获得的最大value
  • function: f[i][j] = max{f[i-1][j],f[i-1][j-c[i]]+v[i]}         
    • “将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为j的背包中”,价值为f[i-1][j];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为j-c[i]的背包中”,此时能获得的最大价值就是f[i-1][j-c[i]]再加上通过放入第i件物品获得的价值V[i]。
  • intialize: f[X][0] = 0; f[0][1..m] = 0
  • answer: f[A.length][m]
public class Solution {
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A & V: Given n items with size A[i] and value V[i]
     * @return: The maximum value
     */
    public int backPackII(int m, int[] A, int V[]) {
        int[][] dp = new int[A.length + 1][m + 1];
        for (int j = 0; j <= m; j++) {
            dp[0][j] = 0;
        }
        for (int i = 0; i <= A.length; i++) {
            dp[i][0] = 0;
        }
        for (int i = 1; i <= A.length; i++) {
            for (int j = 1; j <= m; j++) {
                if (A[i-1] > j) {
                    dp[i][j] = dp[i-1][j];
                } else {
                    dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-A[i-1]] + V[i-1]);
                }
            }
        }
        return dp[A.length][m];
    }
}


2015年5月6日星期三

Longest Common Substring

Given two strings, find the longest common substring.
Return the length of it.
Example
Given A="ABCD"B="CBCE", return 2.
state: dp[i][j] 表示必须包括i字符和j字符的前i个字符配上前j个字符的LCS长度(前i个字符和前j个字符完全匹配)
function: dp[i][j] 1.如果charAt[i] = charAt[j]: dp[i][j] = dp[i-1][j-1]
                         2. 如果不等于 dp[i][j]= 0
initial: dp[i][0] dp[0][j] 为0
return max
要维护一个max 每次的出来的dp[i][j]和max比较 return最后最大的max
public class Solution {
    /**
     * @param A, B: Two string.
     * @return: the length of the longest common substring.
     */
    public int longestCommonSubstring(String A, String B) {
        if (A == null || B == null) {
            return 0;
        }
        int m = A.length();
        int n = B.length();
        int[][] dp = new int[m+1][n+1];
        int max = 0;
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (A.charAt(i-1) != B.charAt(j-1)) {
                    dp[i][j] = 0;
                } else {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    
                }
                max = Math.max(dp[i][j], max);
            }
        }
        return max;
    }
}

Longest Common Subsequence

Given two strings, find the longest comment subsequence (LCS).
Your code should return the length of LCS.
Example
For "ABCD" and "EDCA", the LCS is "A" (or D or C), return 1
For "ABCD" and "EACB", the LCS is "AC", return 2
state: dp[i][j] 表示前i个字符配上前j个字符的LCS长度(必须包括以i j结尾的字符)
function: dp[i][j] 有两种情况:
               1. charAt(i) = charAt(j) dp[i][j] = dp[i-1][j-1], dp[i][j-1], dp[i-1][j]中最大的一个
               2. charAt(i) != charAt(j) dp[i][j] =dp[i][j-1], dp[i-1][j]中最大的一个 (只有最后一个不同, 可能i字符和j-1相同 或者j和i-1相同)
initial: 二维数组所以dp[i][0] = 0 dp[0][j] = 0
return: dp[m][n]

public class Solution {
    /**
     * @param A, B: Two strings.
     * @return: The length of longest common subsequence of A and B.
     */
    public int longestCommonSubsequence(String A, String B) {
        if (A == null || B == null) {
            return 0;
        }
        int m = A.length();
        int n = B.length();
        int[][] dp = new int[m+1][n+1];
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (A.charAt(i - 1) == B.charAt(j - 1)) {
                    dp[i][j] = Math.max(dp[i-1][j-1] + 1, Math.max(dp[i][j-1], dp[i-1][j]));
                } else {
                    dp[i][j] = Math.max(dp[i][j-1], dp[i-1][j]);
                }
            }
        }
        return dp[m][n];
    }
}

Longest Increasing Subsequence Show result

Given a sequence of integers, find the longest increasing subsequence (LIS).
You code should return the length of the LIS.
Example
For [5, 4, 1, 2, 3], the LIS  is [1, 2, 3], return 3
For [4, 2, 4, 5, 3, 7], the LIS is [4, 4, 5, 7], return 4
state: dp[i]表示前i个数中以第i个为结尾的LIS长度
function: dp[i] = max{dp[j] + 1}--> if (A[j] <= A[i])
initial: dp[0] = 1; dp[i] = 1;//如果不初始化dp[i] 例如数组【5,1】dp[1]就为0了
return max{dp[i]}


public class Solution {
    /**
     * @param nums: The integer array
     * @return: The length of LIS (longest increasing subsequence)
     */
    public int longestIncreasingSubsequence(int[] nums) {
        int n = nums.length; 
        if (nums == null || n == 0) {
            return 0;
        }
        int[] dp = new int[n];
        int max = 0;
        dp[0] = 1;
        for (int i = 1; i < n; i++) {
            dp[i] = 1;
            for (int j = 0; j < i; j++) {
                if (nums[i] >= nums[j]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            max = Math.max(dp[i], max);
        }
        return max;
    }
}

2015年4月26日星期日

Search Range in Binary Search Tree

Given two values k1 and k2 (where k1 < k2) and a root pointer to a Binary Search Tree. Find all the keys of tree in range k1 to k2. i.e. print all x such that k1<=x<=k2 and x is a key of given BST. Return all the keys in ascending order.
Example
For example, if k1 = 10 and k2 = 22, then your function should print 12, 20 and 22.
          20
       /        \
    8           22
  /     \
4       12
1. 如果root.val > k1 递归的找他的左子树
2. 如果root.val 在k1, k2之间 添加root到result
3. 如果root.val < k2 递归找他的右子树
public class Solution {
    /**
     * @param root: The root of the binary search tree.
     * @param k1 and k2: range k1 to k2.
     * @return: Return all keys that k1<=key<=k2 in ascending order.
     */
    public ArrayList<Integer> searchRange(TreeNode root, int k1, int k2) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        helper(root, k1, k2, result);
        return result;
    }
    private void helper(TreeNode root, int k1, int k2, ArrayList<Integer> result){
        if (root == null){
            return;
        }
        if (root.val > k1){
            helper(root.left, k1, k2, result);
        }
        if (root.val >= k1 && root.val <= k2){
            result.add(root.val);
        }
        if (root. val < k2){
            helper(root.right, k1, k2, result);
        }
    }
}

2015年4月22日星期三

Lowest Common Ancestor lintcode

Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes.
The lowest common ancestor is the node with largest depth which is the ancestor of both nodes.
Example
        4
    /     \
  3         7
          /     \
        5         6
For 3 and 5, the LCA is 4.
For 5 and 6, the LCA is 7.
For 6 and 7, the LCA is 7.
这道题还是用分治法, 从最底下往上遍历,当找到一个所给node,向上传递node, 如果没找到就传递null。 上一层的parent会check自己的左右子树是否都有返回值,a.如果都有值那么这个node就是LCA, 向上传递这个node一直到根节点。b. 只有一个子树有值, 那么向上传递这个子树。c.若果左右都没有, 向上传递null
/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
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) {
        if (root == null){
            return null;
        }
        if (root == A || root == B){
            return root;//当找到一中一个node, 向上传递这个node
        }
        TreeNode left = lowestCommonAncestor(root.left, A, B);
        TreeNode right = lowestCommonAncestor(root.right, A, B);
        if (left != null && right != null){//check左右,如果左右分别包含两个node则这个root就是LCA, 向上传递这个node
            return root;
        } else if (left != null){//只有左边有node,向上传递此node
            return left;
        } else if (right != null){
            return right;
        } else{//左右边都没有node 传递null
            return null;
        }
    }
}

2015年4月19日星期日

三部反转法--Recover Rotated Sorted Array

Given a rotated sorted array, recover it to sorted array in-place.
Example
[4, 5, 1, 2, 3] -> [1, 2, 3, 4, 5]
Challenge
In-place, O(1) extra space and O(n) time.
『三步翻转法』,以[4, 5, 1, 2, 3]为例。
  1. 首先找到分割点51
  2. 翻转前半部分4, 55, 4,后半部分1, 2, 3翻转为3, 2, 1。整个数组目前变为[5, 4, 3, 2, 1]
  3. 最后整体翻转即可得[1, 2, 3, 4, 5]
由以上3个步骤可知其核心为『翻转』的in-place实现。使用两个指针,一个指头,一个指尾,使用for循环移位交换即可。
注意:arraylist 里面存取数值要用 arraylist.get()/.set() 

public class Solution {
    /**
     * @param nums: The rotated sorted array
     * @return: The recovered sorted array
     */
    public void recoverRotatedSortedArray(ArrayList<Integer> nums) {
        // write your code
        for (int p =1; p < nums.size(); p++){
            if (nums.get(p - 1) > nums.get(p)){
                reverse(nums, 0, p - 1);
                reverse(nums, p, nums.size() - 1);
                reverse(nums, 0, nums.size() - 1);
                return;
            }
        }
    }

    private void reverse(ArrayList<Integer> nums, int start, int end){
        for (int i = start, j = end; i < j; i++, j--){
            int tem = nums.get(i);
            nums.set(i, nums.get(j));
            nums.set(j, tem);
        }
    }
}



2015年4月14日星期二

Search a 2D Matrix II

Write an efficient algorithm that searches for a value in an m x n matrix, return the occurrence of it.
This matrix has the following properties:
    * Integers in each row are sorted from left to right.
    * Integers in each column are sorted from up to bottom.
    * No duplicate integers in each row or column.
Example
Consider the following matrix:
[
    [1, 3, 5, 7],
    [2, 4, 7, 8],
    [3, 5, 9, 10]
]
Given target = 3, return 2.
Challenge
O(m+n) time and O(1) extra space
对于2d的矩阵 可以从左下角或者右上角沿着对角线找, 

例如从左下角开始找(因为从上到下和从左到右都是递增的), 如果大于target就网上走一格, 如果小于target就往下走一格

public class Solution {
    /**
     * @param matrix: A list of lists of integers
     * @param: A number you want to search in the matrix
     * @return: An integer indicate the occurrence of target in the given matrix
     */
    public int searchMatrix(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0){
            return 0;
        }
        if (matrix[0] == null || matrix[0].length == 0){
            return 0;
        }
        int row = matrix.length - 1;
        int column = matrix[0].length - 1;
        int m = row;
        int n = 0;
        int count = 0;
        while (m >= 0 && m <= row && n >= 0 && n <= column){
            int cur = matrix[m][n];
            if (cur == target){
                count++;
                m--;
            } else if (cur > target){
                m--;
            } else {
                n++;
            }
        }
        return count;
    }
}

First Bad Version

The code base version is an integer and start from 1 to n. One day, someone commit a bad version in the code case, so it caused itself and the following versions are all failed in the unit tests.
You can determine whether a version is bad by the following interface: 

Java:    public VersionControl {        boolean isBadVersion(int version);    }
C++:    class VersionControl {    public:        bool isBadVersion(int version);    };
Python:    class VersionControl:        def isBadVersion(version)

Find the first bad version.
Note
You should call isBadVersion as few as possible. 
Please read the annotation in code area to get the correct way to call isBadVersion in different language. For example, Java is VersionControl.isBadVersion.
Example
Given n=5
Call isBadVersion(3), get false
Call isBadVersion(5), get true
Call isBadVersion(4), get true
return 4 is the first bad version
这道题看着很复杂, 其实就是最简单的binary search 
注意调用isBadVersion时候要用VersionControl.isBadVersion

/**
 * public class VersionControl {
 *     public static boolean isBadVersion(int k);
 * }
 * you can use VersionControl.isBadVersion(k) to judge wether 
 * the kth code version is bad or not.
*/
class Solution {
    /**
     * @param n: An integers.
     * @return: An integer which is the first bad version.
     */
    public int findFirstBadVersion(int n) {
        if (n < 1){
            return -1;
        }
        int start = 1;
        int end = n;
        while (start + 1 < end){
            int mid = start + (end - start) / 2;
            if (VersionControl.isBadVersion(mid)){
                end = mid;
            } else {
                start = mid;
            }
        }
        if (VersionControl.isBadVersion(start)){
            return start;
        } else if (VersionControl.isBadVersion(end)){
            return end;
        } else {
            return -1;
        }
    }
}