宽度优先搜索

Java

Queue<TreeNode> queue = new LinkedList<>();
String[] vals = String.split(" ");
int result = Integer.parseInt(String);
Collections.reverse(List);
new int[]{1,0};
  1. BFS应用场景
    图的遍历 Traversal in Graph
  • 层级遍历 Level Order Traversal
  • 由点及面 Connected Component
  • 拓扑排序 Topological Sorting

最短路径 Shortest Path in Simple Graph

  • 仅限简单图求最短路径
  • 即,图中每条边长度都是1,或者边长都相等

非递归的方式找所有方案 Iteration solution for all possible results
• 这一点我们将在后面 DFS 的课上提到

  1. 复杂度
    二叉树 时间O(V) 空间:同层节点个数最大值
    图 时间O(V+E) 空间:最大深度
    优化方案 双向BFS Bidirectional BFS
  • 假设单向BFS需要搜索 N 层才能到达终点,每层的判断量为 X,那么总的运算量为 X ^ N 如果换成是双向BFS,前后各自需要搜索 N / 2 层,总运算量为 2 * X ^ (N / 2)
  • 无向图; 所有边的长度都为 1 或者长度都一样; 同时给出了起点和终点
  1. 二叉树上的BFS
    102 Binary Tree Level Order Traversal
    297 Serialize and Deserialize Binary Tree
  • 访问到节点的时候 在结果字符串上添加当前节点信息
  • serialize时候空节点也入队 否则无法表示空节点
  1. 图上的BFS
    注意节点不要重复入队就好
    133 Clone Graph
    *127 Word Ladder
    *261 Graph Valid Tree
    lt431 Connected Component in Undirected Graph
  1. 矩阵上的BFS
    200 Number of Islands 四个
    lt611 Knight Shortest Path 八个
    *lt598 Zombie in Matrix
    lt573 Build Post Office II

  2. 拓扑排序
    算法描述:
    统计每个点的入度
    将每个入度为 0 的点放入队列(Queue)中作为起始节点
    不断从队列中拿出一个点,去掉这个点的所有连边(指向其他点的边),其他点的相应的入度 - 1
    一旦发现新的入度为 0 的点,丢回队列中

求任意一个拓扑排序
lt127 Topological Sorting
210 Course Schedule II
*269 Alien Dictionary 注意可能会有重复的字符对 这种情况下入度不更新
求是否存在拓扑排序
207 Course Schedule
求是否存在且仅存在一个拓扑序 Queue中最多同时只有1个节点
*444 Sequence Reconstruction
注意 重复对不能重复统计入度
求所有的拓扑序 DFS

102 Binary Tree Level Order Traversal

/**
 * 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;
 *     }
 * }
 */

public class Solution {
    /**
     * @param root: A Tree
     * @return: Level order a list of lists of integer
     */
    public List<List<Integer>> levelOrder(TreeNode root) {
        // write your code here
        List<List<Integer>> results = new ArrayList<>();
        if(root==null)
            return results;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            List<Integer> list = new ArrayList<>();
            for(int i=0; i<size; i++){
                TreeNode node = queue.poll();
                if(node.left!=null)
                    queue.offer(node.left);
                if(node.right!=null)
                    queue.offer(node.right);
                list.add(node.val);
            }
            results.add(list);
        }
        return results;
    }
}

297 Serialize and Deserialize Binary Tree

/**
 * 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;
 *     }
 * }
 */


public class Solution {
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
    public String serialize(TreeNode root) {
        // write your code here
        StringBuilder sb = new StringBuilder();
        if(root==null){
            return sb.toString();
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            if(node==null){
                sb.append("# ");
                continue;
            }
            sb.append(node.val);
            sb.append(" ");
            queue.offer(node.left);
            queue.offer(node.right);
        }
        return sb.toString();
    }

