1. 程式人生 > >lintcode階梯訓練第四關(九章)

lintcode階梯訓練第四關(九章)

7、二叉樹的序列化和反序列化

  • 題目
    設計一個演算法,並編寫程式碼來序列化和反序列化二叉樹。將樹寫入一個檔案被稱為“序列化”,讀取檔案後重建同樣的二叉樹被稱為“反序列化”。
    如何反序列化或序列化二叉樹是沒有限制的,你只需要確保可以將二叉樹序列化為一個字串,並且可以將字串反序列化為原來的樹結構。
    【需要再來一遍~】
    注意事項
    There is no limit of how you deserialize or serialize a binary tree, LintCode will take your output of serialize as the input of deserialize, it won’t check the result of serialize.
    樣例


    給出一個測試資料樣例, 二叉樹{3,9,20,#,#,15,7},表示如下的樹結構:
    3
    / \
    9 20
    .. / \
    . 15 7
    我們的資料是進行BFS遍歷得到的。當你測試結果wrong answer時,你可以作為輸入除錯你的程式碼。
    你可以採用其他的方法進行序列化和反序列化。

  • 程式碼

class Solution {
    public String serialize(TreeNode root) {
        if (root == null) {
            return "{}";
        }
        ArrayList<TreeNode> list
= new ArrayList<>(); list.add(root); for (int i = 0; i < list.size(); i++) { TreeNode node = list.get(i); if (node == null) { continue; } list.add(node.left); list.add(node.right); } while
(list.get(list.size() - 1) == null) { list.remove(list.size() - 1); } StringBuilder sb = new StringBuilder(); sb.append("{"); sb.append(list.get(0).val); for (int i = 1; i < list.size(); i++) { if (list.get(i) == null) { sb.append(",#"); } else { sb.append(","); sb.append(list.get(i).val); } } sb.append("}"); return sb.toString(); } public TreeNode deserialize(String data) { if (data.equals("{}")) { return null; } String[] vals = data.substring(1, data.length() - 1).split(","); TreeNode head = new TreeNode(Integer.parseInt(vals[0])); boolean isLeft = true; int index = 0; ArrayList<TreeNode> list = new ArrayList<>(); list.add(head); for (int i = 1; i < vals.length; i++) { if (!vals[i].equals("#")) { TreeNode node = new TreeNode(Integer.parseInt(vals[i])); if (isLeft) { list.get(index).left = node; } else { list.get(index).right = node; } list.add(node); } if (!isLeft) { index++; } isLeft = !isLeft; } return head; } }

433、島嶼的個數

  • 題目
    給一個01矩陣,求不同的島嶼的個數。
    0代表海,1代表島,如果兩個1相鄰,那麼這兩個1屬於同一個島。我們只考慮上下左右為相鄰。
    樣例
    在矩陣:
    [
    [1, 1, 0, 0, 0],
    [0, 1, 0, 0, 1],
    [0, 0, 0, 1, 1],
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1]
    ]
    中有 3 個島.

  • 程式碼

class Point {
    int x;
    int y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
public class Solution {
    public int numIslands(boolean[][] grid) {
        if (grid == null || grid.length == 0) {
            return 0;
        }
        if (grid[0] == null || grid[0].length == 0) {
            return 0;
        }
        int n = grid.length;
        int m = grid[0].length;
        int count = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j]) {
                    bfsHelper(grid, i, j);
                    count++;
                }
            }
        }
        return count;
    }
    private void bfsHelper(boolean[][] grid, int x, int y) {
        Queue<Point> q = new LinkedList<>();
        q.offer(new Point(x, y));
        grid[x][y] = false;
        while (!q.isEmpty()) {
            Point node = q.poll();
            int[] deltaX = {-1, 0, 0, 1};
            int[] deltaY = {0, -1, 1, 0};
            for (int i = 0; i < 4; i++) {
                Point newNode = new Point(node.x + deltaX[i],
                                          node.y + deltaY[i]);
                if (!isValid(grid, newNode)) {
                    continue;
                }
                if (grid[newNode.x][newNode.y]) {
                    q.offer(newNode);
                    grid[newNode.x][newNode.y] = false;
                }
            }
        }
    }
    private boolean isValid(boolean[][] grid, Point newNode) {
        int n = grid.length;
        int m = grid[0].length;
        return newNode.x >= 0 && newNode.x < n && newNode.y >= 0 && newNode.y < m;
    }
}

