过关斩将编程题

1.70-爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

python 复制代码
# 空间O(1)
# 时间O(n)
class Solution:
    def climbStairs(self, n:int) -> int:
        if n==1 or n==2: return n
        a, b, temp = 1, 2, 0
        for i in range(3, n+1):
            temp = a + b
            a = b
            b = temp
        return temp 


# 递推空间O(n)
# 时间O(n)

class Solution:
    def climbStairs(self, n:int) -> int:
        stairs = [0] * (n+1)
        stairs[0] = stairs[1] = 1
        for i in range(2, n+1):
            stairs[i] = stairs[i - 1] + stairs[i - 2]
        return stairs[-1]

2. 10-II. 青蛙跳台阶问题

一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

python 复制代码
# 斐波那契数列

class Solution:
    def numWays(self, n: int) -> int:
        a, b = 1, 1
        mod = 1000000007
        for _ in range(n):
            a, b = b, a + b
        return int(a % mod)
        

class Solution:
    def numWays(self, n: int) -> int:
        if n == 0 or n == 1: return 1
        a, b = 1, 1
        mod = 1000000007
        for i in range(2, n+1, 1):
            a, b = b, a + b
        return int(b % mod)

3. 3-无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

python 复制代码
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if not s: return 0
        left = 0
        lookup = set()
        n = len(s)
        max_len = 0
        cur_len = 0
        for i in range(n):
            cur_len += 1
            while s[i] in lookup:
                lookup.remove(s[left])
                left += 1
                cur_len -= 1
            
            if cur_len > max_len:
                max_len = cur_len
            lookup.add(s[i])

        return max_len


class Solution:
    def lengthOfLongestSubstring(self, s:str) -> int:
        dic, res, i = {}, 0, -1
        for j in range(len(s)):
            if s[j] in dic:
                i = max(i, dic[s[j]])
            dic[s[j]] = j
            res = max(res, j - i)
        return res

4. 146-LRU 缓存

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。实现

LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量
    capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字
    key 存在于缓存中,则返回关键字的值,否则返回
    -1 。
  • void put(int key, int value) 如果关键字
    key 已经存在,则变更其数据值
    value ;如果不存在,则向缓存中插入该组
    key-value 。如果插入操作导致关键字数量超过
    capacity ,则应该 逐出 最久未使用的关键字。
    函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
python 复制代码
## 需要使用一个哈希表和一个双向链表来实现
哈希时间复杂度O(1)、链表O(1),空间复杂度O(capacity)

class LRUCache(collections.OrderedDict):

    def __init__(self, capacity: int):
        super().__init__()
        self.capacity = capacity

    def get(self, key: int) -> int:
        if key not in self:
            return -1
        self.move_to_end(key)
        return self[key]

    def put(self, key: int, value: int) -> None:
        if key in self:
            self.move_to_end(key)
        self[key] = value
        if len(self) > self.capacity:
            self.popitem(last=False)


## 不适用调用
class LRUCache:

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.hashmap = {}
        self.head = ListNode()
        self.tail = ListNode()
        self.head.next = self.tail
        self.tail.prev = self.head
    
    def move_node_to_tail(self, key):
        node = self.hashmap[key]
        node.prev.next = node.next
        node.next.prev = node.prev

        node.prev = self.tail.prev
        node.next = self.tail
        self.tail.prev.next = node
        self.tail.prev = node

    def get(self, key: int) -> int:
        if key in self.hashmap:
            self.move_node_to_tail(key)
        res = self.hashmap.get(key, -1)
        if res == -1: 
            return res
        else:
            return res.value


    def put(self, key: int, value: int) -> None:
        if key in self.hashmap:
            self.hashmap[key].value = value
            self.move_node_to_tail(key)
        
        else:
            if len(self.hashmap) == self.capacity:
                # 去掉哈希表对应项
                self.hashmap.pop(self.head.next.key)
                self.head.next = self.head.next.next
                self.head.next.prev = self.head
            
            new = ListNode(key, value)
            self.hashmap[key] = new
            new.prev = self.tail.prev
            new.next = self.tail
            self.tail.prev.next = new
            self.tail.prev = new



class ListNode:
    def __init__(self, key=None, value=None):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None
    


# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

5. 648-单词替换