    /**
     * This method will be invoked second, the argument data is what exactly
     * you serialized at method "serialize", that means the data is not given by
     * system, it's given by your own serialize method. So the format of data is
     * designed by yourself, and deserialize it here as you serialize it in 
     * "serialize" method.
     */
    public TreeNode deserialize(String data) {
        // write your code here
        if(data==null || data.length()==0)
            return null;
        String[] vals = data.split(" ");
        TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int index = 1;
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            if(vals[index].equals("#")){
                node.left = null;
            }else{
                node.left = new TreeNode(Integer.parseInt(vals[index]));
                queue.offer(node.left);
            }
            index++;
            if(vals[index].equals("#")){
                node.right = null;
            }else{
                node.right = new TreeNode(Integer.parseInt(vals[index]));
                queue.offer(node.right);
            }
            index++;
        }
        return root;
    }
}

133 Clone Graph

/**
 * 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) {
        // write your code here
        if(node==null)
            return null;
        UndirectedGraphNode newroot = new UndirectedGraphNode(node.label);
        Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
        map.put(node, newroot);
        Queue<UndirectedGraphNode> queue = new LinkedList<>();
        queue.offer(node);
        while(!queue.isEmpty()){
            UndirectedGraphNode current = queue.poll();
            for(UndirectedGraphNode neighbor: current.neighbors){
                UndirectedGraphNode newNeighbor;
                if(!map.containsKey(neighbor)){
                    newNeighbor = new UndirectedGraphNode(neighbor.label);
                    map.put(neighbor, newNeighbor);
                    queue.offer(neighbor);
                }
                newNeighbor = map.get(neighbor);
                UndirectedGraphNode newCurrent = map.get(current);
                newCurrent.neighbors.add(newNeighbor);
            }
        }
        return newroot;
    }
}

127 Word Ladder

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> set = new HashSet<>();
        for(String str : wordList){
            set.add(str);
        }
        int result = 2;
        if(!set.contains(endWord))
            return 0;
        if(beginWord.equals(endWord))
            return 1;
        Queue<String> queue = new LinkedList<>();
        Set<String> visited = new HashSet<>();
        visited.add(beginWord);
        queue.offer(beginWord);
        while(!queue.isEmpty()){
            
            int size = queue.size();
            for(int i=0; i<size; i++){
                String current = queue.poll();
                for(String next : getNextWords(set, current, visited)){
                    if(endWord.equals(next))
                        return result;
                    queue.offer(next);
                }
            } 
           result++; 
        }
        return 0;
    }
    private List<String> getNextWords(Set<String> set, String str, Set<String> visited){
        List<String> result = new ArrayList<>();
        char[] chars = str.toCharArray();
        for(int i=0; i<chars.length; i++){
            for(char c='a'; c<'z'; c++){
                char charati = chars[i];
                if(c==chars[i])
                    continue;
                chars[i] = c;
                String temp = new String(chars);
                if(set.contains(temp) && !visited.contains(temp)){
                    result.add(temp);
                    visited.add(temp);
                }     
                chars[i] = charati;
            }
        }
        return result;
    }
}

261 Graph Valid Tree

class Solution {
    public boolean validTree(int n, int[][] edges) {
        return bfs(n, edges);
    }
    private boolean bfs(int n, int[][] edges){
        if(edges.length!=n-1)
            return false;
        Map<Integer, Set<Integer>> graph = new HashMap<>();
        for(int[] edge : edges){
            int n0 = edge[0];
            int n1 = edge[1];
            Set<Integer> set0 = graph.getOrDefault(n0, new HashSet<>());
            Set<Integer> set1 = graph.getOrDefault(n1, new HashSet<>());
            set0.add(n1);
            set1.add(n0);
            graph.put(n0, set0);
            graph.put(n1, set1);
        }
        Queue<Integer> queue = new LinkedList<>();
        Set<Integer> visited = new HashSet<>();
        queue.offer(0);
        visited.add(0);
        int count = 0;
        while(!queue.isEmpty()){
            int current = queue.poll();
            count++;
            for(Integer next : graph.getOrDefault(current, new HashSet<>())){
                if(visited.contains(next))
                    return false;
                visited.add(next);
                Set<Integer> set = graph.get(next);
                set.remove(current);
                graph.put(next, set);
                queue.offer(next);
            }
        }
        System.out.println(count);
        return count == n;
    }
}

lt431 Connected Component in Undirected Graph

/**
 * Definition for Undirected graph.
 * class UndirectedGraphNode {
 *     int label;
 *     ArrayList<UndirectedGraphNode> neighbors;
 *     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
 * };
 */