69、二叉樹的層次遍歷

  • 題目
    給出一棵二叉樹,返回其節點值的層次遍歷(逐層從左往右訪問)
    樣例
    給一棵二叉樹 {3,9,20,#,#,15,7} :
    3
    / \
    9 20
    … / \
    . 15 7
    返回他的分層遍歷結果:
    [
    [3],
    [9,20],
    [15,7]
    ]

  • 程式碼

public class Solution {
    public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
        ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>();
        if (root == null) {
            return results;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        while (!q.isEmpty()) {
            ArrayList<Integer> list = new ArrayList<>();
            int size = q.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = q.poll();
                list.add(node.val);
                if (node.left != null) {
                    q.offer(node.left);
                }
                if (node.right != null) {
                    q.offer(node.right);
                }
            }
            results.add(list);
        }
        return results;
    }
}

70、二叉樹的層次遍歷 II

  • 題目
    給出一棵二叉樹,返回其節點值從底向上的層次序遍歷(按從葉節點所在層到根節點所在的層遍歷,然後逐層從左往右遍歷)
    樣例
    給出一棵二叉樹 {3,9,20,#,#,15,7},
    .. 3
    . / \
    9 20
    … / \
    ..15 7
    按照從下往上的層次遍歷為:
    [
    [15,7],
    [9,20],
    [3]
    ]

  • 程式碼

public class Solution {
    public ArrayList<ArrayList<Integer>> levelOrderBottom(TreeNode root) {
        ArrayList<ArrayList<Integer>> results = new ArrayList<>();
        if (root == null) {
            return results;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        while (!q.isEmpty()) {
            ArrayList<Integer> list = new ArrayList<>();
            int size = q.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = q.poll();
                list.add(node.val);
                if (node.left != null) {
                    q.offer(node.left);
                }
                if (node.right != null) {
                    q.offer(node.right);
                }
            }
            results.add(list);
        }
        Collections.reverse(results);
        return results;
    }
}

71、二叉樹的鋸齒形層次遍歷

  • 題目
    給出一棵二叉樹,返回其節點值的鋸齒形層次遍歷(先從左往右,下一層再從右往左,層與層之間交替進行)
    樣例
    給出一棵二叉樹 {3,9,20,#,#,15,7},
    .. 3
    . / \
    9 20
    .. / \
    .15 7
    返回其鋸齒形的層次遍歷為:
    [
    [3],
    [20,9],
    [15,7]
    ]

  • 程式碼

public class Solution {
    public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
        ArrayList results = new ArrayList<>();
        if (root == null) {
            return results;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        int count = 0;
        while (!q.isEmpty()) {
            ArrayList<Integer> list = new ArrayList<>();
            int size = q.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = q.poll();
                list.add(node.val);
                if (node.left != null) {
                    q.offer(node.left);
                }
                if (node.right != null) {
                    q.offer(node.right);
                }
            }
            if (count % 2 == 1) {
                Collections.reverse(list);
            }
            results.add(list);
            count++;
        }
        return results;
    }
}

242、將二叉樹按照層級轉化為連結串列

  • 題目
    給一棵二叉樹,設計一個演算法為每一層的節點建立一個連結串列。也就是說,如果一棵二叉樹有D層,那麼你需要建立D條連結串列。
    樣例
    對於二叉樹:
    1
    / \
    2 3
    /
    4
    返回3條連結串列:
    [
    1->null,
    2->3->null,
    4->null
    ]

  • 程式碼

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<ListNode> binaryTreeToLists(TreeNode root) {
        List<ListNode> result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        while (!q.isEmpty()) {
            int size = q.size();
            ListNode dummy = new ListNode(0);
            ListNode list = dummy;
            for (int i = 0; i < size; i++) {
                TreeNode node = q.poll();
                list.next = new ListNode(node.val);
                list = list.next;
                if (node.left != null) {
                    q.offer(node.left);
                }
                if (node.right != null) {
                    q.offer(node.right);
                }
            }
            result.add(dummy.next);
        }
        return result;
    }
}

