LC摘选

454. 四数相加 II

  • 思路
    • example
    • 四个数组相同长度
    • 第一步:brute-force: O(n^4)
    • hash: dict
      • record[num] = freq

第二步:O(n^3)+O(n) = O(n^3)
第三步:(nums1[i]+nums2[j]) + (nums3[k]+nums4[l]), O(n^2)

  • 复杂度. 时间:O(n^2), 空间: O(n^2)
class Solution:
    def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
        record = collections.defaultdict(int)  
        for num1 in nums1:
            for num2 in nums2:
                record[num1+num2] += 1
        res = 0
        for num3 in nums3:
            for num4 in nums4:
                if record[-(num3+num4)] > 0:
                    res += record[-(num3+num4)] # !!!
        return res    

151. 反转字符串中的单词

  • 思路
    • example
    • 内置函数
  • 复杂度. 时间:O(n), 空间: O(n)
class Solution:
    def reverseWords(self, s: str) -> str:
        return ' '.join(reversed(s.split()))
  • 反转两次 (局部,整体)
  • step 1: trim spaces
    • " abc def " --> “abc def"
  • step 2: reverse each word in the string
    • "cba fed"
  • step 3: reverse the whole string
    • “def abc"
  • 细节比较多
class Solution:
    def reverseWords(self, s: str) -> str:
        def trim(s):
            n = len(s)
            left = 0
            while left < n and s[left] == ' ':
                left += 1
            right = n-1
            while left <= right and s[right] == ' ':
                right -= 1
            s1 = []
            while left <= right:
                if s[left] != ' ' or s1[-1] != ' ': # !!!
                    s1.append(s[left]) 
                left += 1
            return s1 
        def reverse_word(s1):
            n = len(s1)
            left, right = 0, 0
            while right < n:
                ch = s1[right]
                if ch == ' ':
                    reverse(s1, left, right-1) 
                    left = right + 1
                elif right == n-1: # !!!
                    reverse(s1, left, right)
                right += 1
        def reverse(s1, left, right):
            while left < right:
                s1[left], s1[right] = s1[right], s1[left]
                left += 1
                right -= 1
        # step 1, trim spaces
        s1 = trim(s) # output is a list
        # step 2 
        reverse_word(s1) # reverse each word
        # step 3
        reverse(s1, 0, len(s1)-1) # reverse the whole list 
        return ''.join(s1)

28. 找出字符串中第一个匹配项的下标

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        def compute_next(s):
            n = len(s) 
            nxt = [0 for _ in range(n)] 
            i = 1
            j = 0
            while i < n:
                if s[i] == s[j]:
                    nxt[i] = j + 1
                    i += 1
                    j += 1
                else:
                    if j > 0:
                        j = nxt[j-1] 
                    else:
                        nxt[i] = 0 
                        i += 1 
            return nxt  
        m, n = len(haystack), len(needle) 
        nxt = compute_next(needle)  
        i, j = 0, 0 
        while i < m:
            if haystack[i] == needle[j]:
                i += 1
                j += 1
            else:
                if j > 0:
                    j = nxt[j-1] 
                else:
                    i += 1
                    j = 0 
            if j == n:
                return i - n 
        return -1 

20. 有效的括号

  • 思路
    • example
      • '(([]{}))'
      • '(([]})'
      • '(('
    • 用list实现stack (FILO), 用dict记录配对。
    • 最后return的时候注意判断stack是否非空
  • 复杂度. 时间:O(n), 空间: O(n)
class Solution:
    def isValid(self, s: str) -> bool:
        pairs = {'(' : ')', '[': ']', '{': '}'}
        stack = []
        for ch in s:
            if ch in pairs:
                stack.append(ch) 
            else:
                if stack == []: # !!!
                    return False 
                else: 
                    ch0 = stack.pop()  
                    if pairs[ch0] != ch: # !!!
                        return False   
        if stack: # !!!
            return False  
        return True 

