数据结构与算法笔记:字典序最大问题分析

拓扑排序 文章目录拓扑排序1. 算法分析1.1 特点分析1.2 使用场景2. 例题2.1 求出拓扑序2.1.1 一般拓扑序2.1.2 求出字典序最大/最小的拓扑序2.2 判断图中是否有环2.3 拓扑排序+dp2.3.1 求最短路\最长路2.3.2 求可达性 拓扑排序 1. 算法分析 1.1 特点分析     拓扑排序可以在线性的时间复杂度 O(n + m) 内完成求出拓扑序的操作,对象是有向无环图。 拓扑图的性质如下: 有向图才有拓扑序 有向无环图必定存在拓扑序 存在拓扑序 <=> 无环 有向无环图至少 阅读详情

字典序最大问题

问题描述

  • 给定一个1到n的排列(无序状态的),依次插入到栈中,在每时每刻都可以多次从栈中弹出栈顶
  • 问:应如何使得弹出栈顶的序列的字典序最大,并输出这个序列

问题分析

  • 什么是字典序
    • 比如两个序列:5,4,3,2,1和1,2,3,4,5
    • 这两个中第一个的字典序最大
    • 每个位置上的数字比其他序列上同一位置的数字要大
    • 比如:第一位置中5比1大,第二位置中4比2大这样
    • 即:字典序最大 = 从左向右看这个序列,每个数字都尽量大
  • 题目给定一个1到n的排列,每个数字只出现一次
  • 要使出栈的字典序最大,则第一个出栈的一定是n, 也就是序列中的最大值,同时n的入栈和出栈动作一定是连续的,不会被其他元素所干扰
  • 第二个出栈的会是谁呢?
    • 在n出栈之前,n前面的所有元素都一定在栈中,没有一个被弹出去,否则第一个弹出的位置就不会是n
    • 由于每次只能弹出栈顶,我们只需考虑栈顶的数字和n这个数字后面的元素中选一个最大值作为第二个出栈的候选者
  • 第三、第四等等以此类推
  • 总结一下,这个算法实现需要三个功能
    • 栈的基本操作
    • 连续一段(至末尾)序列最大值的查找
    • 判断谁是下一个出栈:当前栈顶与前一个出栈元素后面的元素中最大的那个

关键算法实现

1 ) 蛮力算法:算法复杂度为:O(n2)O(n^2)O(n2)

  • 每次花费O(n)的时间查找最大值
  • 一共进行了O(n)次
  • 算法复杂度为:O(n2)O(n^2)O(n2)
// n: 序列长度
// ele:序列数组,下标从0开始
// 返回值:返回字典序最大的出栈序列
vector<int> getResult(int n, int *ele) {
    vector<int> ans; // 动态数组,用于返回
    stack<int> s; // 用于存放索引的栈
    // 处理当前所有的元素
    for (int i = 0; i < n;) {
        int mx = 0; // 初始化最大值
        // 找到当前最大值(并非全局最大值,第一次循环的时候是全局最大值)
        for (int j = i; j < n; ++j) {
            mx = max(mx, ele[j]);
        }
        // 如果栈不空且栈顶元素较大,则将较大的栈顶弹出(满足字典序最大)
        if(!s.empty() && ele[s.top()] > mx) {
            ans.push_back(ele[s.top()]); // 将这个较大栈顶存入结果
            s.pop(); // 出栈
        } else {
            // 将最大值之外的元素全部压进去(因为最大值只有一个,所以用!=的方式处理除了最大值之外的所有元素)
            while(mx!=ele[i]) {
                s.push(i); // 入栈
                ++i; // i自增跳出while,重新执行外层循环
            }
            // 当前的i元素ele[i]就是最大值的时候,将这个最大值存入结果
            ans.push_back(ele[i]);
            ++i;
        }
    }
    // 当外面的元素全都没有了(该入栈的都入栈了),最后只能从栈中一个一个弹出来了,将剩余元素依次弹出,并存入最终结果
    while(!s.empty()) {
        ans.push_back(ele[s.top()]);
        s.pop();
    }
    return ans;
}

2 ) 线性算法:算法复杂度为:O(n)O(n)O(n)

  • 维护一个数组maxElement,表示位置i到位置n的最大值
    • maxElementi=max{maxElementi+1,elementi}maxElement_i = max\{ maxElement_{i+1}, element_i \}maxElementi​=max{maxElementi+1​,elementi​}
    • 算法开始之前做数据的预处理,时间复杂度为O(n)
  • 之后,算法查询O(n)次,每次花费O(1)的时间来查询最大值,结合之前预处理时间也是O(n), 所以总时间复杂度还是O(n)
  • 以空间换时间,妥妥的线性算法, 非常高效
