<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    IT技術小屋

    秋風秋雨,皆入我心

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      38 隨筆 :: 1 文章 :: 19 評論 :: 0 Trackbacks

    #

    Distinct Subsequences

    Given a string S and a string T, count the number of distinct sub sequences of T in S.
    A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).
    Here is an example:
    S = "rabbbit", T = "rabbit"
    Return 3.

    這兩個題目很相似,狀態方程是f(i, j) = f(i - 1, j) + S[i] == T[j]? f(i - 1, j - 1) : 0 Where f(i, j) is the number of distinct sub-sequence for T[0:j] in S[0:i].
    數組初始情況是第一列全部是1,代表T字符串是空串,S和自己做匹配。實現代碼如下:
     1 public class DistinctSubsequences {
     2     public int numDistinct(String S, String T) {
     3         int[][] f = new int[S.length() + 1][T.length() + 1];
     4         for (int k = 0; k < S.length(); k++)
     5             f[k][0] = 1;
     6         for (int i = 1; i <= S.length(); i++) {
     7             for (int j = 1; j <= T.length(); j++) {
     8                 if (S.charAt(i - 1) == T.charAt(j - 1)) {
     9                     f[i][j] += f[i - 1][j] + f[i - 1][j - 1];
    10                 } else {
    11                     f[i][j] += f[i - 1][j];
    12                 }
    13             }
    14         }
    15         return f[S.length()][T.length()];
    16     }
    17 }

    Edit Distance
    Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)
    You have the following 3 operations permitted on a word:
    a) Insert a character
    b) Delete a character
    c) Replace a character

     1 public class EditDistance {
     2     public int minDistance(String word1, String word2) {
     3         if (word1.length() == 0 || word2.length() == 0)
     4             return word1.length() == 0 ? word2.length() : word1.length();
     5         int[][] arr = new int[word2.length() + 1][word1.length() + 1];
     6         for (int i = 0; i <= word1.length(); i++) {
     7             arr[0][i] = i;
     8         }
     9         for (int j = 0; j <= word2.length(); j++) {
    10             arr[j][0] = j;
    11         }
    12         for (int i = 0; i < word1.length(); i++) {
    13             for (int j = 0; j < word2.length(); j++) {
    14                 if (word1.charAt(i) == word2.charAt(j)) {
    15                     arr[j + 1][i + 1] = arr[j][i];
    16                 } else {
    17                     int dis = Math.min(arr[j][i + 1], arr[j + 1][i]);
    18                     arr[j + 1][i + 1] = Math.min(arr[j][i], dis) + 1;
    19                 }
    20             }
    21         }
    22         return arr[word2.length()][word1.length()];
    23     }
    24 }
    posted @ 2013-12-31 10:21 Meng Lee 閱讀(244) | 評論 (0)編輯 收藏

    給定一個無序的整數數組,怎么找到第一個大于0,并且不在此數組的整數。比如[1,2,0] 返回 3, [3,4,-1,1] 返回 2。最好能O(1)空間和O(n)時間。
     1 public class Solution {
     2     public int findMissedNumber(int[] nums) {
     3         for (int i = 0; i < nums.length; i++) {
     4             if (nums[i] > 0 && nums[i] - 1 != i && nums[i] != nums[nums[i] - 1]) {
     5                 int tmp = nums[nums[i] - 1];
     6                 nums[nums[i] - 1] = nums[i];
     7                 nums[i] = tmp;
     8                 i--;
     9             }
    10         }
    11         for (int j = 0; j < nums.length; j++) {
    12             if (nums[j] - 1 != j) return j + 1;
    13         }
    14         return nums.length + 1;
    15     }
    16 }
    posted @ 2013-12-28 15:31 Meng Lee 閱讀(147) | 評論 (0)編輯 收藏

    3個字符串a,b,c。判斷c是否是a和b的interleave,也就是c中應該有a,b中所有字 符,并且c中字符順序和a,b中一樣。比如,
    1. a = "ef" b = "gh" c = "egfh" return true
    2. a = "ef" b = "gh" c = "ehgf" return false

    分析:
    這個題目中,并沒有說明a和b中是否有相同的字符,這個直接影響了最終的解法。所以,大家在面試的過程中,要和面試官進行交互,弄清楚之后再動手。a和b中不含有相同字符的情況很簡單,這里略去。下面給出a和b中包含相同字符的動態規劃的解法。

     1 public class Solution {
     2     public boolean isInterleaved(String a, String b, String c) {
     3         int lengthA = a.length();
     4         int lengthB = b.length();
     5         int lengthC = c.length();
     6         if (lengthA + lengthB != lengthC)
     7             return false;
     8         boolean[][] map = new boolean[lengthB + 1][lengthA + 1];
     9         map[0][0] = true;
    10         for (int m = 1; m < lengthA; m++) {
    11             map[0][m] = (a.charAt(m - 1) == c.charAt(m - 1) && map[0][m - 1]);
    12         }
    13         for (int n = 1; n < lengthB; n++) {
    14             map[n][0] = (b.charAt(n - 1) == c.charAt(n - 1) && map[n - 1][0]);
    15         }
    16         for (int i = 1; i <= lengthB; i++) {
    17             for (int j = 1; j <= lengthA; j++) {
    18                 map[i][j] = (c.charAt(i + j - 1) == b.charAt(i - 1) && map[i - 1][j])
    19                         || (c.charAt(i + j - 1) == a.charAt(j - 1) && map[i][j - 1]);
    20             }
    21         }
    22         return map[lengthB][lengthA];
    23     }
    24 }


    posted @ 2013-12-28 14:29 Meng Lee 閱讀(163) | 評論 (0)編輯 收藏

    刪除字符串中的“b”和“ac”,需要滿足如下的條件:
    1. 字符串只能遍歷一次
    2. 不能夠實用額外的空間

    例如:
    1. acbac   ==>  ""
    2. aaac    ==>  aa
    3. ababac  ==>   aa
    4. bbbbd   ==>   d
    5. aaccac  ==> ""

     1 public class Solution {
     2     public String deleteChars(String s) {
     3         StringBuffer sb = new StringBuffer(s);
     4         int fast = 0, slow = -1;
     5         int length = s.length();
     6         while (fast < length) {
     7             if (sb.charAt(fast) == 'b') {
     8                 fast++;
     9             } else if (fast < length - 1 && sb.charAt(fast) == 'a' && sb.charAt(fast + 1) == 'c') {
    10                 fast += 2;
    11             } else {
    12                 sb.setCharAt(++slow, sb.charAt(fast++));
    13                 if (slow > 0 && sb.charAt(slow - 1) == 'a' && sb.charAt(slow) == 'c') {
    14                     slow -= 2;
    15                 }
    16             }
    17         }
    18         return sb.substring(0, slow + 1);
    19     }
    20 }


    posted @ 2013-12-28 11:02 Meng Lee 閱讀(114) | 評論 (0)編輯 收藏

    對一個字符串按照回文進行分割,例如aba|b|bbabb|a|b|aba就是字符串ababbbabbababa的一個回文分割,每一個字串都是一個回文。請找到可以分割的最少的字串數。例如:
    1. ababbbabbababa最少4個字符串,分割三次:a|babbbab|b|ababa
    2. 如果字符串整體是回文,則需要0次分割,最少1個字符串

    分析:
    遞歸方程為:f(i) = MIN(f(j - 1) + 1), map[j][i] == true, 0<=j<i,其中f(i)為以第i個字符結尾的字符串的最小切割次數,map數組用來記錄s[i][j]是否是對稱的。實現代碼如下:
     1 public class Solution {
     2     public int minPalindromePartition(String s) {
     3         int length = s.length();
     4         boolean[][] map = new boolean[length][length];
     5         int[] record = new int[length];
     6         for (int k = 0; k < length; k++) {
     7             record[k] = k;
     8         }
     9         for (int offset = 0; offset < length; offset++) {
    10             for (int i = 0, j = i + offset; i < length - offset; i++, j++) {
    11                 if (i == j || (s.charAt(i) == s.charAt(j) && (j - i == 1 || map[i + 1][j - 1]))) {
    12                     map[i][j] = true;
    13                 }
    14             }
    15         }
    16         for (int i = 1; i < length; i++) {
    17             for (int j = 0; j < i; j++) {
    18                 if (map[j][i]) {
    19                     if (j > 0) {
    20                         record[i] = Math.min(record[i], record[j - 1] + 1);
    21                     } else {
    22                         record[i] = 0;
    23                     }
    24                 }
    25             }
    26         }
    27         return record[length - 1];
    28     }
    29 }
    posted @ 2013-12-27 16:06 Meng Lee 閱讀(141) | 評論 (0)編輯 收藏

    求二叉搜索樹的中序后繼節點

    分析:
    1. 如果目標節點的右子樹不為空,則返回右子樹的最小節點;
    2. 如果目標節點的右子樹為空,則從根節點開始遍歷。
    實現代碼如下:
     1 public class Solution {
     2     public TreeNode inOrderSuccessor(TreeNode root, TreeNode target) {
     3         if (target == nullreturn null;
     4         if (target.right != nullreturn minValue(target.right);
     5         TreeNode succ = null;
     6         while (root != null) {
     7             if (target.val < root.val) {
     8                 succ = root;
     9                 root = root.left;
    10             } else if (target.val > root.val) {
    11                 root = root.right;
    12             } else {
    13                 break;
    14             }
    15         }
    16         return succ;
    17     }
    18 
    19     private TreeNode minValue(TreeNode root) {
    20         while (root.left != null) {
    21             root = root.left;
    22         }
    23         return root;
    24     }
    25 }
    posted @ 2013-12-27 11:06 Meng Lee 閱讀(208) | 評論 (0)編輯 收藏

    最少插入字符

    給定字符串,可以通過插入字符,使其變為回文。求最少插入字符的數量。例如:
    1. ab最少插入1個字符,變為bab
    2. aa最少插入0個字符
    3. abcd最少插入3個字符,dcbabcd

    分析
        這個題目的分析思路,和前面兩期是非常相似的:給出遞歸的解法,發現重復的子問題,改進為動態規劃的解法,這是一個分析的過程,待同學們比較熟悉時候,可以直接給出動態規劃的解決方案,就很好了。
        這個題目,遞歸該如何解呢?給定一個字符串str,長度為n,怎么插入最少的字符,是的字符串變為回文呢?插入最少的字符,就是要盡量利用原來的字符,在原字符串str中,盡量利用更多能夠匹配的字符。怎么對這個問題進行分解呢?考慮str字符串整體:
        1. 如果str[0]==str[n-1],則問題轉變為求str[1,n-2],插入最少字符,得到回文
        2. 如果str[0]!=str[n-1],則需要插入一個字符要么和str[0]相同,要么和str[n-1]相同,
        3. 如果和str[0],則轉變為str[1,n-1],插入最少字符,得到回文
        4. 如果和str[n-1],則轉變為str[0,n-2],插入最少字符,得到回文
        上面的第2種情況中,需要取兩個值最小值。則完成了問題的分解,并且,基本情況也分析完全,則有遞歸式為:
        fmi(str, l, h) = (str[l] == str[h]) ? fmi(str, l+1, h-1) : (min(fmi(str, i+1, h), fmi(str,l, h-1))+1)
        通過上面的式子,有經驗的、熟練的同學,很直接的就能看出來,存在重復的子問題,這就意味著,我們可以講子問題的解緩存使用。如果,沒有直接能夠看出來的同學們,還是可以按照我們之前的方法,把遞歸樹畫出來吧,那樣更加一目了然。
        那么,這個題目該如何用動態規劃的解決呢?如何重復利用子問題的解呢?似乎有些不那么直接。但其實也是于規律可循的。上面的遞歸式,是從字符串的兩 邊,想中間移動遞歸,根據動態規劃解決問題的思想,我們先解決子問題,再重復利用子問題,就是要從內向外解決,大家還記得回文子串判斷的那個題目么,動態 規劃解法的外層循環是子串的長度,這個題目也是類似的。示例代碼如下:
     1 public class Solution {
     2     public int constructPalindrome(String s) {
     3         int length = s.length();
     4         int[][] map = new int[length][length];
     5         for (int offset = 1; offset < length; offset++) {
     6             for (int i = 0, j = offset; i < length - offset; i++, j++) {
     7                 if (i == j - 1) {
     8                     if (s.charAt(i) != s.charAt(j)) {
     9                         map[i][j] = 1;
    10                     }
    11                 } else {
    12                     if (s.charAt(i) != s.charAt(j)) {
    13                         map[i][j] = Math.min(map[i][j - 1], map[i + 1][j]) + 1;
    14                     } else {
    15                         map[i][j] = map[i + 1][j - 1];
    16                     }
    17                 }
    18             }
    19         }
    20         return map[0][length - 1];
    21     }
    22 }
    posted @ 2013-12-26 16:53 Meng Lee 閱讀(172) | 評論 (0)編輯 收藏

    1、給定一組區間,表示為[start,end],請給出方法,將有重疊的區間進行合并。例如:
    給定:[1,3],[2,6],[8,10],[15,18],
    合并:[1,6],[8,10],[15,18].
    分析:題目很直觀,首先把區間遞增排序,然后從頭合并,合并時觀察當前區間的start是否小于或等于前一個區間的end。代碼如下:
     1 public class MergeIntervals {
     2     public class IntervalCmp implements Comparator<Interval> {
     3         @Override
     4         public int compare(Interval i1, Interval i2) {
     5             if (i1.start < i2.start) return -1;
     6             if (i1.start == i2.start && i1.end <= i2.end) return -1;
     7             return 1;
     8         }
     9     }
    10     
    11     public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
    12         ArrayList<Interval> ret = new ArrayList<Interval>();
    13         if (intervals.size() == 0) return ret;
    14         Interval[] arr = new Interval[intervals.size()];
    15         intervals.toArray(arr);
    16         Arrays.sort(arr, new IntervalCmp());
    17         int start = arr[0].start;
    18         int end = arr[0].end;
    19         for (int i = 0; i < arr.length; i++) {
    20             if (arr[i].start <= end) {
    21                 end = Math.max(end, arr[i].end);
    22             } else {
    23                 ret.add(new Interval(start, end));
    24                 start = arr[i].start;
    25                 end = arr[i].end;
    26             }
    27         }
    28         ret.add(new Interval(start, end));
    29         return ret;
    30     }
    31 }
    2、給定的一組區間,將區間中的存在的任意區間的父區間刪除,例如:
    給定:[1,2] [1,3] [1,4] [5,9] [6,8]
    刪除后:[1,2] [6,8]
    分析:此題暴力的解法的復雜度為O(N^2)。受上一題排序的啟發,是否有好一點的思路呢?
    我們可以按照start遞增排序,若start相等,則按照end遞減排序??紤]排序后的第i-1 和第i個區間,由于start是遞增的,所以第i-1個區間的start肯定小于等于第i個區間的start。若第i-1個區間的end大于等于第i個區間的end,則第i-1個區間就成為第i個區間的父區間了。

    按照這個思路,可以試著在排序之后逆向順序處理每一個區間。假設當前處理第i個區間,如前所述,若第i-1個區間的end大于等于第i個區間的end,則第i-1個區間成為第i個區間的父區間,可以保留第i個區間,將第i-1個區間刪除。由于第i-1個區間是第i個區間的父區間,所以第i-1個區間的父區間也是第i個區間的父區間,這種情形下刪掉第i-1個區間,后續不會漏刪第i-1個區間的父區間。若第i-1個區間的end小于第i個區間的end,則可以跳過第i個區間,開始處理第i-1個區間。因為按照這種處理的方法,在處理到第i個區間時,該區間不會是任何區間的父區間(若是父區間已經被如前所述的方法刪除了)。而且,在這種情形下,后續可能出現的第i個區間的父區間會是第i-1個區間的父區間,所以也不會漏掉第i個區間的父區間。所以排序之后逆向處理,只需要O(N)的時間,就可以解決這道問題。整體的時間復雜度為O(nlogn)。
     1 public class Solution {
     2     public class IntervalCmp implements Comparator<Interval> {
     3         @Override
     4         public int compare(Interval i1, Interval i2) {
     5             if (i1.start < i2.start) return -1;
     6             if (i1.start == i2.start && i1.end >= i2.end) return -1;
     7             return 1;
     8         }
     9     }
    10     
    11     public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
    12         ArrayList<Interval> ret = new ArrayList<Interval>();
    13         if (intervals.size() == 0) return ret;
    14         Interval[] arr = new Interval[intervals.size()];
    15         intervals.toArray(arr);
    16         Arrays.sort(arr, new IntervalCmp());
    17         int start = arr[arr.length - 1].start;
    18         int end = arr[arr.length - 1].end;
    19         for (int i = arr.length - 2; i >= 0; i--) {
    20             if (arr[i].end < end) {
    21                 ret.add(new Interval(start, end));
    22                 start = arr[i].start;
    23                 end = arr[i].end;
    24             }
    25         }
    26         ret.add(new Interval(start, end));
    27         return ret;
    28     }
    29 }
    posted @ 2013-12-26 14:47 Meng Lee 閱讀(1796) | 評論 (0)編輯 收藏

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
    For example, given the following triangle
    [
         [2],
        [3,4],
       [6,5,7],
      [4,1,8,3]
    ]
    The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
    Note:
    Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

    本題本來的想法是用遞歸做,實現代碼如下:
     1 public class Solution {
     2     public int minimumTotal(ArrayList<ArrayList<Integer>> triangle) {
     3         int row = triangle.size();
     4         return findMinPath(triangle, 0, 0, row);
     5     }
     6 
     7     private int findMinPath(ArrayList<ArrayList<Integer>> triangle, int row,
     8             int col, int totalRow) {
     9         if (row == totalRow - 1) {
    10             return triangle.get(row).get(col);
    11         } else {
    12             return triangle.get(row).get(col) + Math.min(findMinPath(triangle, row + 1, col, totalRow), findMinPath(triangle, row + 1, col + 1, totalRow));
    13         }
    14     }
    15 }
    提交之后發現超時,于是考慮到可能是遞歸的開銷問題,考慮用迭代解題。實現如下:
     1 public class Triangle {
     2     public int minimumTotal(ArrayList<ArrayList<Integer>> triangle) {
     3         int n = triangle.size() - 1;
     4         int[] path = new int[triangle.size()];
     5         for (int o = 0; o < triangle.get(n).size(); o++) {
     6             path[o] = triangle.get(n).get(o);
     7         }
     8         for (int i = triangle.size() - 2; i >= 0; i--) {
     9             for (int j = 0, t = 0; j < triangle.get(i + 1).size() - 1; j++, t++) {
    10                 path[t] = triangle.get(i).get(t)
    11                         + Math.min(path[j], path[j + 1]);
    12             }
    13         }
    14         return path[0];
    15     }
    16 }
    這個解法的核心是從葉節點自底向上構造解空間。
    posted @ 2013-12-25 11:31 Meng Lee 閱讀(155) | 評論 (0)編輯 收藏

    Subsets的解法是從空集開始,依次取每一個元素與子集中的每個集合做并操作。實現代碼如下:

     1 public class Subsets {
     2     public ArrayList<ArrayList<Integer>> subsets(int[] S) {
     3         Arrays.sort(S);
     4         ArrayList<ArrayList<Integer>> subsets = new ArrayList<ArrayList<Integer>>();
     5         subsets.add(new ArrayList<Integer>());
     6         for (int i = 0; i < S.length; i++) {
     7             int size = subsets.size();
     8             for (int j = 0; j < size; j++) {
     9                 ArrayList<Integer> subset = new ArrayList<Integer>(
    10                         subsets.get(j));
    11                 subset.add(S[i]);
    12                 subsets.add(subset);
    13             }
    14         }
    15         return subsets;
    16     }
    17 }

    Gray Code的算法是初始時集合中只有{0, 1}兩個元素,此后在每個元素的前面附加一個1。實現代碼如下:

     1 public class GrayCode {
     2     public ArrayList<Integer> grayCode(int n) {
     3         ArrayList<Integer> result = new ArrayList<Integer>();
     4         if (n == 0) {
     5             result.add(0);
     6             return result;
     7         }
     8         ;
     9         result.add(0);
    10         result.add(1);
    11         for (int i = 1; i < n; i++) {
    12             ArrayList<Integer> tmp = new ArrayList<Integer>(result);
    13             Integer a = 1 << i;
    14             for (int k = result.size() - 1; k >= 0; k--) {
    15                 tmp.add(result.get(k) + a);
    16             }
    17             result = tmp;
    18         }
    19         return result;
    20     }
    21 }

    posted @ 2013-12-24 12:06 Meng Lee 閱讀(252) | 評論 (0)編輯 收藏

    僅列出標題
    共4頁: 上一頁 1 2 3 4 下一頁 
    主站蜘蛛池模板: 国产精品亚洲一区二区麻豆| 免费**毛片在线播放直播| 亚洲乱色伦图片区小说| 久久久久高潮毛片免费全部播放 | 亚洲 无码 在线 专区| 国产成人精品日本亚洲直接| 美女视频黄免费亚洲| 亚洲不卡影院午夜在线观看| 免费毛片在线看片免费丝瓜视频 | 久久久无码精品亚洲日韩蜜臀浪潮| 久久精品成人免费国产片小草| 一级毛片**不卡免费播| 久久精品国产亚洲av四虎| 99久久免费精品高清特色大片| 国产免费看插插插视频| 亚洲精品免费在线视频| 在线观看H网址免费入口| 亚洲最大av资源站无码av网址| 好男人视频在线观看免费看片| 在线亚洲精品视频| 亚洲毛片免费观看| 国产av天堂亚洲国产av天堂| 亚洲人成人伊人成综合网无码| 国产福利免费观看| 国产免费A∨在线播放| 亚洲欧洲在线观看| 日韩av无码成人无码免费| 18禁亚洲深夜福利人口| 欧洲一级毛片免费| 久久亚洲成a人片| 在线免费视频你懂的| 666精品国产精品亚洲 | 精品女同一区二区三区免费站| 亚洲一卡一卡二新区无人区| 亚洲精品第一国产综合境外资源| 亚洲中文字幕无码久久| 亚洲精品偷拍视频免费观看 | 国产裸体美女永久免费无遮挡| 精品亚洲成a人片在线观看少妇| 成人免费看黄20分钟| 青青操视频在线免费观看|