zoukankan      html  css  js  c++  java
  • [LintCode] Find the Missing Number II

    Giving a string with number from 1 to n in random order, but miss 1 number.Find that number.

    You can assume n <= 30

    Example

    Given n = 20, str = 19201234567891011121314151618

    return 17

    Solution 1. DFS 

    Algorithm.

    1. set a 1D boolean array: exist[0........n] to track a number from 1 to n is found or not.

    2. starting from index i, get 2 digits d1 and d2 and do the following in order.

      a. d1 == 0:  return false for invalid split;

      b. d1 != 0 && exist[d1] == false:   get a valid unchecked 1 digit number, set exist[d1] to true and keep searching from index i + 1;

        if the searching from i + 1 returns true, then the current search from i also returns true;

        if it returns false, backtrack exist[d1] to false and proceed to case c.

      c. d <= n && exist[d] == false:  get a valid unchecked 2 digits numbers, set exist[d] to true and keep searching from index i + 2;

          if the searching from i + 2 returns true, then the current search from i also returns true;

       if it returns false, backtrack exist[d] to false and the current search from i returns false as we've already exhausted all possible

          splits without finding a valid split.

    3. After the search from index 0 finishes, the boolean array exist is correctly updated. Scan from index 1 to n and find the index k where exist[k] = false.

    Return k as the missing number. 

     1 public class Solution {
     2     /**
     3      * @param n an integer
     4      * @param str a string with number from 1-n
     5      *            in random order and miss one number
     6      * @return the missing integer
     7      */
     8     public int findMissing2(int n, String str) {
     9         if(n < 1 || str == null){
    10             return 0;
    11         }
    12         boolean[] exist = new boolean[n + 1];
    13         for(int i = 0; i <= n; i++){
    14             exist[i] = false;
    15         }
    16         dfs(str, 0, exist, n);
    17         int val = 1;
    18         for(; val <= n; val++){
    19             if(!exist[val]){
    20                 break;    
    21             }
    22         }
    23         return val;
    24     }
    25     private boolean dfs(String str, int startIdx, boolean[] exist, int maxNum){
    26         if(startIdx >= str.length()){
    27             return true;
    28         }
    29         if(startIdx == str.length() - 1){
    30             int d = str.charAt(startIdx) - '0';
    31             if(d == 0 || exist[d]){
    32                 return false;
    33             }
    34             else{
    35                 exist[d] = true;
    36                 return true;
    37             }
    38         }
    39         int d1 = str.charAt(startIdx) - '0';
    40         int d2 = str.charAt(startIdx + 1) - '0';
    41         int d = d1 * 10 + d2;
    42         //first digit is 0, no valid way to keep searching
    43         if(d1 == 0){
    44             return false;
    45         }
    46         //can get a valid unchecked 1 digit number
    47         if(!exist[d1]){
    48             exist[d1] = true;
    49             if(dfs(str, startIdx + 1, exist, maxNum)){
    50                 return true;
    51             }
    52             exist[d1] = false;
    53         }
    54         //can get a valid unchecked 2 digits number
    55         if(d <= maxNum && !exist[d]){
    56             exist[d] = true;
    57             if(dfs(str, startIdx + 2, exist, maxNum)){
    58                 return true;
    59             }
    60             exist[d] = false;
    61         }            
    62         //can't get either a 1 or 2 digits unchecked number
    63         return false;
    64     }
    65 }

    To correctly get the missing number,  we should check the possiblity of splitting 1 digit before checking splitting 2 digits. Swaping the order of these

    two steps yields incorrect answer. The reason for this is discussed in solution 2.

     Solution 2. DFS

    Solution 1 uses the condition n <= 30, so when deciding whether keep searching, it only checks the next 2 digits.  The disadvantage of this solution 

    is that it does not extend well if n is changed to more than 2 digits. 

    Solution 2 does not use the condition that n can have at most 2 digits, so it is a better in this matter. 

    The algorithm of this solution is as follows.

    1. starting from the current digit, check if it is 0; if it is 0, return as we hit an invalid splitting.

    2. if it is not 0 and <= n, set its checked flag to true and keep searching starting from the next digit.

    3. after done searching, backtrack the current number's checked flag to false. 

    4. include the next digit to the current number; repeat steps 2 and 3 until the current number is > n.

    Important note: 

    To get the correct result, a found boolean flag must be used to make sure a correct answer does not 

    get overwritten by an incorrect answer.

    For example, str = "1234567891011" and n = 12.

    The only right split is {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} and the missing integer is 12;

    Another split of {12, 3, 4, 5, 6, 7, 8, 9, 10, 11} also reaches the end of str since each splitted number is

    in [1, 12].  However, this is not a right split as there are two missing numbers 1 and 2, which contradicts 

    the problem assumption. Any wrong splits that can reach the end of str always has at least two missing

    numbers.

    At some point, if splitting one digit and two digits can both reach the end of str, the one digit split is 

    always the right split and it always set the final answer first.  As a result, this solution uses a boolean flag

    to ensure only the first reach of str's end updates the final answer.

     1 public class Solution {
     2     private boolean found = false;
     3     private int ans = 0;
     4     public int findMissing2(int n, String str) {
     5         boolean[] exist = new boolean[n + 1];
     6         dfs(0, n, str, exist);
     7         return ans;
     8     }
     9     
    10     private void dfs(int startIdx, int maxNum, String s, boolean[] exist) {
    11         if (startIdx >= s.length()) {
    12             if(!found){
    13                 for (int k = 1; k <= maxNum; k++) {
    14                     if (!exist[k]) {
    15                         ans = k;
    16                         break;
    17                     }
    18                 }
    19                 found = true;
    20             }
    21             return;
    22         }
    23         int sum = s.charAt(startIdx) - '0';
    24         if (sum == 0) {
    25             return;
    26         }
    27         while (sum <= maxNum) {
    28             if (!exist[sum]) {
    29                 exist[sum] = true;
    30                 dfs(startIdx + 1, maxNum, s, exist);
    31                 exist[sum] = false;
    32             }
    33             startIdx++;
    34             if (startIdx >= s.length()) {
    35                 break;
    36             }
    37             sum = sum * 10 + (s.charAt(startIdx) - '0');
    38         }
    39     }
    40 }

    Related Problems 

    Decode Ways

    Find the Missing Number

  • 相关阅读:
    ios 写项目的时候遇到的问题及解决方案(1)
    思绪锦集
    iOS学习-----真机测试过程
    StackOverflow程序员推荐的几本书籍
    关于算法学习的重要性
    程序的灵魂-算法
    C++ 之 const 随笔记
    Foundation 框架之——NSString、NSMutableString
    Objective-C之NSString和NSMutableString
    Objective-C之集合对象(NSSet,NSMutableSet,NSIndexSet)
  • 原文地址:https://www.cnblogs.com/lz87/p/7216818.html
Copyright © 2011-2022 走看看