---------------------------------------------------------------

本文使用方法:所有题目,只需要把标题输入lintcode就能找到。主要是简单的剖析思路以及不能bug-free的具体细节原因。

----------------------------------------------------------------

-------------------------------------------

第九周:图和搜索。

-------------------------------------------

1,-------Clone Graph(克隆图)

(1)答案和思路:首先用list来记录有哪些图,然后对于每一个节点都要新建。用map来做新旧节点的一一对应,以便于后面的建立邻结点。

/**
 * Definition for undirected graph.
 * class UndirectedGraphNode {
 *     int label;
 *     ArrayList<UndirectedGraphNode> neighbors;
 *     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
 * };
 */
public class Solution {
    /**
     * @param node: A undirected graph node
     * @return: A undirected graph node
     */
    public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
        if (node == null) {
            return null;
        }
        ArrayList<UndirectedGraphNode> nodes = new ArrayList();
        nodes.add(node);
        Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap();
        map.put(node, new UndirectedGraphNode(node.label));
        int index = 0;
        while (index < nodes.size()) {
            UndirectedGraphNode curNode = nodes.get(index++);
            for (int i = 0; i < curNode.neighbors.size(); i++) {
                if (!nodes.contains(curNode.neighbors.get(i))) {
                    nodes.add(curNode.neighbors.get(i));
                    map.put(curNode.neighbors.get(i), new UndirectedGraphNode(curNode.neighbors.get(i).label));
                }
            }
        }
        for (int i = 0; i < nodes.size(); i++) {
            UndirectedGraphNode curNode = nodes.get(i);
            for (int j = 0; j < curNode.neighbors.size(); j++) {
                map.get(curNode).neighbors.add(map.get(curNode.neighbors.get(j)));
            }
        }
        return map.get(node);
    }
}
View Code

(2)一刷没有AC:思路没有处理好。

(2)二刷bug-free

 2,-----------Toplogical Sorting(拓扑排序) 

(1)答案和思路:首先,利用map来记录入度。并且把没进去map的那些点先加入结果,因为他们入度为0.为了方便遍历,用queue来辅助遍历。

/**
 * Definition for Directed graph.
 * class DirectedGraphNode {
 *     int label;
 *     ArrayList<DirectedGraphNode> neighbors;
 *     DirectedGraphNode(int x) { label = x; neighbors = new ArrayList<DirectedGraphNode>(); }
 * };
 */
public class Solution {
    /**
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */
     public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
        ArrayList<DirectedGraphNode> result = new ArrayList();
        if (graph == null || graph.size() == 0) {
            return result;
        }
        HashMap<DirectedGraphNode, Integer> map = new HashMap();
        //map 用来记录那些成为了别人邻居的点作为多少个邻居,也就是他的入度是多少。
        for (DirectedGraphNode g : graph) {
            for (DirectedGraphNode n : g.neighbors) {
                if (map.containsKey(n)) {
                    map.put(n, map.get(n) + 1);
                } else {
                    map.put(n, 1);
                }
            }
        }
        Queue<DirectedGraphNode> queue = new LinkedList();
        for (DirectedGraphNode g : graph) {
            if (!map.containsKey(g)) {
                //不在map里面,说明他的度为0
                result.add(g);
                queue.add(g);
            }
        }
        while (!queue.isEmpty()) {
            DirectedGraphNode node = queue.poll();
            for (DirectedGraphNode n : node.neighbors) {
                map.put(n, map.get(n) - 1);
                if (map.get(n) == 0) {
                    result.add(n);
                    queue.add(n);
                }
            }
        }
        return result;
    }
}
View Code

(2)一刷没过。

3,------permutation(全排列)

(1)答案和思路:就是没一个数字加进去之前,他可以放在已经有的地方的n+1个位置。不断地循环就可以了。

class Solution {
    /**
     * @param nums: A list of integers.
     * @return: A list of permutations.
     */
    public static ArrayList<ArrayList<Integer>> permute(ArrayList<Integer> nums)  {
        ArrayList<ArrayList<Integer>> res = new ArrayList();
        if (nums == null || nums.size() == 0) {
            return res;
        }
        ArrayList<Integer> list1 = new ArrayList();
        list1.add(nums.get(0));
        res.add(list1);
        for (int i = 1; i < nums.size(); i++){
            ArrayList<ArrayList<Integer>> res2 = new ArrayList();
            for (ArrayList<Integer> tmp : res) {
                for (int j = 0; j <= tmp.size(); j++) {
                    ArrayList<Integer> list2 = new ArrayList(tmp);
                    list2.add(j, nums.get(i));
                    res2.add(list2);
                }
            }
            res = new ArrayList(res2);
        }
        return res;
    }
}
View Code

(2)注意细节问题。

(3)二刷bug-free; 

4,---------permutationII(全排列)