在英语中,我们有一个叫做 词根(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词------我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。

现在,给定一个由许多词根组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。

你需要输出替换之后的句子。

python 复制代码
时间复杂度。构建字典树消耗 O(d) 时间,字典数的搜索的复杂度为O(1),因此整体的时间复度为O(d)
空间复杂度。哈希集合的占用空间为O(d),分割setence占用空间为O(n),整体的空间复杂度为O(d+n)

class Solution:
    def replaceWords(self, dictionary: List[str], sentence: str) -> str:
        #利用嵌套字典构建字典树
        trie = {}
        for word in dictionary:
            cur = trie
            for c in word:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            # "#"作为一个word的终止符
            cur['#'] = {}
        print(trie)
        words = sentence.split(' ')
        for i, word in enumerate(words):
            cur = trie
            for j, c in enumerate(word):
                if '#' in cur:
                    words[i] = word[:j]
                    break
                if c not in cur:
                    break
                cur = cur[c]

        return ' '.join(words)



if __name__ == '__main__':
    dictionary = ["cat","ct","rat"]
    sentence = "the cattle was cty rattled by the battery"
    # 输出:"the cat was rat by the bat"

    # dictionary = ["a","b","c"]
    # sentence = "aadsfasf absbs bbab cadsfafs"
    # 输出:"a a b c"

    res = Solution()
    s = res.replaceWords(dictionary, sentence)
    print(s)

6. 662- 二叉树最大宽度

两种解法,BFS和DFS。

关键点:结构同满二叉树。

1.对于满二叉树,从根节点开始可以对节点编号1,2,...,某节点p的左子节点的序号为2p,右子节点的序号为2p+1;

2.若令根节点的序号p为0,且左子节点的序号为2p,右子节点的序号为2p+1,则每层节点中,节点的序号即代表节点在这一层中的位置索引。

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

时间复杂度:O(N),每个节点访问一次; 空间复杂度:O(N),取决于队列;
class Solution:
    def widthOfBinaryTree(self, root: Optional[TreeNode]) -> int:
        # BFS,队列中记录每个节点的root,pos,按层更新max_width
        if not root:
            return 0
        max_width = 0
        queue = [(root, 0)]
        while queue:
            width = queue[-1][1] - queue[0][1] + 1
            if max_width < width:
                max_width = width
            
            for _ in range(len(queue)):
                node, pos = queue.pop(0)
                if node.left:
                    queue.append((node.left, pos*2))
                if node.right:
                    queue.append((node.right, pos*2 + 1))
        return max_width

时间复杂度:O(N),每个节点访问一次; 空间复杂度:O(N),递归栈、字典开销;
       # DFS dfs更新最大宽度,用字典记录每层的左侧节点pos,递归时传递当前遍历到的root的pos
        def dfs(root, pos=0, level=0):
            if not root:
                return
            dic.setdefault(level, pos)
            self.max_width = max(self.max_width, pos - dic[level] + 1)
            dfs(root.left, pos*2, level + 1)
            dfs(root.right, pos*2 + 1, level + 1)

            self.max_width = 0
            dic = {}
            dfs(root)
        return self.max_width

欢迎关注交流与指正!

相关推荐
老歌老听老掉牙4 分钟前
Matplotlib Pyplot 数据可视化完全指南
python·信息可视化·matplotlib
Sunhen_Qiletian7 分钟前
《Python开发之语言基础》第六集:操作文件
前端·数据库·python
珑墨8 分钟前
【唯一随机数】如何用JavaScript的Set生成唯一的随机数?
开发语言·前端·javascript·ecmascript
Python编程学习圈12 分钟前
Python真的要一统天下了?
python
周杰伦fans18 分钟前
C# - Task 是什么?想象一下你在餐厅点餐
服务器·开发语言·c#
芳草萋萋鹦鹉洲哦22 分钟前
【tauri+rust】App会加载白屏,有时显示在左上角显示一小块,如何优化
开发语言·后端·rust
前端世界24 分钟前
float 还是 double?用储罐体积计算带你看懂 C 语言浮点数的真实世界坑
java·c语言·开发语言
豐儀麟阁贵26 分钟前
8.5在方法中抛出异常
java·开发语言·前端·算法
Hacker_Oldv36 分钟前
Python技能进阶:探索Selenium库,实现网页自动化测试与爬虫
自动化测试·软件测试·爬虫·python·selenium·职场和发展
Bro_cat1 小时前
Java基础
java·开发语言·面试