Lintcode Ladder2 总结

这篇博客总结了Lintcode Ladder2中涉及的各种算法,包括字符串处理、整数数组、二分搜索、数学与位操作、贪婪算法、链表、二叉树、搜索与递归以及动态规划。讲解了各个题目中的关键思路,如KMP算法、二分查找、动态规划解法等,并提及了多种数据结构的应用,如hash表、队列和栈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. String

[Lintcode Ladder2] String

13.Implement strStr()

KMP算法

171.Anagrams

对之前代码对改进:

item_ = str(sorted(item))

注意要转换成string,因为list不能作为dictionary对hash表的key。

79. Longest Common Substring

再看一次还是没有思路,·
自己之前是用暴力做的。
但是现在看起来是一个典型的DP问题。
但是没想太好状态是怎么转变的-> 很简单。自己想多了。

78. Longest Common Prefix

可以用二分。但是蛮复杂的感觉不是很有必要。

2. Integer Array

78. Longest Common Prefix 游标x2/交换

记得python可以直接pop(index)
还有一种思路,是类似于快排的方法。
将相等的数置换到队尾,因为最后inplace的结果,只看前面

138. Subarray Sum 前缀和数组

想用list的index,但是好像不太好用的样子。

100. Remove Duplicates from Sorted Array 游标/交换

直接用list.pop(index)
其他人的做法,有一个游标,用来找到下一个和当前位置不等的数,并将这个数与当前位置的数进行交换

64. Merge Sorted Array 游标

队尾两个游标,从A, B中选取较大的一次填充到队尾

56. Two Sum hash表

50. Product of Array Exclude Itself 前缀积和后缀积,相乘

189. First Missing Positive 交换

将索引和数字匹配

59. 3Sum Closest 游标

固定最左边,left起始位置在固定点的相邻左侧,right在最右边
固定点从左到右移动。

15.3Sum

类似于上一题

3. Binary Search

141. Sqrt(x)

60. Search Insert Position

28. Search a 2D Matrix

把二维数组展开,用二分法,然后重写换算成二维数组的形式。

14. First Position of Target

159. Find Minimum in Rotated Sorted Array

很简单,只要找到第一个不是递增的就是了。

75. Find Peak Element

注意边界情况(然而边界情况被题目排出了,就比较好算)

74. First Bad Version

也是用二分法来找,但是我一开始还费劲吧啦地讨论前一个是false,后一个是true才是满足条件。后来看发现只需要是false右移,是true左移,最后l==r的时候,这个数就是结果。

62. Search in Rotated Sorted Array

分情况讨论,

61. Search for a Range

分两个二分法查找

183. Wood Cut

选取最大的木头,二分查找所有可能的情况,得到第一个可以的

4. Math & Bit Manipulation

181. Flip Bits 负数

负数处理方法:

ff = pow(2, 32)
a_r = (a+ff)%ff

142. O(1) Check Power of 2 **