public class Solution {
    /*
     * @param nodes: a array of Undirected graph node
     * @return: a connected set of a Undirected graph
     */
    public List<List<Integer>> connectedSet(List<UndirectedGraphNode> nodes) {
        // write your code here
        if(nodes==null)
            return null;
        Set<UndirectedGraphNode> set = new HashSet<>();
        List<List<Integer>> result = new ArrayList<>();
        for(UndirectedGraphNode node: nodes){
            if(!set.contains(node)){
                set.add(node);
                List<Integer> temp = getBFS(nodes, node, set);
                result.add(temp);
            }
        }
        return result;
    }
    private List<Integer> getBFS(List<UndirectedGraphNode> nodes, UndirectedGraphNode node, Set<UndirectedGraphNode> set){
        List<Integer> result = new ArrayList<>();
        Queue<UndirectedGraphNode> queue = new LinkedList<>();
        queue.offer(node);
        while(!queue.isEmpty()){
            UndirectedGraphNode temp = queue.poll();
            result.add(temp.label);
            for(UndirectedGraphNode neighbor: temp.neighbors){
                if(!set.contains(neighbor)){
                    queue.offer(neighbor);
                    set.add(neighbor);
                }
            }
        }
        Collections.sort(result);
        return result;
    }
}

200 Number of Islands

class Solution {
    public int numIslands(char[][] grid) {
        if(grid==null || grid.length==0 || grid[0]==null || grid[0].length==0)
            return 0;
        int result = 0;
        boolean[][] visited = new boolean[grid.length][grid[0].length];
        for(int i=0; i<grid.length; i++){
            for(int j=0; j<grid[0].length; j++){
                if(grid[i][j]=='1'){
                    result++;
                    grid[i][j] = '0';
                    visited[i][j] = true;
                    bfs(grid, i, j, visited);
                }
            }
        }
        return result;
    }
    private void bfs(char[][] grid, int i, int j, boolean[][] visited){
        int[] dirx = {1, -1, 0, 0};
        int[] diry = {0, 0, 1, -1};
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{i, j});
        while(!queue.isEmpty()){
            int[] current = queue.poll();
            for(int k=0; k<4; k++){
                int x = current[0]+dirx[k];
                int y = current[1]+diry[k];
                if(isValid(visited, x, y, grid)){
                    queue.offer(new int[]{x, y});
                    grid[x][y] = '0';
                    visited[x][y] = true;
                }
            }
        }
    }
    private boolean isValid(boolean[][] visited, int x, int y, char[][] grid){
        return x>=0 && x<grid.length && y>=0 && y<grid[0].length && visited[x][y]==false && grid[x][y]=='1';
    }
}

lt611 Knight Shortest Path

/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */

public class Solution {
    /**
     * @param grid: a chessboard included 0 (false) and 1 (true)
     * @param source: a point
     * @param destination: a point
     * @return: the shortest path 
     */
    public int shortestPath(boolean[][] grid, Point source, Point destination) {
        // write your code here
        if(grid==null || grid.length==0 || grid[0]==null || grid[0].length==0)
            return 0;
        if(source.x==destination.x && source.y==destination.y)
            return 0;
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{source.x, source.y});
        int[] dirx = {1, -1, 2, 2, 1, -1, -2, -2};
        int[] diry = {2, 2, 1, -1, -2, -2, 1, -1};
        boolean[][] visited = new boolean[grid.length][grid[0].length];
        visited[source.x][source.y] = true;
        int result = 0;
        while(!queue.isEmpty()){
            result++;
            int size = queue.size();
            System.out.println(size);
            for(int i=0; i<size; i++){
                int[] current = queue.poll();
                int x = current[0];
                int y = current[1];
                System.out.println(x+" "+y);
                for(int j=0; j<8; j++){
                    int newx = x+dirx[j];
                    int newy = y+diry[j];
                    if(isValid(newx, newy, grid, visited)){
                        if(newx==destination.x && newy==destination.y)
                            return result;
                        queue.offer(new int[]{newx, newy});
                        visited[newx][newy] = true;
                    }
                }
            }
        }
        return -1;
    }
    
    private boolean isValid(int x, int y, boolean[][] grid, boolean[][] visited){
        return x>=0 && x<grid.length && y>=0 && y<grid[0].length && grid[x][y]==false && visited[x][y]==false;
    }
}