(1)答案和思路:跟上一题的区别就只需要再加入结果之前判断一下是否已经有了。

class Solution {
    /**
     * @param nums: A list of integers.
     * @return: A list of unique permutations.
     */
    public static ArrayList<ArrayList<Integer>> permuteUnique(ArrayList<Integer> nums) {
        // write your code here
        HashSet<ArrayList<Integer>> res = new HashSet();
        ArrayList<ArrayList<Integer>> ans = new ArrayList();
        if (nums == null || nums.size() == 0) {
            return ans;
        }
        ArrayList<Integer> list1 = new ArrayList();
        list1.add(nums.get(0));
        res.add(list1);
        for (int i = 1; i < nums.size(); i++){
            HashSet<ArrayList<Integer>> res2 = new HashSet();
            for (ArrayList<Integer> tmp : res) {
                for (int j = 0; j <= tmp.size(); j++) {
                    ArrayList<Integer> list2 = new ArrayList(tmp);
                    list2.add(j, nums.get(i));
                    res2.add(list2);
                }
            }
            res = new HashSet(res2);
        }
        for (ArrayList list : res){
            ArrayList<Integer> list3 = new ArrayList(list);
            ans.add(list3);
        }
        return ans;
    }
}
View Code

 (2)一刷bug-free;

 5,----------N Queens (n皇后问题)

(1)答案和思路:首先,就是一场不断尝试放置的过程,那么需要一个函数来判断是否能够放(不能放的条件:这一列已经放了,他不能和上面的行构成斜对角线(当行差值==列差值的时候,就是在对角线上))。技巧:columns[i] = j来记录每一行的Q放在哪里。i行放在j列。    第二步就是进行放置:放置对于第一行来说,能放N个位置,所以,for循环。放好了第一个,利用递归,开始放第二。不断的判断是否可行,直到放置行数达到N。那么就是一次合法的放置,存进list里面。

import java.util.ArrayList;


public class Solution {
    public static void main(String[] args) {
        System.out.println(solveNQueens(4));
    }
    public static ArrayList<ArrayList<String>> solveNQueens(int n) {
        ArrayList<ArrayList<String>> result = new ArrayList();
        int[] columns = new int[n];
        for (int i = 0; i < n; i++) {
            columns[i] = -1;
        }
        ArrayList<int[]> results = new ArrayList();
        placeNQueens(0, columns, results, n);
        for (int[] r : results) {
            ArrayList<String> list = new ArrayList();
            
            for (int i = 0; i < r.length; i++) {
                char[] c = new char[n];
                for (int j = 0; j < n; j++) {
                    c[j] = '.';
                }
                c[r[i]] = 'Q';
                list.add(new String(c));
            }
            result.add(new ArrayList(list));
        }
        
        return result;
    }
    private static void placeNQueens(int row, int[] columns, ArrayList<int[]> results, int n) {
        if (row == n) {
            results.add(columns.clone());
        } else {
            for (int col = 0; col < n; col++) {
                if (checkValid(columns, row, col)) {
                    columns[row] = col;
                    placeNQueens(row + 1, columns, results, n);
                }
            }
        }
    }
    // columns[i] = j 表示第i行第j列放皇后
    private static boolean checkValid(int[] columns, int row, int column) {
        // 看一下跟已有的行的哪些列冲突了
        // i 到 row 行之间这些行已经存了东西了。columns[i]能得到存了哪些列
        for (int i = 0; i < row; i++) {
            int hasColumn = columns[i];
            if (hasColumn == column) {
                return false;
            }
            if (row - i == Math.abs(column - hasColumn)) { 
            // 如果行之间的差值等于列之间的差值,那么在同一个对角线
                return false;
            }
        }
        return true;
    }
    
}
View Code

(2)一刷没过。完全没想到怎么判断。

 6,--------Palindrome Partition I(回文区分)

(1)答案和思路:首先,拿到0到第i个字符,如果他是回文,那么存下来,然后从他到结尾,这一个字符串,也来进行0,到1,。。,i的判断。

基本思路就是从0-i是否是回文,是的话,接着处理i到结束的字符串递归:在后面的字符串里继续考虑:第一个到新的i是否是回文。如果一直这样处理,直到最后的str为空了,那么说明找到一组完整的了,因为只有是回文才会进入递归。这里就是递归结束之后,要remove掉list的最后一个,这是因为:假如,0-i是,但是后来一直处理结束了都不是,那么这就不是一组合格的,那么递归结束,这个值必须出局。想法如果全部都是,那么一层一层往外走,也需要list一个一个删除。

import java.util.ArrayList;
import java.util.List;

public class Solution {
    public static void main(String[] args) {
        System.out.println(partition("aaa"));
    }
    public static List<List<String>>  partition(String s) {
        List<List<String>> result = new ArrayList();
        if (null == s || s.length() == 0) {
            return result;
        }
        List<String> list = new ArrayList();
        calResult(result, list, s);
        return result;
    }
    