// n: 序列长度
// ele:序列数组,下标从0开始
// 返回值:返回字典序最大的出栈序列
vector<int> getResult(int n, int *ele) {
    vector<int> ans; // 动态数组,用于返回
    stack<int> s; // 
    // ----- 数据预处理 开始 ----- //
    int *maxElement = new int[n](); // 定义一个存储所有元素的空间
    maxElement[n-1] = ele[n-1]; // 初始化最后一个元素,作为切入点
    // 批量处理其他元素,注意,此处是倒序,最大值的比较是当前元素和前一个最大值(序号较大的,因为是倒序循环)
    for(int i=n-2; i>=0; --i) {
        maxElement[i] = max(maxElement[i+1], ele[i]);
    }
    // ----- 数据预处理 结束 ----- //
    // 遍历当前所有的元素 O(n)
    for (int i = 0; i < n;) {
        int mx = maxElement[i]; // 初始化最大值
        
        // 如果栈不空且栈顶元素较大,则将较大的栈顶弹出(满足字典序最大)
        if(!s.empty() && ele[s.top()] > mx) {
            ans.push_back(ele[s.top()]); // 将这个较大栈顶存入结果
            s.pop(); // 出栈
        } else {
            // 将最大值之外的元素全部压进去(因为最大值只有一个,所以用!=的方式处理除了最大值之外的所有元素)
            while(mx!=ele[i]) {
                s.push(i); // 入栈
                ++i; // i自增跳出while,重新执行外层循环
            }
            // 当前的i元素ele[i]就是最大值的时候,将这个最大值存入结果
            ans.push_back(ele[i]);
            ++i;
        }
    }
    // 当外面的元素全都没有了(该入栈的都入栈了),最后只能从栈中一个一个弹出来了,将剩余元素依次弹出,并存入最终结果
    while(!s.empty()) {
        ans.push_back(ele[s.top()]);
        s.pop();
    }
    return ans;
}

3 ) 其他复杂度算法:O(nlogn)O(nlogn)O(nlogn)

  • 既然解决方案可以从O(n2) O(n)O(n^2) ~ O(n)O(n2) O(n), 那么O(nlogn)的复杂度也可以实现
  • 每一次查询只会花费O(logn)的时间,构建以及其他零散总时间也不会超过O(nlogn)
  • 可以参考:线段树,堆,平衡树来考虑,此处不再赘述
  • 具体替换的位置在下面,替换上上面的一些技术来做查询
    // 找到当前最大值(并非全局最大值,第一次循环的时候是全局最大值)
    for (int j = i; j < n; ++j) {
        mx = max(mx, ele[j]);
    }
    

通用的输入程序

int main() {
    int n;
    cin >> n;
    int *ele = new int[n](); // 输入的数组
    // 初始化
    for (int i = 0; i < n; ++i) {
        cin >> ele[i];
    }
    auto answer = getResult(n, ele);
    // 循环输出数组
    for (auto i: answer) {
        cout << i << " ";
    }
    cout << "\n";
    return 0;
}

测试数据

  • 给定输入序列
    • 5
    • 4 1 3 5 2
  • 输出序列:5 3 2 1 4

扩展

  • 当这个序列不是逐个排列给出,而是允许有重复元素,上述算法也可正常运行
(算法设计与分析)第一章算法概述-习题 我们以列变换优先,每一列都可作为第一列,然后再进行第一列与目标列进行比较,如果不相同,则进行行翻转,此后,第一列将固定下来;用后一个抽屉的小值减去上一个抽屉的大值,得到抽屉之间的间隙,最后取出最大的那个间隙(前提:易知最大间隙一定大于等于n个元素的平均距离,所以抽屉内的元素间隙一定不是最大间隙,最大间隙只能在抽屉间)根据数组中n个元素的相对大小,将他们放在这n-1个抽屉中,可能有的抽屉中为空值,可能有的抽屉中含有多个元素,并记录每一个抽屉的小值和大值。找出数组中的最小值和最大值。,都是常数阶,区别在于。 阅读详情

相关推荐

【数据结构与算法】之深入解析“三个无重叠子数组的最大和”的求解思路与算法示例