598 Zombie in Matrix

public class Solution {
   /**
    * @param grid: a 2D integer grid
    * @return: an integer
    */
   public int zombie(int[][] grid) {
       // write your code here
       Queue<int[]> queue = new LinkedList<>();
       for(int i=0; i<grid.length; i++){
           for(int j=0; j<grid[0].length; j++){
               if(grid[i][j]==1)
                   queue.offer(new int[]{i,j});
           }
       }
       int days = 0;
       int[] dirx = {1, -1, 0, 0};
       int[] diry = {0, 0, 1, -1};
       while(!queue.isEmpty()){
           int size = queue.size();
           days++;
           for(int i=0; i<size; i++){
               int[] current = queue.poll();
               int x = current[0];
               int y = current[1];
               for(int k=0; k<4; k++){
                   int newx = x+dirx[k];
                   int newy = y+diry[k];
                   if(isValid(grid, newx, newy)){
                       grid[newx][newy] = 1;
                       queue.offer(new int[]{newx, newy});
                   }
               }
           }
       }
       for(int i=0; i<grid.length; i++){
           for(int j=0; j<grid[0].length; j++){
               if(grid[i][j]==0)
                   return -1;
           }
       }
       return days-1;
   }
   private boolean isValid(int[][] grid, int x, int y){
       return x>=0 && x<grid.length && y>=0 && y<grid[0].length && grid[x][y]==0;
   }
}

127 Topological Sorting