    public static void calResult(List<List<String>> result, List<String> list, String str) {
        if (str == null || str.length() == 0) {
//            ERROR : result.add(list);
            result.add(new ArrayList(list));
        }
        for (int i = 1; i <= str.length(); i++) {
            String subStr = str.substring(0, i);
            if (isPalindrome(subStr)) {
                list.add(subStr);
                calResult(result, list, str.substring(i));
                list.remove(list.size() - 1);
            }
        }
    }
    
    public static boolean isPalindrome(String s) {
        if (null == s || s.length() == 0) {
            return false;
        }
        int i = 0;
        int j = s.length() - 1;
        while (i < j) {
            if (s.charAt(i) != s.charAt(j)) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }
}
View Code

(2)一刷没过。

(3)二刷错在:list存入是需要new的。不然一直是原来的list,是错的。

 

7,----------combination sum(求一个集合里面能够组合成目标值的组合种类)

(1)答案和思路:这里依然是利用递归来做。不同的就是,从i开始,在sum没有大于target之前,再次递归的元素下标是不变的。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {
    public static void main(String[] args) {
        int[] a = {7, 1, 2, 5, 1, 6, 10};
        System.out.println(combinationSum(a, 8));
    }
    public static List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList();
        if (candidates == null || candidates.length == 0) {
            return result;
        }
        List<Integer> list = new ArrayList();
        Arrays.sort(candidates);
        calResult(candidates,target, 0, 0, result, list);

        return result;
    }

    public static void calResult(int[] candidates, int target, int sum, int index, List<List<Integer>> result, List<Integer> list) {
        if (sum > target) {
            return;
        }
        if (sum == target) {
            if (!result.contains(list)) {
                result.add(new ArrayList(list));
            }
        }
        for (int i = index; i < candidates.length; i++) {
            sum += candidates[i];
            list.add(candidates[i]);
            calResult(candidates, target, sum, i, result, list);
            sum -= candidates[i];
            list.remove(list.size() - 1);
        }
    }
}
View Code

(2)一刷思路没弄对。

(3)二刷:忘记了sort数组。因为结果要求有序。

8, --------------combination sum II(和I的区别是,每个元素只能用一次,那么就是每一次递归都是i+1的走)

答案:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {
//     public static void main(String[] args) {
//         int[] a = {7, 1, 2, 5, 1, 6, 10};
//         System.out.println(combinationSum(a, 8));
//     }
    public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList();
        if (candidates == null || candidates.length == 0) {
            return result;
        }
        List<Integer> list = new ArrayList();
        Arrays.sort(candidates);
        calResult(candidates,target, 0, 0, result, list);

        return result;
    }

    public static void calResult(int[] candidates, int target, int sum, int index, List<List<Integer>> result, List<Integer> list) {
        if (sum > target) {
            return;
        }
        if (sum == target) {
            if (!result.contains(list)) {
                result.add(new ArrayList(list));
            }
        }
        for (int i = index; i < candidates.length; i++) {
            sum += candidates[i];
            list.add(candidates[i]);
            calResult(candidates, target, sum, i + 1, result, list);
            sum -= candidates[i];
            list.remove(list.size() - 1);
        }
    }
}
View Code

(1)一刷bug-free

 

9,--------------word ladder

(1)答案和思路:利用队列来进行记录每一次可以有多少个next直到遇到了end。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public class Solution {
    
    public static int ladderLength(String start, String end, Set<String> dict) {
        if (dict == null) {
            return 0;
        }
        dict.add(start);
        dict.add(end);
        HashSet<String> hash = new HashSet();
        Queue<String> queue = new LinkedList();
        queue.add(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();
                dict.remove(word);
                for (String nextWord : getNextWords(word, dict)) {
                    if (hash.contains(nextWord)) {
                        continue;
                    }
                    if (nextWord.equals(end)) {
                        return length;
                    }
                    hash.add(nextWord);
                    queue.add(nextWord);
                }
            
                
            }
        }
        return 0;
    }
    private static String replace(String s, int index, char c) {
        char[] chars = s.toCharArray();
        chars[index] = c;
        return new String(chars);
    }
    private static ArrayList<String> getNextWords(String word, Set<String> dict) {
        ArrayList<String> nextWords = new ArrayList();
        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;
    }
}
View Code

相关文章:

  • 2021-12-01
  • 2022-12-23
  • 2021-12-29
  • 2021-05-16
  • 2022-02-05
  • 2022-12-23
  • 2021-06-06
猜你喜欢
  • 2021-11-04
  • 2022-01-16
  • 2021-08-08
  • 2022-12-23
  • 2022-02-14
  • 2021-10-24
  • 2021-09-16
相关资源
相似解决方案