239. 滑动窗口最大值

  • 思路
    • example
    • 手动实现单调队列 class
      • que = deque(): 左边出,右边进或出
        • que 维护单调下降数列
          • 新加元素大于前面元素,可以把前面元素pop(),因为前面元素不可能成为当前或者下面窗口的最大值。
          • 新加元素小前面元素,append新元素即可。
      • size(que) = k,滑动窗口size = k
      • 每次需要 (先出后进
        • 移除最左边元素
        • 加进当前位置元素
        • 取que[0]得到当前窗口最大值
  • 复杂度. 时间:O(n), 空间: O(k)

单调队列:先进先出 + 维护最大(小)值


class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        n = len(nums) 
        que = collections.deque() 
        res = []
        for i in range(n):
            num = nums[i] 
            while que and num >= nums[que[-1]]: # !!!
                que.pop() 
            que.append(i)   
            if i - que[0] + 1 > k: # !!!
                que.popleft()  
            if i >= k-1:
                res.append(nums[que[0]])
        return res   

4. 寻找两个正序数组的中位数

  • 第k小 (k >= 1), 二分查找

m+n 奇数:k = (m+n)//2 + 1
m+n 偶数:k = (m+n)//2, (m+n)//2+1 --> average
nums1[index1,...,index1+k//2-2], nums2[index2,...,index2+k//2-2] 假设没有越界情况
pivot1 = nums1[index1+k//2-1], pivot2 = nums2[index2+k//2-1]
Case 1: pivot1 <= pivot2, pivot1 不可能是第k小 (最多第k-1小),index1 = min(index1 + k//2, m-1) , 更新k继续搜索直到k=1
Case 2: pivot1 > pivot2, pivot2 不可能是第k小 (最多第k-1小),index2 = min(index2 + k//2, n-1), 更新k继续搜索直到k=1

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        def getKth(k):
            left1, left2 = 0, 0 # !!!
            while k >= 1: 
                if left1 == m: # !!!
                    return nums2[left2+k-1]
                if left2 == n: # !!!
                    return nums1[left1+k-1] 
                if k == 1: # !!!
                    return min(nums1[left1], nums2[left2])
                right1 = min(left1+k//2-1, m-1) # valid index in nums1
                right2 = min(left2+k//2-1, n-1) # valid index in nums2
                # 有越界的时候,并不是找第k小。比如可能是找第k-3小,但不影响算法,因为每次并不是k//2的递减!!!
                pivot1, pivot2 = nums1[right1], nums2[right2]  
                if pivot1 <= pivot2:
                    k -= right1 - left1 + 1
                    left1 = right1 + 1
                else:
                    k -= right2 - left2 + 1
                    left2 = right2 + 1
        m, n = len(nums1), len(nums2)  
        if (m+n) % 2 == 1:
            return getKth((m+n)//2+1) 
        else:
            return (getKth((m+n)//2) + getKth((m+n)//2+1)) / 2

114. Flatten Binary Tree to Linked List

  • 思路
    • example
    • 分解子问题 (后序遍历)


class Solution:
    def flatten(self, root: Optional[TreeNode]) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        if root == None:
            return 
        self.flatten(root.left)
        self.flatten(root.right) 
        old_left = root.left 
        old_right = root.right 
        root.left = None 
        root.right = old_left 
        while root.right:
            root = root.right 
        root.right = old_right 

98. 验证二叉搜索树

有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。

  • 思路
    • example
    • 递归
    • 注意搜索树的定义
      • 验证左右子树是否搜索树
      • 只比较root.val,root.left.val, root.right.val是不够的。下面的递归前序遍历是错误的。还需要验证根节点值小于右子树最小值,大于左子树最大值。
    • 上图中,就算右子树改为[6,3,7]也是False.
  • 复杂度. 时间:O(n), 空间: O(n)
  • 递归,中序遍历。BST利用中序遍历就是自然的递增顺序!
    • 中序遍历中,如果知道当前节点的pre节点,并且是递增顺序,那么符合要求。
    • 最简单的方法,中序遍历得到一个数组,再判断该数组是不是严格递增顺序。
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        def traversal(root):
            nonlocal pre 
            if root == None:
                return True 
            if traversal(root.left) == False:
                return False 
            if pre and pre.val >= root.val:
                return False 
            pre = root 
            if traversal(root.right) == False:
                return False 
            return True 
        pre = None 
        return traversal(root)

501. 二叉搜索树中的众数

  • 思路
    • example
    • 含重复值
    • 有序数组累计频率
    • 递归,中序,维护pre节点, 双指针
      • pre节点
      • max_freq
      • cur_freq
      • res = [] 保存结果
  • 复杂度. 时间:O(n), 空间: O(1) (如果递归栈不算在内)
class Solution:
    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        def traversal(root):
            nonlocal pre, cnt, cnt_max, res # res!!!
            if root == None:
                return 
            traversal(root.left)
            if pre:
                if root.val == pre.val:
                    cnt += 1
                else:
                    cnt = 1
            else:
                cnt = 1
            if cnt > cnt_max:
                cnt_max = cnt 
                res = [root.val]
            elif cnt == cnt_max:
                res.append(root.val)
            pre = root 
            traversal(root.right)
        cnt, cnt_max = -1, -float('inf')
        pre = None 
        res = []
        traversal(root)
        return res 

236. 二叉树的最近公共祖先

  • 思路
    • example
    • 所有 Node.val 互不相同.
    • p and q will exist in the tree.
  • 递归,后序自下而上,回溯

返回值:p, q, None, 或者LCA(p,q)

  • 遍历整棵树
  • 不直观, 注意Base Case的逻辑。
  • 前提:树中必有p,q节点,并且树中节点数值各不相同!!!
  • def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
    • 函数意义:
      • 树中含有p,q时,返回最近公共祖先
      • 树中只含p或q的一个时,返回相应的节点
      • 树中不含p和q时,返回None
    • 后序:结合左子树与右子树遍历结果
      • 如果左子树含有p,q。那么左子树返回结果即为答案。如果右子树含有p,q. 那到右子树返回结果即为答案。
      • 如果左子树只含q,q中的一个,返回左子树结果。如果右子树只含q,q中的一个,返回右子树结果。
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if root == None:
            return None 
        if root == p or root == q:
            return root 
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        if left and right:
            return root 
        if left == None:
            return right 
        if right == None:
            return left 
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        def traversal(root):
            if root == None:
                return None 
            if root == p or root == q:
                return root 
            left = traversal(root.left) 
            right = traversal(root.right) 
            if left == None:
                return right 
            if right == None:
                return left 
            return root 
        return traversal(root) 
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if root == None:
            return None   
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)  
        if root.val == p.val or root.val == q.val:
            return root  
        if left and right == None:
            return left  
        if left == None and right:
            return right 
        if left == None and right == None:
            return None  
        if left and right:
            return root  

77. 组合

  • 思路
    • example
    • 回溯,去重
      • 宽度:n
      • 深度:k


  • 复杂度. 时间:, 空间:
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        def backtrack(start):
            if len(path) == k:
                res.append(path[:])
                return 
            for i in range(start+1, n+1):
                path.append(i)
                backtrack(i)
                path.pop()
        res = []
        path = []
        backtrack(0)
        return res 
  • 优化:剪枝
    • 横向遍历的时候去掉不可能成功(个数不足)的情况。


class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        def backtrack(start):
            if len(path) == k:
                res.append(path[:])
                return 
            for i in range(start, n-(k-len(path))+2):
                path.append(i)
                backtrack(i+1) 
                path.pop()
        res, path = [], []
        backtrack(1)
        return res 

93. 复原 IP 地址

class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        def backtrack(start_idx):
            if start_idx == len(s):
                if len(path) == 4:
                    res.append('.'.join(path)) 
                return  
            for i in range(start_idx, min(start_idx+3, len(s))):
                if s[start_idx] == '0' and i > start_idx: # !!!
                    break   
                if int(s[start_idx:i+1]) <= 255:
                    if len(path) == 4:
                        break  
                    path.append(s[start_idx:i+1])
                    backtrack(i+1)
                    path.pop()  
        res, path = [], []
        backtrack(0) 
        return res   

698. 划分为k个相等的子集

class Solution:
    def canPartitionKSubsets(self, nums: List[int], k: int) -> bool:
        cache = dict()
        def dfs(state, cur_sum):
            if (state, cur_sum) in cache:
                return cache[(state, cur_sum)] 
            if state == (1<<len(nums))-1: 
                return True   
            for j in range(len(nums)):
                if state & (1<<j) == 0:
                    if cur_sum + nums[j] > target:
                        break  
                    if dfs(state+(1<<j), (cur_sum+nums[j]) % target):
                        cache[(state, cur_sum)] = True  
                        return True  
            cache[(state, cur_sum)] = False  
            return False 
        total = sum(nums) 
        if total % k != 0:
            return False  
        target = total // k  
        nums.sort()  
        if nums[-1] > target:
            return False  
        return dfs(0, 0)

491. Non-decreasing Subsequences

class Solution:
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        def backtrack(start_idx):
            if len(path) >= 2:
                res.append(path[:]) 
            if start_idx == len(nums):
                return  
            used = set()
            for i in range(start_idx, len(nums)):
                if nums[i] in used:
                    continue   
                if path and nums[i] < path[-1]:
                    continue  
                path.append(nums[i]) 
                backtrack(i+1) 
                path.pop()   
                used.add(nums[i]) # !!!
        res, path = [], []  
        backtrack(0)  
        return res  

332. 重新安排行程


class Solution:
    def findItinerary(self, tickets: List[List[str]]) -> List[str]:
        def backtrack(start_pos):
            if len(path) == n+1:
                return True  
            for _ in range(len(record[start_pos])): # !!!
                end_pos = record[start_pos].pop(0)
                path.append(end_pos)
                if backtrack(end_pos):
                    return True  
                path.pop() 
                record[start_pos].append(end_pos) 
            return False  
        record = collections.defaultdict(list)  
        n = len(tickets)
        for i in range(n):
            record[tickets[i][0]].append(tickets[i][1]) 
        for key, val in record.items():
            record[key].sort()  
        path = ['JFK'] 
        backtrack('JFK') 
        return path  

53. 最大子数组和

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)  
        sum_ = nums[0] 
        res = nums[0] 
        for i in range(1, n):
            if sum_ < 0:
                sum_ = nums[i]  
            else:
                sum_ += nums[i]  
            res = max(res, sum_)  
        return res   

1005. K 次取反后最大化的数组和

class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        nums.sort() # !!!
        n = len(nums)
        cnt = 0 
        for i in range(n):
            if nums[i] < 0:
                cnt += 1
        for i in range(min(cnt, k)):
            nums[i] = -nums[i] 
        k -= min(cnt, k)
        if k % 2 == 0:
            return sum(nums) 
        else:
            return sum(nums) - 2*min(nums)
class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        sum_ = sum(nums)
        freq = collections.defaultdict(int)   
        for num in nums:
            freq[num] += 1 
        for num in range(-100, 0):
            if freq[num] == 0:
                continue   
            times = min(k, freq[num]) 
            sum_ -= 2*num*times  
            freq[num] -= times  
            freq[-num] += times  
            k -= times  
            if k == 0:
                return sum_  
        for num in range(0, 101):
            if freq[num] == 0:
                continue 
            if k % 2 == 0:
                return sum_  
            else:
                return sum_ - 2*num 

406. 根据身高重建队列

class Solution:
    def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
        people.sort(key=lambda x: (-x[0], x[1]))
        res = []  
        for i in range(len(people)):
            res.insert(people[i][1], people[i])
        return res   

452. 用最少数量的箭引爆气球

class Solution:
    def findMinArrowShots(self, points: List[List[int]]) -> int:
        n = len(points) 
        points.sort(key=lambda x: x[0]) # !!!
        res = 1
        right = points[0][1]  
        for i in range(1, n):
            if points[i][0] > right:
                res += 1
                right = points[i][1] 
            else: # !!!
                right = min(right, points[i][1])  
        return res    

968. 监控二叉树

# - 0:无覆盖, 无摄像头 (没有**被childern覆盖**)
# - 1:有覆盖, 有摄像头
# - 2:有覆盖,无摄像头 (被其中一个child覆盖)
class Solution:
    def minCameraCover(self, root: Optional[TreeNode]) -> int:
        def traversal(root):
            nonlocal res  
            if root == None:
                return 2
            left = traversal(root.left)
            right = traversal(root.right) 
            if left == 0 or right == 0:
                res += 1
                return 1
            if left == 1 or right == 1:
                return 2  
            if left == 2 and right == 2:
                return 0  
        res = 0
        if traversal(root) == 0:
            res += 1
        return res  

494. 目标和

  • 思路
    • example
    • 返回不同 表达式 的数目。
    • 暴力回溯
    • 数字分为两组:positive (+), negative (-)

positive - negative = target
positive + negative = sum_
positive = (sum_ + target) // 2 (if sum+ target is even)

  • 选出(+)子集使得和为positive (integer)
  • 0 <= nums[i] <= 1000, -1000 <= target <= 1000
  • 0-1背包
    • 背包容量:j
    • 物品:每个数字最多选一次
  • DP (1D): dp[j]: 使得(+)数组和为j的组合数。
    • dp[0] = 1
  • 目标:dp[positive]
  • 复杂度. 时间:O(n*sum_), 空间: O(sum_)
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        n = len(nums)
        sum_ = sum(nums)
        if (target + sum_) % 2 != 0:
            return 0
        else:
            positive = (target + sum_) // 2
        if positive < 0:
            return 0
        dp = [0 for _ in range(positive+1)]
        dp[0] = 1
        for i in range(n):
            for j in range(positive, -1, -1):
                if j >= nums[i]:
                    dp[j] += dp[j-nums[i]] # 选与不选两种情况累加
        return dp[positive]
  • 2D, 前i个
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        n = len(nums) 
        total = sum(nums) 
        if (total + target) % 2 != 0:
            return 0 
        pos =  (total + target) // 2 
        if pos < 0:  #!!!
            return 0 
        dp = [[0 for _ in range(pos+1)] for _ in range(n+1)]  
        dp[0][0] = 1
        for i in range(1, n+1):
            for j in range(pos+1):
                if j < nums[i-1]:
                    dp[i][j] = dp[i-1][j] 
                else:
                    dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]]
        return dp[n][pos]  

322. Coin Change

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        n = len(coins)  
        dp = [[amount+1 for _ in range(amount+1)] for _ in range(n+1)]  # !!!
        dp[0][0] = 0
        for i in range(1, n+1):
            coin = coins[i-1] 
            for j in range(amount+1):
                if j < coin:
                    dp[i][j] = dp[i-1][j] 
                else:
                    dp[i][j] = min(dp[i-1][j], dp[i][j-coin] + 1)  # !!!
        return dp[n][amount] if dp[n][amount] != amount+1 else -1

518. 零钱兑换 II

class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        n = len(coins)  
        dp = [[0 for _ in range(amount+1)] for _ in range(n+1)] 
        dp[0][0] = 1 
        for i in range(1, n+1):
            coin = coins[i-1] 
            for j in range(amount+1):
                if j < coin:
                    dp[i][j] = dp[i-1][j] 
                else:
                    dp[i][j] = dp[i-1][j] + dp[i][j-coin]  
        return dp[n][amount] 
class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        dp = [0 for _ in range(amount+1)]
        dp[0] = 1 # !!!
        for coin in coins:
            for j in range(coin, amount+1):
                dp[j] += dp[j-coin]
        return dp[amount] 

377. 组合总和 Ⅳ

  • 爬楼梯框架
class Solution:
    def combinationSum4(self, nums: List[int], target: int) -> int:
        dp = [0 for _ in range(target+1)] 
        dp[0] = 1  # !!!
        for j in range(target+1):
            for num in nums:
                if j >= num:
                    dp[j] += dp[j-num] 
        return dp[target]

139. 单词拆分

  • 思路
    • example
    • 暴力回溯,memo dfs
      • 分割字符串问题
    • 完全背包 + 排列 (有先后顺序)
      • 物品:wordDict
      • 遍历顺序:先背包 再物品
        • 注意index j的意义及取值范围
  • 复杂度. 时间:O(?), 空间: O(?)
    • 为了处理空字符串,用前j个逻辑。
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        n = len(s)  
        m = len(wordDict)  
        dp = [False for _ in range(n+1)]
        dp[0] = True  
        for j in range(1, n+1):
            for i in range(m):
                length = len(wordDict[i]) 
                if j >= length:
                    dp[j] = dp[j] or (dp[j-length] and s[j-length:j] == wordDict[i]) 
                if dp[j]: 
                    break  
        return dp[n] 
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容