/**
 * 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) {
        // write your code here
        Map<DirectedGraphNode, Integer> map = new HashMap<>();
        for(DirectedGraphNode node : graph){
            for(DirectedGraphNode neighbor : node.neighbors){
                map.put(neighbor, map.getOrDefault(neighbor, 0)+1);
            }
        }
        Queue<DirectedGraphNode> queue = new LinkedList<>();
        for(DirectedGraphNode node : graph){
            if(!map.containsKey(node)){
                queue.offer(node);
            }
        }
        ArrayList<DirectedGraphNode> result = new ArrayList<>();
        while(!queue.isEmpty()){
            DirectedGraphNode node = queue.poll();
            result.add(node);
            for(DirectedGraphNode neighbor : node.neighbors){
                map.put(neighbor, map.get(neighbor)-1);
                if(map.get(neighbor)==0)
                    queue.offer(neighbor);
            }
        }
        return result;
    }
}

210 Course Schedule II

class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        Map<Integer, Integer> map = new HashMap<>();
        Map<Integer, List<Integer>> graph = new HashMap<>();
        for(int[] prerequest : prerequisites){
            int in = prerequest[0];
            int out = prerequest[1];
            map.put(in, map.getOrDefault(in,0)+1);
            List<Integer> neighbors = graph.getOrDefault(out, new ArrayList<>());
            neighbors.add(in);
            graph.put(out, neighbors);
        }
        Queue<Integer> queue = new LinkedList<>();
        for(int i=0; i<numCourses; i++){
            if(!map.containsKey(i)){
                queue.offer(i);
            }
        }
        int count = 0;
        int[] result = new int[numCourses];
        while(!queue.isEmpty()){
            int out = queue.poll();
            result[count] = out;
            count++;
            for(Integer in : graph.getOrDefault(out, new ArrayList<>())){
                map.put(in, map.get(in)-1);
                if(map.get(in)==0)
                    queue.offer(in);
            }
        }
        if(count==numCourses)
            return result;
        return new int[0];
    }
}

269 Alien Dictionary

class Solution {
    public String alienOrder(String[] words) {
        Map<Character, Set<Character>> graph = new HashMap<>();
        Map<Character, Integer> indegree = new HashMap<>();
        Set<Character> alphabet = new HashSet<>();
        for(String word : words){
            for(int i=0; i<word.length(); i++){
                alphabet.add(word.charAt(i));
            }
        }
        for(int i=1; i<words.length; i++){
            String pre = words[i-1];
            String next = words[i];
            int j=0;
            while(j<pre.length() && j<next.length() ){
                if(pre.charAt(j)==next.charAt(j)){
                    j++;
                }else{
                    Set<Character> set = graph.getOrDefault(pre.charAt(j), new HashSet<>());
                    if(set.add(next.charAt(j))){
                        graph.put(pre.charAt(j), set);
                        indegree.put(next.charAt(j), indegree.getOrDefault(next.charAt(j), 0)+1);
                    }
                    break;
                }
            }
        }
        StringBuilder sb = new StringBuilder();
        Queue<Character> queue = new LinkedList<>();
        for(Character c : alphabet){
            if(!indegree.containsKey(c)){
                queue.offer(c);
            }
        }
        while(!queue.isEmpty()){
            Character c = queue.poll();
            sb.append(c);
            for(Character next : graph.getOrDefault(c, new HashSet<>())){
                indegree.put(next, indegree.get(next)-1);
                if(indegree.get(next)==0)
                    queue.offer(next);
            }
        }
        if(sb.length()==alphabet.size()){
            return sb.toString();
        }
        return "";
    }
}

207 Course Schedule

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        Map<Integer, Integer> map = new HashMap<>();
        Map<Integer, List<Integer>> graph = new HashMap<>();
        for(int[] prerequest : prerequisites){
            int in = prerequest[0];
            int out = prerequest[1];
            map.put(in, map.getOrDefault(in,0)+1);
            List<Integer> neighbors = graph.getOrDefault(out, new ArrayList<>());
            neighbors.add(in);
            graph.put(out, neighbors);
        }
        Queue<Integer> queue = new LinkedList<>();
        for(int i=0; i<numCourses; i++){
            if(!map.containsKey(i)){
                queue.offer(i);
            }
        }
        int count = 0;
        while(!queue.isEmpty()){
            int out = queue.poll();
            count++;
            for(Integer in : graph.getOrDefault(out, new ArrayList<>())){
                map.put(in, map.get(in)-1);
                if(map.get(in)==0)
                    queue.offer(in);
            }
        }
        return count==numCourses;
    }
}

444 Sequence Reconstruction

class Solution {
    public boolean sequenceReconstruction(int[] org, List<List<Integer>> seqs) {
        // write your code here
        Map<Integer, Integer> indegree = new HashMap<>();
        Map<Integer, Set<Integer>> graph = new HashMap<>();
        
        int index = 0;
        for(List<Integer> seq : seqs){
            for(int i=1; i<seq.size(); i++){
                int in = seq.get(i);
                int out = seq.get(i-1);
                if(in>org.length || out>org.length)
                    return false;
                if(!graph.containsKey(in)){
                    graph.put(in, new HashSet<>());
                }
                Set<Integer> set = graph.getOrDefault(out, new HashSet<>());
                if(set.add(in)){
                    graph.put(out, set);
                    indegree.put(in, indegree.getOrDefault(in, 0)+1);
                }
                
            }
        }
        System.out.println(indegree.size());
        System.out.println(graph.size());
        Queue<Integer> queue = new LinkedList<>();
        if(indegree.containsKey(org[0]))
            return false;
        queue.offer(org[0]);
        while(!queue.isEmpty()){
            Integer current = queue.poll();
            if(org[index]!=current)
                return false;
            index++;
            for(Integer next : graph.getOrDefault(current, new HashSet<>())){
                indegree.put(next, indegree.get(next)-1);
                if(indegree.get(next)==0)
                    queue.offer(next);
            }
            if(queue.size()>1)
                return false;
        }
        return index==org.length;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容