137、克隆圖

  • 題目
    克隆一張無向圖,圖中的每個節點包含一個 label 和一個列表 neighbors。
    資料中如何表示一個無向圖?
    你的程式需要返回一個經過深度拷貝的新圖。這個新圖和原圖具有同樣的結構,並且對新圖的任何改動不會對原圖造成任何影響。
    【再來一遍~】
    樣例
    比如,序列化圖 {0,1,2#1,2#2,2} 共有三個節點, 因此包含兩個個分隔符#。
    第一個節點label為0,存在邊從節點0連結到節點1和節點2
    第二個節點label為1,存在邊從節點1連線到節點2
    第三個節點label為2,存在邊從節點2連線到節點2(本身),從而形成自環。
    我們能看到如下的圖:
    … 1
    .. / \
    ./ … \
    0 — 2
    ….. /.. \
    ….. \ _ /

  • 程式碼

/**
 * Definition for undirected graph.
 * class UndirectedGraphNode {
 *     int label;
 *     ArrayList<UndirectedGraphNode> neighbors;
 *     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
 * };
 */
public class Solution {
    public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
        if (node == null) {
            return node;
        }
        ArrayList<UndirectedGraphNode> nodes = getNode(node);
        Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
        for (UndirectedGraphNode n : nodes) {
            map.put(n, new UndirectedGraphNode(n.label));
        }
        for (UndirectedGraphNode n : nodes) {
            UndirectedGraphNode newNode = map.get(n);
            for (UndirectedGraphNode nei : n.neighbors) {
                newNode.neighbors.add(map.get(nei));
            }
        }
        return map.get(node);
    }
    private ArrayList<UndirectedGraphNode> getNode(UndirectedGraphNode node) {
        Queue<UndirectedGraphNode> q = new LinkedList<>();
        Set<UndirectedGraphNode> hash = new HashSet<>();
        q.offer(node);
        hash.add(node);
        while (!q.isEmpty()) {
            UndirectedGraphNode head = q.poll();
            for (UndirectedGraphNode nei : head.neighbors) {
                if (hash.contains(nei)) {
                    continue;
                }
                q.offer(nei);
                hash.add(nei);
            }
        }
        return new ArrayList<UndirectedGraphNode>(hash);
    }
}

598、Zombie in Matrix

  • 題目
    Given a 2D grid, each cell is either a wall 2, a zombie 1 or people 0 (the number zero, one, two).Zombies can turn the nearest people(up/down/left/right) into zombies every day, but can not through wall. How long will it take to turn all people into zombies? Return -1 if can not turn all people into zombies.
    樣例
    Given a matrix:
    0 1 2 0 0
    1 0 0 2 1
    0 1 0 0 0
    return 2

  • 程式碼

class Point {
    int x;
    int y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
public class Solution {
    public int zombie(int[][] grid) {
        if (grid == null || grid.length == 0) {
            return -1;
        }
        if (grid[0] == null || grid[0].length == 0) {
            return -1;
        }
        int[] deltaX = {1, 0, 0, -1};
        int[] deltaY = {0, 1, -1, 0};
        Queue<Point> q = new LinkedList<>();
        int countPeople = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == 1) {
                    q.offer(new Point(i, j));
                } else if (grid[i][j] == 0) {
                    countPeople++;
                }
            }
        }
        int day = 0;
        while (!q.isEmpty()) {
            if (countPeople == 0) {
                return day;
            }
            int size = q.size();
            for (int i = 0; i < size; i++) {
                Point node = q.poll();
                for (int j = 0; j < 4; j++) {
                    Point newNode = new Point(node.x + deltaX[j],
                                              node.y + deltaY[j]);
                    if (!isValid(grid, newNode)) {
                        continue;
                    }
                    grid[newNode.x][newNode.y] = 1;
                    countPeople--;
                    q.offer(newNode);
                }
            }
            day++;
        }
        return -1;
    }
    private boolean isValid(int[][] grid, Point node) {
        int n = grid.length;
        int m = grid[0].length;
        return node.x >= 0 && node.x < n && node.y >= 0 && node.y < m && grid[node.x][node.y] == 0;
    }
}

