【Lintcode】570. Find the Missing Number II

题目地址:

https://www.lintcode.com/problem/find-the-missing-number-ii/description

给定一个正整数 n n n,和一个由数字组成的字符串 s s s。题目保证 s s s存在一种分割,使得每个部分都是 [ 1 , n ] [1,n] [1,n]之间的整数,并且一一对应,但是独缺某一个数。求出这个数。题目保证 n ≤ 30 n\le 30 n30

思路是DFS。从字符串的某个位置开始,尝试切出一个一位数或者两位数,同时用一个boolean数组记录 1 ∼ n 1\sim n 1n中的哪些数已经取过。如果切出的数已经取过则略过,否则将其标记为取过,进入下一层递归。因为题目确保有解,所以当枚举到字符串最后的时候就说明枚举完了,最后只需将未标记为取过的数返回即可。代码如下:

public class Solution {
     
    /**
     * @param n: An integer
     * @param str: a string with number from 1-n in random order and miss one number
     * @return: An integer
     */
    public int findMissing2(int n, String str) {
     
        // write your code here
        boolean[] visited = new boolean[n + 1];
        dfs(str, n, 0, visited);
    
        for (int i = 1; i <= n; i++) {
     
            if (!visited[i]) {
     
                return i;
            }
        }
        
        return -1;
    }
    
    // 从s的下标为pos的地方开始枚举
    private boolean dfs(String s, int n, int pos, boolean[] visited) {
     
    	// 如果pos到了字符串末尾,说明枚举成功,返回true
        if (pos == s.length()) {
     
            return true;
        }
        // 如果开始枚举的数是0,非法,直接返回false
        if (s.charAt(pos) == '0') {
     
            return false;
        }
        // 按照分割数的位数循环,长度只能是1或者2
        for (int i = pos + 1; i <= Math.min(pos + 2, s.length()); i++) {
     
        	// 分割出枚举的数字
            int num = Integer.parseInt(s.substring(pos, i));
            // 如果数字没越界,并且之前没取过,说明可以枚举,标记其为取过后进入下一层递归
            if (0 < num && num <= n && !visited[num]) {
     
                visited[num] = true;
                if (dfs(s, n, i, visited)) {
     
                    return true;
                }
                visited[num] = false;
            }
        }
        
        return false;
    }
}

时间复杂度 O ( 2 l ) O(2^l) O(2l),空间复杂度 O ( n ) O(n) O(n)

你可能感兴趣的:(#,DFS,BFS与图论,字符串,算法,java)