跳到正文

全排列与已用集合

55 分钟

全排列与已用集合

先别猜算法,先把问题说清楚

今天只解决一个具体任务:输出无重复数组的所有排列。。上一节《决策树与撤销不变量》已经产出一个可检查的状态或边界;今天不要清零重来,要把它带进《全排列与已用集合》。 你先复述输入是什么、输出必须唯一满足什么、哪些输入合法、出现并列或无解怎样返回、能否修改输入、下标从零还是从一开始。若这些话写不完整,样例跑对也不能证明程序做的是同一道题。本节案例编号是 cs-08-leetcode/u09/l02/全排列与已用集合/contract,后续代码、证明和测试都引用同一份契约。

为什么在这里学习它

本章要解决的是:画清决策树,保证每个解恰好到达一次,再用上界、排序和对称性安全剪枝。。本节不是孤立模板,它承担的连接是:无重复排列完成后,下一课处理输入本身含重复值。 我们会先保留一个显然正确但可能很慢的方案,再圈出重复工作;只有能指出被删掉的工作为何不影响答案,优化才有依据。面试时真正有价值的不是迅速喊出算法名,而是让对方看到你怎样从限制推出模型。

核心不变量和复杂度必须单独写

把这句话拆成三层。第一层是状态语义:变量、区间、栈、队列或 dp 项究竟代表哪一段已经完成的工作。第二层是保持性:本轮读入一个新元素后,怎样更新仍使语义成立。第三层是终止性:循环或递归结束时,这个语义为什么恰好推出题目要求的答案。复杂度要从元素进入、退出、比较或转移的次数累加,不能凭印象写 O(n)。

跟我从暴力基线走到优化

先为“输出无重复数组的所有排列。”写一个覆盖全部候选的基线,并用两三个最小输入说明它没有漏解。接着在纸上标出哪些区间、比较或子问题被反复计算。现在引入本节状态:每处理一步,都用一句话重述“已经完成什么、仍未知什么”。若要移动指针、弹栈、丢弃搜索区间或覆盖 dp,必须证明被丢掉的候选不可能成为更优答案。最后才写代码,并把每个分支对应回契约中的一种情况。

课堂上至少手推三组:普通输入用于看主流程;最小或空输入用于看初始化;带重复、并列、负数、极值或不可达状态的输入用于看边界。每轮写出关键状态,而不是只写最后答案。这样当程序错时,你能判断错误来自规格、模型、不变量、实现还是测试,而不是盲目换模板。(推导锚:cs-08-leetcode/u09/l02/全排列与已用集合/trace。)

一个完整例题怎样讲给人听

围绕“输出无重复数组的所有排列。”,先给一个小输入,逐步列出状态表或指针位置;再解释为什么下一步只有当前动作安全。随后把规模扩大到约束上界,按“状态数 × 每状态工作量”核算时间,并把数组、哈希、递归栈或队列占用逐项计入空间。若存在两种方案,要比较它们依赖的前提,而不是一律选择渐近阶更低者:排序会改变顺序,哈希有额外空间,递归有栈深,位运算受数值范围限制。

今天最重要的失败边界

请故意构造这个失败:按值标记会混淆相同值的不同下标;空数组是否有一个空排列需定义。。先预测错误程序第一次在哪一轮偏离,再运行最小反例验证。只说“注意边界”不给分;必须写出输入、错误状态、错误输出和违反的契约。若修复需要新增特判,反问能否改写初始化或区间语义,让空输入、首尾元素和普通输入走同一条逻辑。(反例锚:cs-08-leetcode/u09/l02/全排列与已用集合/counterexample。)

在线编程题怎样严格验收

本课绑定的代码题使用真实 Python 3 标准输入输出,不是伪代码。先在编辑器中写可运行基线,再提交优化版。基础任务至少六组、标准任务至少八组、挑战任务至少十组测试,覆盖普通、最小、空或单元素、重复/并列、极值、不可达以及复杂度压力。判题通过只证明这些可观察输入输出满足契约;你还要在题解里说明不变量、复杂度和未覆盖风险。

