Question Bank

本贴最后更新于 271 天前,其中的信息可能已经事过境迁
  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 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    536 引用 • 672 回帖

相关帖子

回帖

欢迎来到这里!

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

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

推荐标签 标签

  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖 • 2 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 20 关注
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    386 引用 • 1226 回帖 • 593 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 702 关注
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    328 引用 • 1715 回帖 • 3 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 557 关注
  • 30Seconds

    📙 前端知识精选集,包含 HTML、CSS、JavaScript、React、Node、安全等方面,每天仅需 30 秒。

    • 精选常见面试题,帮助您准备下一次面试
    • 精选常见交互,帮助您拥有简洁酷炫的站点
    • 精选有用的 React 片段,帮助你获取最佳实践
    • 精选常见代码集,帮助您提高打码效率
    • 整理前端界的最新资讯,邀您一同探索新世界
    488 引用 • 383 回帖 • 1 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    19 引用 • 23 回帖 • 702 关注
  • 笔记

    好记性不如烂笔头。

    306 引用 • 782 回帖
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    26 引用 • 85 回帖
  • NetBeans

    NetBeans 是一个始于 1997 年的 Xelfi 计划,本身是捷克布拉格查理大学的数学及物理学院的学生计划。此计划延伸而成立了一家公司进而发展这个商用版本的 NetBeans IDE,直到 1999 年 Sun 买下此公司。Sun 于次年(2000 年)六月将 NetBeans IDE 开源,直到现在 NetBeans 的社群依然持续增长。

    78 引用 • 102 回帖 • 645 关注
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 53 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    20147 引用 • 77683 回帖 • 1 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 648 关注
  • React

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

    192 引用 • 291 回帖 • 430 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    109 引用 • 54 回帖 • 3 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    83 引用 • 165 回帖 • 5 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 2 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    75 引用 • 258 回帖 • 631 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 529 关注
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    96 引用 • 330 回帖
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 705 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖 • 3 关注
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 1 关注
  • 职场

    找到自己的位置,萌新烦恼少。

    126 引用 • 1699 回帖
  • TextBundle

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

    1 引用 • 2 回帖 • 40 关注