611、Knight Shortest Path

  • 題目
    Given a knight in a chessboard (a binary matrix with 0 as empty and 1 as barrier) with a source position, find the shortest path to a destination position, return the length of the route.
    Return -1 if knight can not reached.
    【需要再來一遍~】
    注意事項
    source and destination must be empty.
    Knight can not enter the barrier.
    說明
    If the knight is at (x, y), he can get to the following positions in one step:
    (x + 1, y + 2)
    (x + 1, y - 2)
    (x - 1, y + 2)
    (x - 1, y - 2)
    (x + 2, y + 1)
    (x + 2, y - 1)
    (x - 2, y + 1)
    (x - 2, y - 1)
    樣例
    [[0,0,0],
    [0,0,0],
    [0,0,0]]
    source = [2, 0] destination = [2, 2] return 2
    [[0,1,0],
    [0,0,0],
    [0,0,0]]
    source = [2, 0] destination = [2, 2] return 6
    [[0,1,0],
    [0,0,1],
    [0,0,0]]
    source = [2, 0] destination = [2, 2] return -1

  • 程式碼

/**
 * Definition for a point.
 * public class Point {
 *     publoc int x, y;
 *     public Point() { x = 0; y = 0; }
 *     public Point(int a, int b) { x = a; y = b; }
 * }
 */
public class Solution {
    public int shortestPath(boolean[][] grid, Point source, Point destination) {
        int[] deltaX = {1, 1, -1, -1, -2, -2, 2, 2};
        int[] deltaY = {2, -2, 2, -2, 1, -1, 1, -1};
        Queue<Point> q = new LinkedList<>();
        q.offer(source);
        int count = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                Point node = q.poll();
                if (node.x == destination.x && node.y == destination.y) {
                    return count;
                }
                for (int j = 0; j < 8; j++) {
                    Point newNode = new Point(node.x + deltaX[j],
                                              node.y + deltaY[j]);
                    if (!isValid(grid, newNode)) {
                        continue;
                    }
                    q.offer(newNode);
                    grid[newNode.x][newNode.y] = true;
                }
            }
            count++;
        }
        return -1;
    }
    private boolean isValid(boolean[][] grid, Point node) {
        int n = grid.length;
        int m = grid[0].length;
        return node.x >= 0 && node.x < n && node.y >= 0 && node.y < m && grid[node.x][node.y] == false;
    }
}

127、拓撲排序

  • 題目
    給定一個有向圖,圖節點的拓撲排序被定義為:
    對於每條有向邊A–> B,則A必須排在B之前  
    拓撲排序的第一個節點可以是任何在圖中沒有其他節點指向它的節點  
    找到給定圖的任一拓撲排序
    注意事項
    你可以假設圖中至少存在一種拓撲排序

  • 程式碼

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<>();
        Map<DirectedGraphNode, Integer> map = new HashMap<>();
        for (DirectedGraphNode node : graph) {
            for (DirectedGraphNode nei : node.neighbors) {
                if (map.containsKey(nei)) {
                    map.put(nei, map.get(nei) + 1);
                } else {
                    map.put(nei, 1);
                }
            }
        }
        Queue<DirectedGraphNode> q = new LinkedList<>();
        for (DirectedGraphNode node : graph) {
            if (!map.containsKey(node)) {
                q.offer(node);
            }
        }
        while (!q.isEmpty()) {
            DirectedGraphNode node = q.poll();
            result.add(node);
            for (DirectedGraphNode nei : node.neighbors) {
                map.put(nei, map.get(nei) - 1);
                if (map.get(nei) == 0) {
                    q.offer(nei);
                }
            }
        }
        return result;
    }
}

615、Course Schedule

  • 題目
    There are a total of n courses you have to take, labeled from 0 to n - 1.
    Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
    Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
    【需要再來一遍~】
    樣例
    Given n = 2, prerequisites = [[1,0]]
    Return true
    Given n = 2, prerequisites = [[1,0],[0,1]]
    Return false

  • 程式碼

public class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        List[] edges = new ArrayList[numCourses];
        for (int i = 0; i < numCourses; i++) {
            edges[i] = new ArrayList<Integer>();
        }
        int[] degree = new int[numCourses];
        for (int i = 0; i < prerequisites.length; i++) {
            degree[prerequisites[i][0]]++;
            edges[prerequisites[i][1]].add(prerequisites[i][0]);
        }
        Queue<Integer> q = new LinkedList<>();
        for (int i = 0; i < numCourses; i++) {
            if (degree[i] == 0) {
                q.offer(i);
            }
        }
        int count = 0;
        while (!q.isEmpty()) {
            int course = q.poll();
            count++;
            for (int i = 0; i < edges[course].size(); i++) {
                int pointer = (int) edges[course].get(i);
                degree[pointer]--;
                if (degree[pointer] == 0) {
                    q.offer(pointer);
                }
            }
        }
        return count == numCourses;
    }
}