这个做法也太巧妙了吧!利用了2的幂在二进制条件下的特殊形式。
由此可以推广到n进制(?

2. Trailing Zeros

只需要考虑5的情况,每个5都能产生一位0

179. Update Bits

163. Unique Binary Search Trees

递归

140. Fast Power

只需要考虑不整整除的部分,在每一次幂运算后的变化

180. Binary Representation

这道题要注意小数运算的问题
字符转化成浮点数

5. Greedy

82. Single Number 利用了异或两两抵消

所有元素与0异或,最后的结果是缺少的元素

46. Majority Element

O(nlogn)的话,可以先sort,再求二分之一
如果是O(n)的情况,可以利用主元素的性质,遍历每个元素,存储第一个元素,并与后面的元素比较,如果该元素等于存储的元素,count+1,否则减1,并将存储的元素替换为当前元素。最终留下的元素肯定是主元素。

187. Gas Station

因为是循环,所以可以计算从第一个开始,到最后一个的情况,然后找一个最低的位置,以他后一个开始。因为他们的相对情况是不变的。

184. Largest Number

182. Delete Digits

数学关系

  1. 每次操作都争取找最小的数
  2. 对每次找数时,应该删掉第一个比后面的数大的,因为前一位有进制的加成,肯定比后面的好。

116. Jump Game

每到一个位置,查看该位置是否可抵达,确认后更新后面的位置是否可抵达。

52. Next Permutation

  1. 将数列分成前后两端,保证后面是递减数列。
  2. 在后段从右往左,找到一个大于前段最后一个数的数(即后段第一个小于前段最后一个数的数)
  3. 将这个数和前段的交换。(此时后段递减的性质不变)
  4. 调整后段顺序,从递减到递增。
		# num[:i+1] // num[i+1:] decrease
        # find a smallest element which is bigger than num[i] -> num[j]
        # num[:i] unchange
        # num[i]  <-> num[j]
        #num[i+1:j] num[j] num[j+1:] decrease
        # resvere
        # num[i + 1 + k] <-> num[len(num) - 1- k]
        # 0 - (len(num) - i)//

6. Linked List

174. Remove Nth Node From End of List 快慢指针

165. Merge Two Sorted Lists 建立新的linked list

新建的头结点只作为一个位置,没有实际意义,最后return的时候记得return newhead.next

112. Remove Duplicates from Sorted List 快慢指针

记得一直往后移动

96. Partition List

建立新的两个linked list 一个存大于的一个存小的。注意最后队尾一定要tail.next = null 否则可能残留。
=> 只建一个list

35. Reverse Linked List

搞清关系就好了,画图

170. Rotate List

  1. 注意关系
  2. count链表长度减少计算

106. Convert Sorted List to Binary Search Tree

特别巧妙的一个方式,dfs将时间复杂度降低到了O(n)

105. Copy List with Random Pointer

"""
Definition for singly-linked list with a random pointer.
class RandomListNode:
    def __init__(self, x):
        self.label = x
        self.next = None
        self.random = None
"""


class Solution:
    # @param head: A RandomListNode
    # @return: A RandomListNode
    def copyRandomList(self, head):
        # write your code here
        dic = collections.defaultdict(lambda: RandomListNode(0))
        dic[None] = None
        pos = head
        while(pos):
            dic[pos].label = pos.label
            dic[pos].next = dic[pos.next]
            dic[pos].random = dic[pos.random]
            pos = pos.next
        return dic[head]

102. Linked List Cycle

快慢指针

99. Reorder List

翻转加插空

98. Sort List

7. Binary Tree

97. Maximum Depth of Binary Tree DFS

1+ max(左子树,右子树) if root else 0
特别简洁

93. Balanced Binary Tree

上面的升级版,用-1表示非的情况

85. Insert Node in a Binary Search Tree

不要求平衡,所以可以直接插入

69. Binary Tree Level Order Traversal

同样是是dfs增加了一个h

66. Binary Tree Preorder Traversal

preorder root -> left -> right
inorder left->root-> right
postorder left -> right -> root

95. Validate Binary Search Tree inorder

https://www.jiuzhang.com/solution/validate-binary-search-tree/#tag-highlight-lang-python

    def isValidBST(self, root):
        self.lastVal = None
        self.isBST = True
        self.validate(root)
        return self.isBST

    def validate(self, root):
        if root is None:
            return
        self.validate(root.left)
        if self.lastVal is not None and self.lastVal >= root.val:
            self.isBST = False
            return
        self.lastVal = root.val
        self.validate(root.right)

73. Construct Binary Tree from Preorder and Inorder Traversal

中序是按根结点的顺序,所以可以用来分割前序。

11. Search Range in Binary Search Tree

前序遍历

7. Serialize and Deserialize Binary Tree

中序遍历,不存在的点用#代替

class Solution:
        
    def serialize(self, root):
        def doit(node):
            if node:
                vals.append(str(node.val))
                doit(node.left)
                doit(node.right)
            else:
                vals.append('#')
        vals = []
        doit(root)
        print(' '.join(vals))
        return ' '.join(vals)

    def deserialize(self, data):
        def doit():
            val = next(vals)
            if val == '#':
                return None
            node = TreeNode(int(val))
            node.left = doit()
            node.right = doit()
            return node
        vals = iter(data.split())
        return doit()

87. Remove Node in Binary Search Tree

找到左子树的最后一个结点作为根结点
左子树的处理方式为递归

8. Search & Recursion

152. Combinations

二叉树,每个数字放与不放

135. Combination Sum

放与不放
因为可重复,所以切记考虑

127. Topological Sorting 队列

统计入度,用字典存
当入度为0时,可以作为起始点

33. N-Queens DFS/BFS

我自己喜欢用bfs+队列

18. Subsets II

DFS
也可以看数字找规律

17. Subsets

上面的建议版本,不考虑重复

16. Permutations II

可以用非递归/递归的bfs和dfs来做

15. Permutations

没有重复的数,更简单

9 Dynamic Programming

115. Unique Paths II

动态规划,有障碍处置为0

111. Climbing Stairs

经典动态规划题

41. Maximum Subarray

当前面的子数列和大于0时,值得相加,否则重新开始一个子数列

191. Maximum Product Subarray

记录当前位置下,最大和最小(负数的绝对值最大)的情况

119. Edit Distance

分析好增删改分别对应dp的不同状态即可

118. Distinct Subsequences

分析具体过程,可以得到,t从左到右,依次找,看是否在左边找完的情况下,在右边找到剩下的部分

109. Triangle

从下往上分析更好,O(n)空间复杂度

107. Word Break

和118分析方式类似

92. Backpack

动态规划的转移方程:

for j in range(1, m + 1):
	if j >= A[i - 1]: #背包比这个物品大,则不放这个物品,是否可以达到j或者放了能否达到j
		f[i][j] = f[i - 1][j] or f[i - 1][j - A[i - 1]]
	else: #不放是否能达到j
		f[i][j] = f[i - 1][j]

10. Data Structure

124. Longest Consecutive Sequence

利用hash表,得到它两边的的元素,更新它们的边界。

104. Merge K Sorted Lists

使用heapq构建一个头结点的最小堆,保证最小堆中每个元素均为各个数组中最小的数

40. Implement Queue by Two Stacks

stack1 压入,则先将stack中所有的数pop+push到stack2,再pop+push到stack1

12. Min Stack

记录当前最小值(不需要pop出最小值

4. Ugly Number II

保证比之后小的数都压入了res中
三个游标分别表示res中2,3,5分别乘到哪一个数了

面对此类最小的问题,又是顺序,可以考虑多个游标进行比较

132. Word Search II

Tire构造

trie = {} #4339361904
for w in words:
    #print(trie)
    t = trie  #4339361904
    #print(id(t),id(trie))
    for c in w:
        if c not in t: #不存在相同前缀的单词已在字典树
            t[c] = {} #t:4339361904 #t[c]: 4339361976
        print(id(t),t)
        t = t[c] #t:4339361976
        print(id(t),t)
        print("*****")
    t['#'] = '#'
print(id(trie))

深度优先
记得每个分支之间互不影响所以要把状态改回来

122. Largest Rectangle in Histogram

单调栈
栈记录着index都是单调的

class Solution:
    """
    @param height: A list of integer
    @return: The area of largest rectangle in the histogram
    """
    def largestRectangleArea(self, height):
        # write your code here
        l = len(height)
        if l == 0:
            return 0
        max_size = 0
        monos = []
        res = [0 for _ in range(l)]
        for i in range(l):
            while(len(monos) != 0 and height[monos[-1]] >= height[i]):
                max_size = max((i - monos[-1] + res[monos[-1]]) * height[monos[-1]], max_size)  # 可以它为顶的最大矩形的æƒ
况
                res[i] = i - monos[-1] + res[monos[-1]] #可以它为顶的最大矩形的æƒ
况
                monos.pop()
            monos.append(i)
            
        while(len(monos)):
            max_size = max((l - monos[-1] + res[monos[-1]])*height[monos[-1]],max_size)
            monos.pop()
            
        return max_size
        
        # 没考虑到想到相等的æƒ
况```


### 81. Find Median from Data Stream
最大堆和最小堆,一边大一边小
代码tricks很巧妙

```python
from heapq import *
class Solution:
    """
    @param nums: A list of integers
    @return: the median of numbers
    """
    def medianII(self, nums):
        # write your code here
        
        small, large, res = [], [], []
        for num in nums:
            heappush(small, -heappushpop(large, num))
            if len(large) < len(small):
                heappush(large, -heappop(small))
            if len(small):
                if len(large) == len(small):
                    res.append(-small[0])
                else:
                    res.append(large[0])
            else:
                res.append(num)
        return res
                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值