一、题目要求 给你一个整数数组 nums 和一个整数 k,找出三个长度为 k、互不重叠、且全部数字和(3 * k 项)最大的子数组,并返回这三个子数组。 以下标的数组形式返回结果,数组中的每一项分别指示每个子数组的起始位置(下标从 0 开始)。如果有多个结果,返回字典序最小的一个。 示例 1: 输入:nums = [1,2,1,2,6,7,5,1], k = 2 输出:[0,3,5] 解释:子数组 [1, 2], [2, 6], [7, 5] 对应的起始下标为 [0, 3, 5]。 也可以取 [2, 1

╰つ栺尖篴夢ゞ 1215

字典序最大子序列字符串

基本常识(字典序): 字典序比较大小的方式就是,从第一位逐位比较,如果这一位不相等,那么肯定有大小之分,大的就大,小的就小,如果相同,找下一位,和字符串长度没有关系,只有s1的全部字符都和s2的前strlen(s1)位都相等的情况,s2更长,所以更大 如:aaa&amp;gt;aa,abc&amp;gt;aaaa,ad&amp;gt;abcd 子序列的话,大概意思就是相对位置不变,每个字符可选可不选 比如abcdefg的...

别把暗恋当饭吃 4585

非递归全排列:字典序算法原理与C语言实现

在计算机算法中,全排列生成是组合数学与搜索算法的基础问题,递归实现直观但存在栈溢出风险,特别是在规模增大时容易崩溃。字典序算法通过“找分界点、交换、反转”三步,将排列生成转化为迭代式的序列演化,彻底摆脱递归调用栈的限制。这种非递归实现具备O(1)空间复杂度,输出天然有序,且是C++标准库next_permutation的基础,在排班调度、路径枚举、组合搜索等工程场景中具有极高的实用价值。本文基于C语言逐段拆解字典序非递归全排列的核心实现、性能对比与典型陷阱,帮助开发者避开递归爆栈的坑,掌握一种可直接落地的算

weixin_27061475的博客 166

如何理解: 使字符串中字典序最大的字符串尽可能小

那么,'aaa'、'aab'、'aac'、'aba'、'abb'、'abc'、'aca'、'acb'、'acc'、'baa'、'bab'、'bac'、'bba'、'bbb'、'bbc'、'bca'、'bcb'、'bcc'、'caa'、'cab'、'cac'、'cba'、'cbb'、'cbc'、'cca'、'ccb'、'ccc'都是可能的字符串。那么,'aa'、'ab'、'ac'、'ba'、'bb'、'bc'、'ca'、'cb'、'cc'都是可能的字符串。所以,'cc'就是我们要找的字符串。

DevangLic Blog 1316

全排列非递归算法:字典序法与堆算法详解及避坑指南

全排列是组合数学与算法设计中的基础问题,其递归实现因函数调用栈开销在资源受限环境下易引发栈溢出。非递归解法通过显式状态管理将递归转为迭代,核心原理包括字典序法的“下一个排列”状态转移与堆算法的最少交换策略。这类方法在嵌入式系统、大规模枚举及随机采样等场景中具有显著工程价值,能有效控制内存并提升稳定性。本文深入剖析字典序法与堆算法的实现细节、复杂度及性能对比,并总结排序遗漏、重复元素、引用陷阱等五大避坑经验,帮助开发者掌握递归转迭代的通用套路。

weixin_33404102的博客 84

从选卡到验证:CST仿真GPU加速全流程实战指南

本文详细介绍了CST仿真中GPU加速的全流程实战指南,从硬件选型到软件配置,再到性能验证和常见问题排查。通过对比专业卡与游戏卡的性能差异,提供硬件选型建议,并分享驱动安装、关键设置及CST软件配置的黄金法则,帮助用户显著提升仿真效率。

weixin_30650039的博客 394

1718. 构建字典序最大的可行序列-深度优先遍历+回溯法

一个序列 a 被认为比序列 b (两者长度相同)字典序更大的条件是: a 和 b 中第一个不一样的数字处,a 序列的数字比 b 序列的数字大。比方说,[0,1,9,0] 比 [0,1,5,6] 字典序更大,因为第一个不同的位置是第三个数字,且 9 比 5 大。解释:[2,3,2,1,3] 也是一个可行的序列,但是 [3,1,2,3,2] 是字典序最大的序列。请你返回满足上述条件中 字典序最大 的序列。输出:[5,3,1,4,3,5,2,4,2]输出:[3,1,2,3,2]

weixin_43327597的博客 419

edusrc挖掘思路

edusrc挖掘思路前言思路信息搜集系统账号常见漏洞实战分享1、确定目标,语法:site:xxxx.edu.cn2、账号密码组成我们知道了,谷歌语法查找工号3、爆破登录系统4、确定功能,抓具体的url5、添加单引号,报错,是mssql6、报数据库版本,到这一步就可以交了,已经是中危了后记 前言 一月份的时候偶然注意到edusrc,起初是抱着学习的心态去挖几个洞,可是后面发现有证书,而且还贼好看,于是我动了凡心,一顿操作也拿了几本,广西民大、山东理工、同济,未到的有浙大、上海理工,证书要求证书图片可以在我个人

qq_45414878的博客 2万+

牛客竞赛---字典序最大的字符串

对于在牛客竞赛中遇到的字典序最大的字符串,本以为可以使用dp来做,奈何一直想不到具体的操作,反而看到这样子的写法便记录下来了

gaoqiandr的博客 973

SAP成本控制范围配置全流程:从货币参数到标准层次(附2024最新SPRO路径)

本文详细拆解了SAP成本控制范围(Controlling Area)的完整配置流程,涵盖从货币与估价参数文件定义、参数文件分配到控制范围,再到成本中心标准层次创建等核心步骤。文章提供了2024年最新的SPRO导航路径和实战配置要点,帮助顾问构建稳健、可扩展的管理会计基础架构,并附有常见问题排查指南。

java5的博客 938

RocketMq面板访问异常 com.alibaba.fastjson.JSONException: not close json text, token : string

rocketmq JSONException: not close json text, token : string 问题解决

qq_21067307的博客 5573

算法-CodeTop(二)字典序最大最小

本文总结了字典序相关算法问题的解题思路,主要包括维护单调栈、合并数组和比较字典序三个核心方法 通过402、316、1081和321四个典型题目,详细讲解了如何利用贪心算法和单调栈处理字典序问题。关键点在于遍历时选择性保留或丢弃元素,保证字典序最优 文章提供了多种解法代码,包括数组模拟栈和双端队列实现,并重点解析了321题中pickMax、merge和greater三个核心方法的协同工作逻辑,这些方法组合使用可解决复杂字典序问题

LUCIAZZZ的博客 1015

【JESD79-5之】8 AC & DC 输入测量标准(AC & DC Input Measurement Levels)

时钟被驱动到DRAM,可以通过L/RDIMM模块的RCD来实现,也可以通过U/SODIMM模块的主机来实现(图184)。接收机DQS(脉冲)输入电压灵敏度测试提供了在没有码间干扰(ISI),抖动(Rj, Dj, DCD)和串扰噪声的情况下测试接收机对不同输入电压的灵敏度的方法。接收机数据输入电压灵敏度测试提供了在没有符号间干扰(ISI),抖动(Rj, Dj, DCD)和串扰噪声的情况下测试接收机对不同输入电压的灵敏度的方法。

m0_61126667的博客 1703

字典序最大的子序列

题目链接:https://www.nowcoder.com/acm/contest/84/A 题目描述 给定字符串s,s只包含小写字母,请求出字典序最大的子序列。 子序列:https://en.wikipedia.org/wiki/Subsequence 字典序:https://en.wikipedia.org/wiki/Lexicographical_order 输入描述: 一行一个字...

ac@zhui的博客 3412

产品包装质检实战:基于YOLOv5的智能包装合格检测系统全流程指南

摘要: 针对产品包装质检效率低、漏检率高的问题,本文提出基于YOLOv5的智能检测系统。系统通过采集包装缺陷数据(破损、缺标、封装不良等),利用YOLOv5实现多类别缺陷识别(准确率≥95%),并开发Flask Web界面实现检测可视化与报告生成。实验表明,该系统在30帧/秒的产线速度下可稳定运行,显著提升质检效率。项目涵盖数据标注、模型训练、系统开发全流程,具有工业落地价值,适用于智能制造场景的自动化质检需求。(149字)

LXY_LOVE36的博客 92

【Oracle】Oracle rman工具使用(真的细)

Oracle RMAN(Recovery Manager)是Oracle数据库备份和恢复的官方工具,它提供的备份和恢复功能非常强大和可靠。RMAN可以备份整个数据库或特定表空间、数据文件、控制文件和归档日志,同时还可以进行增量备份和增量恢复。RMAN还提供了诸如备份验证、备份优化、备份复制、备份集管理、恢复操作、自动备份、自动恢复等高级功能。它使用的备份和恢复格式是Oracle通用的备份集(Backup Set),这使得备份和恢复非常灵活和高效。

tttzzzqqq2018的博客 8501

51nod 1364 最大字典序排列(线段树)

1364 最大字典序排列基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字典序最大的排列是什么? 例如:N = 5, {1 2 3 4 5},k = 6,在6次交换后,能够得到的字典序最大的排列为{5 3 1 2 4}。 Input 第...

diaocuiguo2493的博客 190

多模态大模型在AI人工智能领域的创新实践探索

随着人工智能技术的飞速发展,单一模态的数据处理已经难以满足复杂现实场景的需求。多模态大模型通过融合多种模态的数据,如文本、图像、音频等,能够更全面、深入地理解和处理信息,为人工智能的发展带来了新的机遇和挑战。本文的目的在于深入探讨多模态大模型在AI人工智能领域的创新实践,包括其核心概念、算法原理、实际应用等方面,旨在为相关领域的研究人员和从业者提供全面的技术参考和实践指导。本文的范围涵盖了多模态大模型的基本原理、算法实现、数学模型、项目实战以及实际应用场景等多个方面。

大模型应用工坊 1316

求给定字符串的字典序最大的子序列

链接:https://ac.nowcoder.com/acm/problem/15805 来源:牛客网 给定字符串s,s只包含小写字母,请求出字典序最大的子序列。 子序列:https://en.wikipedia.org/wiki/Subsequence 字典序:https://en.wikipedia.org/wiki/Lexicographical_order 示例1 输入 ababba 输出 bbba 示例2 输入 abbcbccacbbcbaaba 输出 cccccbba .

EnjoyInwind的专栏 2102

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【51NOD1364】最大字典序排列

题面 给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字典序最大的排列是什么?例如:N = 5, {1 2 3 4 5},k = 6,在6次交换后,能够得到的字典序最大的排列为{5 3 1 2 4}。1 <= N <= 100000, 0 <= K <= 10^9 分析 贪心,找第i个位置的数的时候,寻找在i+k的范...

Ashley_2013的博客 388

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

拼接最大数:单调栈与合并策略解法

本文介绍了拼接两个数组形成最大数的算法解决方案。通过分解问题为三个子任务:使用单调栈获取单数组最大子序列、合并两个子序列的策略以及枚举所有可能的分配方式。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 4795

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

头哥算法答案及解析

目录实验1第1关:数字统计问题第2关:字典序第3关:兔子问题(求斐波那契数列前200项)实验二 实验1 第1关:数字统计问题 本关任务:一本书的页码从自然数1开始编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0. 例如,第8页用数字8表示,而不是08或者008之类。 数字统计问题要求对给定书的总页码n,计算出书的全部页码中分别出现了多少次数字0,1,2,…,9。 #include<stdio.h> #include<math.h> #include<

m0_51930376的博客 1万+

欧拉计划24(一种字典序全排列算法)

/******************************************************************************************************************************************* 字典序算法如...

chuijiaozha4817的博客 233

关于Johnson-Trotter和字典序排列在《算法设计与分析基础》中的论述

这是我在看书时看到的,开始看的时候觉得不理解,后来看了两遍觉得豁然开朗,分享给大家。         对于n的较小值来说,不用生成排列的方式来得到n个元素的相同次序的排列是有可能的。为了做到这一点,我们给一个排列中的每个元素k赋予一个方向。我们在所讨论的每个元素上画一个小箭头来指出它的方向,例如:

sinat_33057191的博客 1169

排列的字典序问题

from: http://www.cnblogs.com/janqii/archive/2010/04/08/1722499.html Problem D:【算法】:排列的字典序问题 Time Limit:2000MS Memory Limit:65536K  Total Submit:200 Accepted:66 Description n个元素{1,2,..., n

fivedoumi的专栏 1017

Leetcode0440. 字典序的第K小数字(difficult,三种算法)

Leetcode0440. 字典序的第K小数字(difficult),Python题解。给出了三种算法,但是时间性能都很差。不过失败的算法也有其学习价值,回头再来补上时间性能优化实现。

chenxy_bwave的专栏 1810
上一篇: 数据结构与算法笔记: 最大红矩形分析
下一篇: 数据结构与算法笔记:计算思维之谁做的好事与刑侦作案问题
Wang's Blog
博客等级 码龄12年 7417粉丝 2397原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值