616、安排課程

  • 題目
    你需要去上n門九章的課才能獲得offer,這些課被標號為 0 到 n-1 。
    有一些課程需要“前置課程”,比如如果你要上課程0,你需要先學課程1,我們用一個匹配來表示他們: [0,1]
    給你課程的總數量和一些前置課程的需求,返回你為了學完所有課程所安排的學習順序。
    可能會有多個正確的順序,你只要返回一種就可以了。如果不可能完成所有課程,返回一個空陣列。
    【需要再來一遍~】
    樣例
    給定 n = 2, prerequisites = [[1,0]]
    返回 [0,1]
    給定 n = 4, prerequisites = [1,0],[2,0],[3,1],[3,2]]
    返回 [0,1,2,3] or [0,2,1,3]

  • 程式碼

public class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        List[] edges = new ArrayList[numCourses];
        int[] degree = new int[numCourses];
        for (int i = 0; i < numCourses; i++) {
            edges[i] = new ArrayList<Integer>();
        }
        for (int i = 0; i < prerequisites.length; i++) {
            degree[prerequisites[i][0]]++;
            edges[prerequisites[i][1]].add(prerequisites[i][0]);
        }
        Queue<Integer> q = new LinkedList<>();
        for (int i = 0; i < numCourses; i++) {
            if (degree[i] == 0) {
                q.offer(i);
            }
        }
        int[] result = new int[numCourses];
        int j = 0;
        while (!q.isEmpty()) {
            int course = q.poll();
            result[j++] = course;
            for (int i = 0; i < edges[course].size(); i++) {
                int pointer = (int) edges[course].get(i);
                degree[pointer]--;
                if (degree[pointer] == 0) {
                    q.offer(pointer);
                }
            }
        }
        if (j == numCourses) {
            return result;
        } else {
            return new int[0];
        }
    }
}

178、圖是否是樹

  • 題目
    給出 n 個節點,標號分別從 0 到 n - 1 並且給出一個 無向 邊的列表 (給出每條邊的兩個頂點), 寫一個函式去判斷這張`無向`圖是否是一棵樹
    【再來一遍~】
    注意事項
    你可以假設我們不會給出重複的邊在邊的列表當中. 無向邊 [0, 1] 和 [1, 0] 是同一條邊, 因此他們不會同時出現在我們給你的邊的列表當中。
    樣例
    給出n = 5 並且 edges = [[0, 1], [0, 2], [0, 3], [1, 4]], 返回 true.
    給出n = 5 並且 edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], 返回 false.

  • 程式碼

public class Solution {
    public boolean validTree(int n, int[][] edges) {
        if (n == 0) {
            return false;
        }
        if (edges.length != n - 1) {
            return false;
        }
        Map<Integer, Set<Integer>> map = initialize(n, edges);
        Queue<Integer> q = new LinkedList<>();
        Set<Integer> hash = new HashSet<>();
        q.offer(0);
        hash.add(0);
        int count = 0;
        while (!q.isEmpty()) {
            int node = q.poll();
            count++;
            for (Integer nei : map.get(node)) {
                if (hash.contains(nei)) {
                    continue;
                }
                q.offer(nei);
                hash.add(nei);
            }
        }
        return count == n;
    }
    private Map<Integer, Set<Integer>> initialize(int n, int[][] edges) {
        Map<Integer, Set<Integer>> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            map.put(i, new HashSet<Integer>());
        }
        for (int i = 0; i < edges.length; i++) {
            int u = edges[i][0];
            int v = edges[i][1];
            map.get(u).add(v);
            map.get(v).add(u);
        }
        return map;
    }
}

也可以像615、616那樣用List[]

