枚举法

DFS + Backtracking 的搜索量很大。如果每次 DFS 之前都要进行条件检查的话,优化条件函数可以显著提升程序速度。如 N-Queens 和 Palindrome Partitioning 还有 Sudoku Solver


Generate Parentheses, 限制条件是右括号的数量只能小于等于左括号的数量

    public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<String>();
        if (n <= 0) {
            return result;
        }

        StringBuffer sb = new StringBuffer();
        dfs(result, sb, 0, 0, n);
        return result;
    }

    private void dfs(List<String> result, StringBuffer sb, int left, int right, int n) {
        if (left == n && right == n) {
            result.add(sb.toString());
            return;
        }

        if (left < n) {
            sb.append("(");
            dfs(result, sb, left + 1, right, n);
            sb.setLength(sb.length() - 1);
        }

        if (right < left && right < n) {
            sb.append(")");
            dfs(result, sb, left, right + 1, n);
            sb.setLength(sb.length() - 1);
        }
    }
}

Restore IP Addresses, 限制条件是对于大于一位的substring, 第一位不能’0', 另外数字不能大于255.

    public List<String> restoreIpAddresses(String s) {
        List<String> result = new ArrayList<String>();
        if (s == null || s.length() < 4 || s.length() > 12) {
            return result;
        }

        StringBuffer sb = new StringBuffer();
        dfs(result, sb, s, 0);
        return result;
    }

    private void dfs(List<String> result, StringBuffer sb, String s, int pos) {
        if (pos == s.length()) {
            if (sb.length() == s.length() + 3) {
                result.add(sb.toString());
            }
            return;
        }

        for (int i = pos; i < s.length(); i++) {
            if (i != pos && s.charAt(pos) == '0') {
                return;
            }
            int num = Integer.parseInt(s.substring(pos, i + 1));
            if (num > 255) {
                return;
            }

            int length = sb.length();

            if (length == 0) {
                sb.append(num);
            } else {
                sb.append(".").append(num);
            }

            dfs(result, sb, s, i + 1);
            sb.setLength(length);
        }
    }
}

Palindrome Partitioning,在做dfs之前,用一个二维boolean矩阵去存从index i到index j这段s.substring(i, j + 1)是不是一个palindrome。

    public List<List<String>> partition(String s) {
        List<List<String>> result = new ArrayList<List<String>>();
        if (s == null) {
            return result;
        } 

        boolean[][] isPalindrome = getIsPalindrome(s);

        List<String> list = new ArrayList<String>();
        dfs(result, list, s, isPalindrome, 0);
        return result;
    }

    private void dfs(List<List<String>> result, List<String> list, String s, boolean[][] isPalindrome, int pos) {
        if (pos == s.length()) {
            result.add(new ArrayList<String>(list));
            return;
        }

        for (int i = pos; i < s.length(); i++) {
            if (!isPalindrome[pos][i]) {
                continue;
            }
            list.add(s.substring(pos, i + 1));
            dfs(result, list, s, isPalindrome, i + 1);
            list.remove(list.size() - 1);
        }
    }

    private boolean[][] getIsPalindrome(String s) {
        if (s == null || s.length() == 0) {
            return null;
        }

        int m = s.length();
        boolean[][] isPalindrome = new boolean[m][m];

        for (int i = 0; i < m; i++) {
            isPalindrome[i][i] = true;
        }

        for (int i = 0; i < m - 1; i++) {
            isPalindrome[i][i + 1] = s.charAt(i) == s.charAt(i + 1);
        }

        for (int distance = 2; distance < s.length(); distance++) {
            for (int i = 0; i + distance < s.length(); i++) {
                isPalindrome[i][i + distance] = isPalindrome[i + 1][i + distance - 1] && s.charAt(i) == s.charAt(i + distance);
            }
        }

        return isPalindrome;
    }
}

Letter Combinations of a Phone Number,先建存一下每个数字对应的字母

    public List<String> letterCombinations(String digits) {
        List<String> result = new ArrayList<String>();
        if (digits == null || digits.length() == 0) {
            return result;
        }

        Map<Integer, char[]> map = new HashMap<Integer, char[]>();
        map.put(0, new char[0]);
        map.put(1, new char[0]);
        map.put(2, new char[]{'a', 'b', 'c'});
        map.put(3, new char[]{'d', 'e', 'f'});
        map.put(4, new char[]{'g', 'h', 'i'});
        map.put(5, new char[]{'j', 'k', 'l'});
        map.put(6, new char[]{'m', 'n', 'o'});
        map.put(7, new char[]{'p', 'q', 'r', 's'});
        map.put(8, new char[]{'t', 'u', 'v'});
        map.put(9, new char[]{'w', 'x', 'y', 'z'});

        dfs(result, new StringBuffer(), digits, map, 0);
        return result;
    }

    private void dfs(List<String> result, StringBuffer sb, String digits, Map<Integer, char[]> map, int pos) {
        if (sb.length() == digits.length()) {
            result.add(sb.toString());
            return;
        }

        for (int i = pos; i < digits.length(); i++) {
            int num = digits.charAt(i) - '0';
            if (num < 2 || num > 9) {
                continue;
            }

            for (char c: map.get(num)) {
                sb.append(c);
                dfs(result, sb, digits, map, i + 1);
                sb.setLength(sb.length() - 1);
            }
        }
    }
}

Binary Watch

    public List<String> readBinaryWatch(int num) {
        List<String> result = new ArrayList<String>();
        int[] hours = {1, 2, 4, 8};
        int[] minutes = {1, 2, 4, 8, 16, 32};

        for (int i = 0; i <= num; i++) {
            List<Integer> hour_list = new ArrayList<Integer>();
            List<Integer> minute_list = new ArrayList<Integer>();

            dfs(hour_list, hours, i, 0, 0);
            dfs(minute_list, minutes, num - i, 0, 0);

            for (int h: hour_list) {
                for (int m: minute_list) {
                    String minute = m < 10 ? "0" + m : "" + m;
                    String time = h + ":" + minute;
                    result.add(time);
                }
            }
        }

        return result;
    }

    private void dfs(List<Integer> list, int[] array, int n, int pos, int sum) {
        if (n == 0) {
            if (array.length == 4 && sum <= 11) {
                list.add(sum);
            }
            if (array.length == 6 && sum <= 59) {
                list.add(sum);
            }
            return;
        }

        for (int i = pos; i < array.length; i++) {
            dfs(list, array, n - 1, i + 1, sum + array[i]);
        }
    }
}

解二:bit, 待做

results matching ""

    No results matching ""