Leetcode刷题系列(十八)CombinationSum && WordLadder

  本篇给出Combination Sum 和Word Ladder 这两种题型。

Combination Sum

  这道题为给出一个数组,使用数组中的数组成和为k的组合。使用前面提到的深度搜索,类似于第一篇提到的方法。

public  ArrayList<ArrayList<Integer>> combinationSum(int[] candidates, int target) {
    ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
    if (candidates == null) {
        return result;
    }

    ArrayList<Integer> path = new ArrayList<Integer>();
    Arrays.sort(candidates);
    helper(candidates, target, path, 0, result);

    return result;
}

 void helper(int[] candidates, int target, ArrayList<Integer> path, int index,
    ArrayList<ArrayList<Integer>> result) {
    if (target == 0) {
        result.add(new ArrayList<Integer>(path));
        return;
    }

    int prev = -1;
    for (int i = index; i < candidates.length; i++) {
        if (candidates[i] > target) {
            break;
        }

        if (prev != -1 && prev == candidates[i]) {
            continue;
        }

        path.add(candidates[i]);
        helper(candidates, target - candidates[i], path, i, result);
        path.remove(path.size() - 1);

        prev = candidates[i];
    }
}

Combination Sum II

  这道题也是求组合,不同点在于数组中的数只能使用一次。因此,在下一次搜索时index+1即可。

private ArrayList<ArrayList<Integer>> results;

public ArrayList<ArrayList<Integer>> combinationSum2(int[] candidates,
        int target) {
    if (candidates.length < 1) {
        return results;
    }

    ArrayList<Integer> path = new ArrayList<Integer>();
    java.util.Arrays.sort(candidates);
    results = new ArrayList<ArrayList<Integer>> ();
    combinationSumHelper(path, candidates, target, 0);

    return results;
}

private void combinationSumHelper(ArrayList<Integer> path, int[] candidates, int sum, int pos) {
    if (sum == 0) {
        results.add(new ArrayList<Integer>(path));
    }

    if (pos >= candidates.length || sum < 0) {
        return;
    }

    int prev = -1;
    for (int i = pos; i < candidates.length; i++) {
        if (candidates[i] != prev) {
            path.add(candidates[i]);
            combinationSumHelper(path, candidates, sum - candidates[i], i + 1);
            prev = candidates[i];
            path.remove(path.size()-1);
        }
    }
}

Word Ladder

  这道题是求一个单词变成另一个单词的最少次数,变化过程中的单词必须是词典中的单词。求最少次数这道题可以使用广度搜索,类似于层序遍历,找到第一个即是最短的。

public int ladderLength(String start, String end, Set<String> dict) {
    if (dict == null) {
        return 0;
    }

    if (start.equals(end)) {
        return 1;
    }

    dict.add(start);
    dict.add(end);

    HashSet<String> hash = new HashSet<String>();
    Queue<String> queue = new LinkedList<String>();
    queue.offer(start);
    hash.add(start);

    int length = 1;
    while(!queue.isEmpty()) {
        length++;
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            String word = queue.poll();
            for (String nextWord: getNextWords(word, dict)) {
                if (hash.contains(nextWord)) {
                    continue;
                }
                if (nextWord.equals(end)) {
                    return length;
                }

                hash.add(nextWord);
                queue.offer(nextWord);
            }
        }
    }
    return 0;
}

private String replace(String s, int index, char c) {
    char[] chars = s.toCharArray();
    chars[index] = c;
    return new String(chars);
}

private ArrayList<String> getNextWords(String word, Set<String> dict) {
    ArrayList<String> nextWords = new ArrayList<String>();
    for (char c = 'a'; c <= 'z'; c++) {
        for (int i = 0; i < word.length(); i++) {
            if (c == word.charAt(i)) {
                continue;
            }
            String nextWord = replace(word, i, c);
            if (dict.contains(nextWord)) {
                nextWords.add(nextWord);
            }
        }
    }
    return nextWords;
}

Word Ladder II

  这道题求最少变换的过程。上面题求最少变换次数使用广搜,那么这道题求过程需要在广搜里面插入深度搜索。

public List<List<String>> findLadders(String start, String end,Set<String> dict) {
    List<List<String>> ladders = new ArrayList<List<String>>();
    Map<String, List<String>> map = new HashMap<String, List<String>>();
    Map<String, Integer> distance = new HashMap<String, Integer>();

    dict.add(start);
    dict.add(end);

    bfs(map, distance, start, end, dict);

    List<String> path = new ArrayList<String>();

    dfs(ladders, path, end, start, distance, map);

    return ladders;
}

void dfs(List<List<String>> ladders, List<String> path, String crt,
        String start, Map<String, Integer> distance,
        Map<String, List<String>> map) {
    path.add(crt);
    if (crt.equals(start)) {
        Collections.reverse(path);
        ladders.add(new ArrayList<String>(path));
        Collections.reverse(path);
    } else {
        for (String next : map.get(crt)) {
            if (distance.containsKey(next) && distance.get(crt) == distance.get(next) + 1) { 
                dfs(ladders, path, next, start, distance, map);
            }
        }           
    }
    path.remove(path.size() - 1);
}

void bfs(Map<String, List<String>> map, Map<String, Integer> distance,
        String start, String end, Set<String> dict) {
    Queue<String> q = new LinkedList<String>();
    q.offer(start);
    distance.put(start, 0);
    for (String s : dict) {
        map.put(s, new ArrayList<String>());
    }

    while (!q.isEmpty()) {
        String crt = q.poll();

        List<String> nextList = expand(crt, dict);
        for (String next : nextList) {
            map.get(next).add(crt);
            if (!distance.containsKey(next)) {
                distance.put(next, distance.get(crt) + 1);
                q.offer(next);
            }
        }
    }
}

List<String> expand(String crt, Set<String> dict) {
    List<String> expansion = new ArrayList<String>();

    for (int i = 0; i < crt.length(); i++) {
        for (char ch = 'a'; ch <= 'z'; ch++) {
            if (ch != crt.charAt(i)) {
                String expanded = crt.substring(0, i) + ch + crt.substring(i + 1);
                if (dict.contains(expanded)) {
                    expansion.add(expanded);
                }
            }
        }
    }

    return expansion;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值