Question Bank

本贴最后更新于 395 天前,其中的信息可能已经事过境迁
  1. ⚙ Question Template1
  2. 📄 [975] 奇偶跳2
  3. 📄 [1155] 掷骰子等于目标和的方法数5
  4. 📄 [1726] 同积元组6
  5. 📄 [2530] 执行 K 次操作后的最大分数7


  1. Question Template

    [id] Question Name

    • address

      question address

    • tags

      ​#leetcode#​

    • solution explain

    • solution code

      • Python3

        
        

  2. [975] 奇偶跳

    • address

      [975] 奇偶跳

    • tags

      ​#leetcode#​ #alg/动态规划#​ ​#alg/单调栈#​

    • solution explain

      在给定的数组中,每个位置使用奇数跳跃或者偶数跳跃,落点都是可以唯一确定的。确定了在每个位点奇偶跳的落点,即可判断从每个点能否最终到达末尾。

      奇数跳,只不过是在后续大于等于自己的元素中找值最接近的位置;
      反之偶数跳,是在小于等于自己的元素中找最接近自己的元素。

      • 单调栈解法

        统计在 i​点的奇数跳落点时:

        将原始数组 A​的索引按位置的数值从小到大进行排序。即 B = sorted(range(N), key = lambda i: A[i])

        这样就可以知道每个位置与之数值最接近的值(A[B[1]]与之最接近的值是 A[B[2]]),但是不能这样这样粗暴认为 A[B[n+1]]就是 A[B[i]]的奇数跳落点坐标,因为 B[n+1]和 B[n]还必须满足 B[n+1] > B[n],即索引位置关系。

        因为 A[B[n]]这个数组已经是升序,于是我们就可以总结:“==在 B 数组中 B[n]之后首个大于 B[n]的值 B[m]即为 A[B[n]]的奇数跳落点 A 坐标 A[B[m]]==”(细细品~) 相当于在 B 数组中寻找递减序列

        使用一个单调栈即可实现,遍历 B,保证栈内元素由低至顶递减,当新元素 Y 大于栈顶元素时,弹出栈顶 X,即 A 数组中索引为 X 的点奇数跳落点索引为 Y,遍历完成后仍然在栈中的元素,表明在 A 数组中这些索引位置处无法进行奇数跳,落点记为 None。详见 Python3 - 单调栈1make

        偶数跳同理,只需将元素取负即可(小于等于并最接近自己的元素,取负后成为大于等于并最接近自己)。

      在奇偶数跳跃落点两个数组的基础上即可求出 DP 数组,dp[i][0]​表示能否从 i 处通过偶数跳最终到达终点,dp[i][1]​表示能否从 i 处通过奇数跳最终到达终点,且 dp[len-1][0] = dp[len-1][1] = 1​,从末尾往前推导即可完善整个 DP 数组,规则为:

      1. 如果 i 处能进行偶数跳(即 even[i] is not None),此处能否偶数跳最终最终到达终点取决于跳跃落点处能否通过奇数跳并最终到达终点(即 dp[i][0] = dp[even[i]][1]​)
      2. 奇数跳与上同理。

      因为起始跳跃为奇数跳,对 dp[][1]​进行求和即为题解。

      • TreeMap​解法

        单调栈解法1中我们所做的事情 TreeMap​提供了 API:lowerKey(v)​和 higherKey(v)​,即为略小于 v 的值,略大于 v 的值。

    • solution code

      • Python3 - 单调栈

        class Solution(object):
            def oddEvenJumps(self, A):
                N = len(A)
        
                def make(B):
                    ans = [None] * N
                    stack = []  # invariant: stack is decreasing
                    for i in B:
                        while stack and i > stack[-1]:
                            ans[stack.pop()] = i
                        stack.append(i)
                    return ans
        
                B = sorted(range(N), key = lambda i: A[i])
                oddnext = make(B)
                B.sort(key = lambda i: -A[i])
                evennext = make(B)
        
                odd = [False] * N
                even = [False] * N
                odd[N-1] = even[N-1] = True
        
                for i in range(N-2, -1, -1):
                    if oddnext[i] is not None:
                        odd[i] = even[oddnext[i]]
                    if evennext[i] is not None:
                        even[i] = odd[evennext[i]]
        
                return sum(odd)
        
        作者:LeetCode
        链接:https://leetcode.cn/problems/odd-even-jump/solutions/
        来源:力扣(LeetCode)
        著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
        
      • Java - TreeMap 解法

        class Solution {
            public int oddEvenJumps(int[] A) {
                int N = A.length;
                if (N <= 1) return N;
                boolean[] odd = new boolean[N];
                boolean[] even = new boolean[N];
                odd[N-1] = even[N-1] = true;
        
                TreeMap<Integer, Integer> vals = new TreeMap();
                vals.put(A[N-1], N-1);
                for (int i = N-2; i >= 0; --i) {
                    int v = A[i];
                    if (vals.containsKey(v)) {
                        odd[i] = even[vals.get(v)];
                        even[i] = odd[vals.get(v)];
                    } else {
                        Integer lower = vals.lowerKey(v);
                        Integer higher = vals.higherKey(v);
        
                        if (lower != null)
                            even[i] = odd[vals.get(lower)];
                        if (higher != null) {
                            odd[i] = even[vals.get(higher)];
                        }
                    }
                    vals.put(v, i);
                }
        
                int ans = 0;
                for (boolean b: odd)
                    if (b) ans++;
                return ans;
            }
        }
        
        作者:LeetCode
        链接:https://leetcode.cn/problems/odd-even-jump/solutions/
        来源:力扣(LeetCode)
        著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
        
    • Python3 - 单调栈
    class Solution(object):
        def oddEvenJumps(self, A):
            N = len(A)
    
            def make(B):
                ans = [None] * N
                stack = []  # invariant: stack is decreasing
                for i in B:
                    while stack and i > stack[-1]:
                        ans[stack.pop()] = i
                    stack.append(i)
                return ans
    
            B = sorted(range(N), key = lambda i: A[i])
            oddnext = make(B)
            B.sort(key = lambda i: -A[i])
            evennext = make(B)
    
            odd = [False] * N
            even = [False] * N
            odd[N-1] = even[N-1] = True
    
            for i in range(N-2, -1, -1):
                if oddnext[i] is not None:
                    odd[i] = even[oddnext[i]]
                if evennext[i] is not None:
                    even[i] = odd[evennext[i]]
    
            return sum(odd)
    
    作者:LeetCode
    链接:https://leetcode.cn/problems/odd-even-jump/solutions/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    
    • 单调栈解法

    统计在 i​点的奇数跳落点时:

    将原始数组 A​的索引按位置的数值从小到大进行排序。即 B = sorted(range(N), key = lambda i: A[i])

    这样就可以知道每个位置与之数值最接近的值(A[B[1]]与之最接近的值是 A[B[2]]),但是不能这样这样粗暴认为 A[B[n+1]]就是 A[B[i]]的奇数跳落点坐标,因为 B[n+1]和 B[n]还必须满足 B[n+1] > B[n],即索引位置关系。

    因为 A[B[n]]这个数组已经是升序,于是我们就可以总结:“==在 B 数组中 B[n]之后首个大于 B[n]的值 B[m]即为 A[B[n]]的奇数跳落点 A 坐标 A[B[m]]==”(细细品~) 相当于在 B 数组中寻找递减序列

    使用一个单调栈即可实现,遍历 B,保证栈内元素由低至顶递减,当新元素 Y 大于栈顶元素时,弹出栈顶 X,即 A 数组中索引为 X 的点奇数跳落点索引为 Y,遍历完成后仍然在栈中的元素,表明在 A 数组中这些索引位置处无法进行奇数跳,落点记为 None。详见 Python3 - 单调栈1make

    偶数跳同理,只需将元素取负即可(小于等于并最接近自己的元素,取负后成为大于等于并最接近自己)。

  3. [1155] 掷骰子等于目标和的方法数

    • address

      [1155] 掷骰子等于目标和的方法数

    • tags

      ​#leetcode#​ ​#alg/动态规划#​

    • solution explain

      🥰 很经典的动态规划题

      首先按题意 n​个 k​面骰子一共能产生k^n种结果,要从这些结果中筛选出结果为 target​的结果数量。

      k​可以视为常量,利用动态规划思想拆分问题:

      n 个骰子能组合出 target 的结果数量 = n-1 个骰子能组合出 target - 1 的结果数量(假设第 n 个骰子掷出点数为 1) + ... + n-1 个骰子能组合出 target - k 的结果数量(假设第 n 个骰子掷出点数为 k)

      这样转换公式就显而易见了:f(n, target) = \sum_{pick=1}^k f(n-1, target-pick)

      因为条件限制了 1 <= n,k <= 30​,则初始状态就是f(1, 1..target),当我们只有一个骰子时,所有小于等于**k**​的 target, 其结果都是 1,反之则为 0

      f(1, target) = \begin{cases} 1 &\text{if } target \leq k \\ 0 &\text{if } target \gt k\end{cases}

      这样从上直下,就可以推算出整个 dp 数组,dp[n][target] = f(n, target) 即为所求

    • solution code

      • Python3

        class Solution:
            def numRollsToTarget(self, n: int, k: int, target: int) -> int:
                dp = [[0] * (target + 1) for _ in range(n + 1)]
                for i in range(1, target + 1):
                    if k >= i:
                        dp[1][i] = 1
        
                for cnt in range(2, n + 1):
                    for sum in range(1, target + 1):
                        for pick in range(1, k + 1):
                            if sum > pick:
                                dp[cnt][sum] += dp[cnt - 1][sum - pick]
                                dp[cnt][sum] %= (10 ** 9 + 7)
        
                return dp[-1][-1]
        

        Tips: 在确定了 target 和 k 之后,可以通过大小关系对循环次数进行缩减,甚至可以对 dp 数组进行压缩,以优化空间占用和运行时间。

  4. [1726] 同积元组

    • address

      [1726] 同积元组

    • tags

      ​#leetcode#​ #alg/哈希表#​

    • solution explain

      在所给的数组中均为不同的正整数,任意 4 个符合要求的数字,通过排列组合即可形成 8 个元组。

      统计数组中所有的乘积(共 len(nums) * (len(nums) - 1)​个乘积),这些乘积结果中必然有相同的,那么即为一组题解。

      针对每一个乘积结果,统计数对个数,即可得出 a * b = c * d = product​的题解数:

      例如有`n`​个数对乘积均为`product`​,那么从`n`​个数对中任意取出两个即可组成一个题解,共有$C_n^2$种取法即$\frac{n(n - 1)}{2}$  
      

      将题解个数 * 8 即为最终元组个数。

    • solution code

      • Python3

        class Solution:
            def tupleSameProduct(self, nums: List[int]) -> int:
                res = 0
                productCount: dict = {}
                for i in range(len(nums)):
                    for j in range(i + 1, len(nums)):
                        product = nums[i] * nums[j]
                        productCount[product] = productCount.get(product, 0) + 1
                for _, cnt in productCount.items():
                    res += int((cnt * (cnt - 1)) / 2)
                return res * 8
        

  5. [2530] 执行 K 次操作后的最大分数

    • address

      [2530] 执行 K 次操作后的最大分数

    • tags

      ​#leetcode#​​​ #alg/堆(优先队列)#​​​ #alg/贪心#​​​

    • solution explain

      看到“最”即联想贪心算法,每次都从待选列表(nums​)中取出最大的元素即为目标实现。

      Q: 每次元素变化后如何快速从其中找到最值元素?

      A: 大/小根堆(优先队列)

    • solution code

      • Python3

        from heapq import heapify, heappush, heappop
        
        class Solution:
            def maxKelements(self, nums: List[int], k: int) -> int:
                nums = [-num for num in nums]
                heapify(nums)
                res: int = 0
                for _ in range(k):
                    top = heappop(nums)
                    res += -top
                    heappush(nums, -((-top + 2) // 3))
                return res
        

        Python 中 heapify​​默认小根堆,通过对元素进行取反实现所需的“大根堆”,每次取出堆顶值 top​​,然后进行 (-top+2) // 3​​【等效 ceil(top / 3)​​】,将结果取负后重新 push 进堆中。

      • Java

        使用 PriorityQueue​作为堆的替代实现

  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    543 引用 • 672 回帖

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 529 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 177 关注
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    142 引用 • 442 回帖
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有计划重制上线。

    14 引用 • 257 回帖
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    125 引用 • 169 回帖
  • 导航

    各种网址链接、内容导航。

    40 引用 • 173 回帖
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 27 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 211 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 589 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖
  • 阿里云

    阿里云是阿里巴巴集团旗下公司,是全球领先的云计算及人工智能科技公司。提供云服务器、云数据库、云安全等云计算服务,以及大数据、人工智能服务、精准定制基于场景的行业解决方案。

    89 引用 • 345 回帖 • 1 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 16 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    5 引用 • 7 回帖 • 1 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 49 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 172 关注
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 699 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 385 关注
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 664 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    12 引用 • 54 回帖 • 62 关注
  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖
  • 快应用

    快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。

    15 引用 • 127 回帖 • 1 关注
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 724 关注
  • abitmean

    有点意思就行了

    29 关注
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 210 关注
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 633 关注