public class Solution {
    public boolean validTree(int n, int[][] edges) {
        if (n == 0) {
            return false;
        }
        if (edges.length != n - 1) {
            return false;
        }
        List[] list = initialize(n, edges);
        Queue<Integer> q = new LinkedList<>();
        Set<Integer> hash = new HashSet<>();
        q.offer(0);
        hash.add(0);
        int count = 0;
        while (!q.isEmpty()) {
            int node = q.poll();
            count++;
            for (Object nei : list[node]) {
                if (hash.contains((Integer) nei)) {
                    continue;
                }
                q.offer((Integer) nei);
                hash.add((Integer) nei);
            }
        }
        return count == n;
    }
    private List[] initialize(int n, int[][] edges) {
        List[] list = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            list[i] = new ArrayList<Integer>();
        }
        for (int i = 0; i < edges.length; i++) {
            int u = edges[i][0];
            int v = edges[i][1];
            list[u].add(v);
            list[v].add(u);
        }
        return list;
    }
}

618、Search Graph Nodes

  • 題目
    Given a undirected graph, a node and a target, return the nearest node to given node which value of it is target, return NULL if you can’t find.
    There is a mapping store the nodes’ values in the given parameters.
    注意事項
    It’s guaranteed there is only one available solution
    樣例
    2——3 5
    \ …….. | |
    . \ …….| |
    ….\ …. | |
    ……\ …| |
    …… 1 –4
    Give a node 1, target is 50
    there a hash named values which is [3,4,10,50,50], represent:
    Value of node 1 is 3
    Value of node 2 is 4
    Value of node 3 is 10
    Value of node 4 is 50
    Value of node 5 is 50
    Return node 4

  • 程式碼

/**
 * Definition for graph node.
 * class UndirectedGraphNode {
 *     int label;
 *     ArrayList<UndirectedGraphNode> neighbors;
 *     UndirectedGraphNode(int x) {
 *        label = x; neighbors = new ArrayList<UndirectedGraphNode>();
 *     }
 * };
 */
public class Solution {
    public UndirectedGraphNode searchNode
                           (ArrayList<UndirectedGraphNode> graph,                        
                            Map<UndirectedGraphNode, Integer> values,
                            UndirectedGraphNode node,
                            int target) {
        Queue<UndirectedGraphNode> q = new LinkedList<>();
        Set<UndirectedGraphNode> hash = new HashSet<>();
        q.offer(node);
        hash.add(node);
        while (!q.isEmpty()) {
            UndirectedGraphNode head = q.poll();
            if (values.get(head) == target) {
                return head;
            }
            for (UndirectedGraphNode n : head.neighbors) {
                if (hash.contains(n)) {
                    continue;
                }
                q.offer(n);
                hash.add(n);
            }
        }
        return null;
    }
}

431、找無向圖的連通塊

  • 題目
    找出無向圖中所有的連通塊。
    圖中的每個節點包含一個label屬性和一個鄰接點的列表。(一個無向圖的連通塊是一個子圖,其中任意兩個頂點通過路徑相連,且不與整個圖中的其它頂點相連。)
    注意事項
    每個連通塊內部應該按照label屬性排序
    樣例
    給定圖:
    A——B .C
    \ …….. | . |
    .. \ ….. | . |
    …. \ … | . |
    …… \ . | . |
    …….. . D.E
    返回 {A,B,D}, {C,E}。其中有 2 個連通塊,即{A,B,D}, {C,E}

  • 程式碼

public class Solution {
    public List<List<Integer>> connectedSet(ArrayList<UndirectedGraphNode> nodes) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        Set<UndirectedGraphNode> hash = new HashSet<>();
        for (UndirectedGraphNode node : nodes) {
            if (hash.contains(node)) {
                continue;
            }
            Queue<UndirectedGraphNode> q = new LinkedList<>();
            List<Integer> list = new ArrayList<>();
            q.offer(node);
            hash.add(node);
            while (!q.isEmpty()) {
                UndirectedGraphNode head = q.poll();
                list.add(head.label);
                for (UndirectedGraphNode nei : head.neighbors) {
                    if (hash.contains(nei)) {
                        continue;
                    }
                    q.offer(nei);
                    hash.add(nei);
                }
            }
            Collections.sort(list);
            result.add(list);
        }
        return result;
    }
}