随课四题怎么做

单选题检查哪一种推理链成立;多选题同时验收规格、不变量、复杂度和反例,漏选或多选均错;状态计算题要求把简化操作次数算出来并说明模型;证明题按十分量表评分:契约与基线2分,不变量与保持性3分,终止和正确性2分,复杂度1分,失败边界与测试2分。只贴最终代码、只写算法名或只报复杂度不能证明已经学会。

下课前闭卷交付

不看正文,用五分钟完成一页题解:一句话契约;一个暴力基线;状态语义;初始化—保持—终止证明;时间和空间来源;“按值标记会混淆相同值的不同下标;空数组是否有一个空排列需定义。”的最小反例;六到十组测试分类;最后口述如何完成“输出无重复数组的所有排列。”。下一节《排序去重与同层剪枝》会直接使用今天留下的状态、反例或复杂度结论。 如果其中任何一项只能靠背诵恢复,就回到对应代码行重新手推。(闭环锚:cs-08-leetcode/u09/l02/全排列与已用集合/handoff。)

Practice

本课练习

8

先独立作答再提交;编程题会在隔离沙箱中真实编译、运行并对拍。

1单选推理:全排列与已用集合 4 积分
本科 · 入门

任务是“输出无重复数组的所有排列。”。哪条解题路线可复核?

登录 后答题可以领积分
2多选证据:全排列与已用集合 4 积分
本科 · 基础

验收《全排列与已用集合》应同时提交哪些材料?(漏选、多选均错。)

多选题:必须选全正确项,漏选或多选均不得分。

登录 后答题可以领积分
3状态计算:全排列与已用集合 4 积分
本科 · 基础

在《全排列与已用集合》中,若每个元素恰好完成一次主处理,输入规模 n=69 时主处理次数是多少? 先写采用的计数模型,并说明它为何只是一种上界估算。

登录 后答题可以领积分
4严格证明:全排列与已用集合 4 积分
本科 · 挑战

本题专题为《全排列与已用集合》。围绕“输出无重复数组的所有排列。”写完整题解:契约、暴力基线、状态语义、初始化—保持—终止证明、时间/空间来源、针对“按值标记会混淆相同值的不同下标;空数组是否有一个空排列需定义。”的最小反例和分层测试。只贴代码不得分。

登录 后答题可以领积分
5在线编程:无重复全排列
本科 · 入门代码题

输出所有排列并保持确定顺序。 输入:第一行n,第二行n个互异整数。 输出:第一行排列数,随后按输入次序的itertools字典顺序输出。 约束:1≤n≤8。 使用 Python 3 从标准输入读取,向标准输出写出唯一规定结果;不得读取文件或网络。 使用 Python 3 标准输入输出;不得使用第三方包。必须覆盖题面边界,不能只针对样例。

5 积分进入编程工作台 →
6在线编程:折半搜索最接近目标子序列和
本科 · 挑战代码题

枚举两半子集和并二分组合。 输入:第一行n、target,第二行数组。 输出:输出与target绝对差最小的子序列和;并列取较小和。 约束:1≤n≤36,值在64位范围。 使用 Python 3 从标准输入读取,向标准输出写出唯一规定结果;不得读取文件或网络。 使用 Python 3 标准输入输出;不得使用第三方包。必须覆盖题面边界,不能只针对样例。

6 积分进入编程工作台 →
7U09 独立题 02:全排列与已用集合 4 积分
本科 · 挑战

验收《全排列与已用集合》需要哪些证据?

多选题:必须选全正确项,漏选或多选均不得分。

登录 后答题可以领积分
8U09 独立题 09:全排列与已用集合 4 积分
本科 · 挑战

任务是“输出无重复数组的所有排列。”。哪条路线足以形成正确性证据?

登录 后答题可以领积分