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);
                    }
                    found = s.indexOf(d, found + 1);
                }
            }
        }
        return min;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值