531、六度問題

  • 題目
    六度分離是一個哲學問題,說的是每個人每個東西可以通過六步或者更少的步數建立聯絡。
    現在給你一個友誼關係,查詢兩個人可以通過幾步相連,如果不相連返回 -1
    樣例
    給出圖
    1——2—–4
    \ ………….. /
    . \ ……….. /
    …. \ –3–/
    {1,2,3#2,1,4#3,1,4#4,2,3} s = 1, t = 4 返回 2
    給出圖二
    1 2—–4
    ………. /
    …….. /
    …… 3
    {1#2,4#3,4#4,2,3} s = 1, t = 4 返回 -1

  • 程式碼

/**
 * Definition for Undirected graph.
 * class UndirectedGraphNode {
 *     int label;
 *     List<UndirectedGraphNode> neighbors;
 *     UndirectedGraphNode(int x) { 
 *         label = x;
 *         neighbors = new ArrayList<UndirectedGraphNode>(); 
 *     }
 * };
 */
public class Solution {
    public int sixDegrees(List<UndirectedGraphNode> graph,
                          UndirectedGraphNode s,
                          UndirectedGraphNode t) {
        if (s == t) {
            return 0;
        }
        Map<UndirectedGraphNode, Integer> map = new HashMap<>();
        Queue<UndirectedGraphNode> q = new LinkedList<>();
        q.offer(s);
        map.put(s, 0);
        while (!q.isEmpty()) {
            UndirectedGraphNode node = q.poll();
            if (node == t) {
                return map.get(node);
            }
            for (UndirectedGraphNode nei : node.neighbors) {
                if (map.containsKey(nei)) {
                    continue;
                }
                map.put(nei, map.get(node) + 1);
                q.offer(nei);
            }
        }
        return -1;
    }
}

若用set來做則還需要for迴圈來分層,map則不用。

120、單詞接龍

  • 題目
    給出兩個單詞(start和end)和一個字典,找到從start到end的最短轉換序列
    比如:
    每次只能改變一個字母。
    變換過程中的中間單詞必須在字典中出現。
    注意事項
    如果沒有轉換序列則返回0。
    所有單詞具有相同的長度。
    所有單詞都只包含小寫字母。
    樣例
    給出資料如下:
    start = “hit”
    end = “cog”
    dict = [“hot”,”dot”,”dog”,”lot”,”log”]
    一個最短的變換序列是 “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
    返回它的長度 5

  • 程式碼

public class Solution {
    public int ladderLength(String start, String end, Set<String> dict) {
        if (start.equals(end)) {
            return 1;
        }
        dict.add(end);
        Queue<String> q = new LinkedList<>();
        Set<String> hash = new HashSet<>();
        q.offer(start);
        hash.add(start);
        int ans = 1;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                String str = q.poll();
                if (str.equals(end)) {
                    return ans;
                }
                for (String d : dict) {
                    if (hash.contains(d)) {
                        continue;
                    }
                    if (!isValid(str, d)) {
                        continue;
                    }
                    q.offer(d);
                    hash.add(d);
                }
            }
            ans++;
        }
        return 0;
    }
    private boolean isValid(String str, String d) {
        int diff = 0;
        int len = str.length();
        for (int i = 0; i < len; i++) {
            if (str.charAt(i) != d.charAt(i)) {
                diff++;
            }
        }
        return diff == 1;
    }
}

624、Remove Substrings

  • 題目
    Given a string s and a set of n substrings. You are supposed to remove every instance of those n substrings from s so that s is of the minimum length and output this minimum length.
    【需要再來一遍~】
    樣例
    Given s = ccdaabcdbb, substrs = [“ab”, “cd”]
    Return 2
    Explanation:
    ccdaabcdbb -> ccdacdbb -> cabb -> cb (length = 2)

  • 程式碼

public class Solution {
    public int minLength(String s, Set<String> dict) {
        Queue<String> q = new LinkedList<>();
        Set<String> hash = new HashSet<>();
        q.offer(s);
        hash.add(s);
        int min = s.length();
        while (!q.isEmpty()) {
            s = q.poll();
            for (String d : dict) {
                int found = s.indexOf(d);
                while (found != -1) {
                    String newStr = s.substring(0, found) + s.substring(found + d.length(), s.length());
                    if (!hash.contains(newStr)) {
                        if (newStr.length() < min) {
                            min = newStr.length();
                        }
                        q.offer(newStr);
                        hash.add(newStr);
                    }