[31. 下一个排列] 从错误中思考

Problem: 31. 下一个排列

文章目录

  • 前言
  • 思路
  • 解法
  • 总结
  • Code

前言

题目是难以理解的,解法是匪夷所思的,我们是前途渺茫的。 --「鲁迅」

思路

开个玩笑。不过就像鲁迅说的一样,这道题的题目确实是难以理解的。
题目要求找出下一个字典序更大的排列,可以说是并没有什么思路。“更大”这样一个要求十分抽象,很难说找到一个角度去分解“更大”的要求。那么就只能看题解了吗,或者就试试。

  1. 第一个错误解法
    观察一下简陋的用例们,至少我们知道一件事,把一个大的数字换到前面整个数字会变大,那么找到最大的方法是找到最大的数字,并将它换到前面一格?可是还有一些问题亟待解决,如果最大数字已经到最前面了呢,哦,找第二大的数字,等等,这不是优先队列吗。于是完整的思路就出来了,通过优先队列寻找最大的可向前置换的数字,并将它换到前面。
    [1,3,2],显然,他错了,这个数字被错误的置换成312,而正确的答案是213。
  2. 第二个错误解法
    换大了,显然。我们从1开头的群组直接跳大了3开头的,属于是步子迈大了。那说明我们不必要找最大的可置换的数字,小一点也可以。那怎么找呢?会不会是从右往左找(这就靠点正确思路了)。从右往左找一个前面有比他小的数字,然后把这个数字放到比她小的数字前面。这样一来就变大了,而且不用一次就变大一个最大数字。很好,我又会了。哦,等等,换完之后再把后面的数字排序,这样就让后面的变成最小。
    [4,2,0,2,3,2,0],怎么会变成4220023呢,应该是4203022。不对劲,非常不对劲。
  3. 第三个正确解法
    先把2换到最前面去了,这跨的太远了。我们的思路需要找跨步跨的小的。最小的不就是临近?那是不是这样呢,从右往左找第一个变小的数字 i,把 i 和 i+1 置换就好了。靠点谱了,然而还是需要考虑后面的数字,那索性排个序。哦吼,过了?

解法

当然,这个答案是可以的,但还是有点粗糙。经过对一些优秀题解(例如这个)的研究,最后解法优化到了下面的code。

总结

其实解题过程中遇到的错误远不止列出来的这几个,甚至从开始时我连字典序大小等价于数字大小都没有想到,因为“更大”这样一个概念的抽象。我们没办法描述一个没有见过的理论,或是只能很模糊的描述,这很正常。想出一个完善的理论可能很困难,那就从实践入手,从这个模糊的描述着手实现,找到不可覆盖的用例,从而抽取出理论中的正确部分,变现成新的理论,如此往复。
在实践过程中我们会失败很多次,写出很多错误解法,但每一个错误解法的背后,都是一次成功的尝试。失败总是贯穿人生始终的,但是从这个角度看,成功同样贯穿人生始终。

Code

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        for(int i = nums.size() - 2; i >= 0 ; i--) {
            if(!is_rev(nums, i)) {
                for(int j = nums.size() - 1; j > i; j--) {
                    if(nums[i] < nums[j]) {
                        swap(nums[i], nums[j]);
                        sort(nums.begin() + i + 1, nums.end());
                        return;
                    }
                }
            }
        }

        reverse(nums.begin(), nums.end());
    }

    bool is_rev(vector<int>& nums, int i) {
        for(; i < nums.size() - 1; i++) {
            if(nums[i] < nums[i + 1]) return false;
        }

        return true;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/456874.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3调用钉钉api,内嵌H5微应用单点登录对接

钉钉内嵌H5微应用单点登录对接 https://open.dingtalk.com/document/isvapp/obtain-the-userid-of-a-user-by-using-the-log-free 前端需要的代码 1、安装 dingtalk-jsapi npm install dingtalk-jsapi2、在所需页面引入 import * as dd from dingtalk-jsapi; // 引入钉钉a…

软件测试覆盖率

软件测试覆盖率简介 1、定义&#xff1a;覆盖率是用来度量测试完整性的一个手段&#xff0c;同时也是测试技术有效性的一个度量。2、计算&#xff1a;覆盖率&#xff08;至少被执行一次的item数&#xff09;/item的总数3、特点1&#xff09;通过覆盖率数据&#xff0c;可以检测…

【框架学习 | 第五篇】SpringMVC(常用注解、获取请求参数、域对象共享数据、拦截器、异常处理、上传/下载文件)

文章目录 1.SpringMVC简介1.1定义1.2主要组件1.3工作流程1.3.1简要流程1.3.2详细流程 1.4优缺点 2.常用注解3.获取请求参数3.1通过 HttpServletRequest 获取请求参数3.2通过控制器方法的形参获取请求参数3.2.1请求路径参数与方法形参一致3.2.2请求路径参数与方法形参不一致3.2.…

3、设计模式之工厂模式1(Factory)

工厂模式是什么&#xff1f;     工厂模式是一种创建者模式&#xff0c;用于封装和管理对象的创建&#xff0c;屏蔽了大量的创建细节&#xff0c;根据抽象程度不同&#xff0c;主要分为简单工厂模式、工厂方法模式以及抽象工厂模式。 简单工厂模式 看一个具体的需求 看一个…

【划重点】自动引流软件隐藏风险!?你不知道的网络危机与应对策略

先来看成果&#xff0c;评论888领取 在互联网快速发展的今天&#xff0c;自动引流软件以其高效的推广方式和便捷的操作&#xff0c;成为许多商家和个人提升网络知名度的重要工具。然而&#xff0c;这种看似无害的软件&#xff0c;却潜藏着不容忽视的网络安全风险。本文将深入解…

Linux操作系统启动流程

文章目录 1. Linux操作系统启动流程图2.运行流程&#xff08;1&#xff09; 加载BIOS&#xff08;2&#xff09; 读取MBR&#xff08;3&#xff09; GRUB引导&#xff08;4&#xff09; 加载Kernel&#xff08;5&#xff09; 设定Inittab运行等级&#xff08;6&#xff09; 加载…

如何布局马斯克推特上喊的meme币赛道

2024年的牛市正如火如荼的开展&#xff0c;截止当下&#xff0c;比特币已经站上了7.3万美元&#xff0c;远超2021年高点的6.9万美元&#xff0c;比特币的未来是一片大海。 除了比特币的一枝独秀之外&#xff0c;meme板块可以说是市场资金最青睐的。尤其是马斯克在X分享PEPE相关…

初步了解序列化和反序列化

01什么是序列化和反序列化 序列化是将对象转化为字符串以便存储的一种方式。而反序列化恰好是序列化的逆过程&#xff0c;反序列化会将字符串转化为对象供程序使用。 常见的php系列化和反系列化方式主要有&#xff1a;serialize&#xff0c;unserialize&#xff1b;json_enco…

LVGL移植到ARM开发板(GEC6818开发板)

LVGL移植到ARM开发板&#xff08;GEC6818开发板&#xff09; 一、LVGL概述 LVGL&#xff08;Light and Versatile Graphics Library&#xff09;是一个开源的图形用户界面库&#xff0c;旨在提供轻量级、可移植、灵活和易于使用的图形用户界面解决方案。 它适用于嵌入式系统…

四、MySQL

MySQL MySQL1.初识网站2.安装MySQL2.1 下载&#xff08;最重要的一点是路径中不能有中文&#xff0c;哪怕是同级目录也不行&#xff09;2.2安装补丁2.3安装2.4创建配置文件2.5初始化 3.启动MySQL4.连接测试4.1 设置密码4.2 查看已有的文件夹&#xff08;数据库&#xff09;4.3 …

【SSM】任务列表案例 基本CRUD SSM整合

文章目录 一、案例功能预览二、接口分析三、前端工程导入四、后端程序实现和测试4.1 准备4.2 功能实现4.2.1 分页查询显示4.2.2 添加计划4.2.2 删除计划4.2.3 修改计划 4.3 前后联调 一、案例功能预览 Github 地址 &#xff1a; ssm-integration-part 二、接口分析 学习计划…

【C++初阶】C++入门(上)

C的认识 ①什么是C&#xff1f; ​ C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。 ​ 于是1982年&#xff0c;Bjarne Stroustrup&#xff08;本…

激活函数理解

前言 为什么神经网中非要有各种各样的激活函数&#xff1f;他们有什么用&#xff1f;没有他们会怎样&#xff1f;常见的激活函数有哪些&#xff0c;他们都有什么特点&#xff1f; 如果我们不运用激活函数&#xff0c;神经网络的输出信号将仅仅是一个简单的线性函数。线性方程…

【DL经典回顾】激活函数大汇总(七)(CReLU RReLU附代码和详细公式)

激活函数大汇总&#xff08;七&#xff09;&#xff08;CReLU & RReLU附代码和详细公式&#xff09; 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里&#xff0c;激活函数扮演着不可或…

Solidity 智能合约开发 - 基础:基础语法 基础数据类型、以及用法和示例

苏泽 大家好 这里是苏泽 一个钟爱区块链技术的后端开发者 本篇专栏 ←持续记录本人自学两年走过无数弯路的智能合约学习笔记和经验总结 如果喜欢拜托三连支持~ 本篇主要是做一个知识的整理和规划 作为一个类似文档的作用 更为简要和明了 具体的实现案例和用法 后续会陆续给出…

【应急响应靶场web1】

文章目录 前言 一、web1 1、应急响应 1&#xff09;背景 2&#xff09;报错处理 3&#xff09;webshell查杀 4&#xff09;网站日志排查 5&#xff09;隐藏账户 6&#xff09;挖矿程序 2、渗透复现 1&#xff09;弱口令登录 2&#xff09;插件上传 3&#xff09;getshell 总结 …

还有没有免费裁剪音频的软件?15款音乐裁剪软件测评!(不断更新)

市面上有哪些免费裁剪音频的软件呢&#xff1f;今天&#xff0c;我们就来为大家详细介绍15款热门的音乐裁剪软件&#xff0c;并对其进行深度测评。 裁剪音频软件测评1&#xff1a;金舟音频大师 好评指数&#xff1a;4.5/5 优点罗列&#xff1a;支持音频格式转换、裁剪、降噪、…

Linux-vim显示乱码

Linux运维工具-ywtool 目录 一.问题二.解决2.1 编辑VIM的配置文件2.2 添加以下内容 一.问题 用vim编辑的时候,中文显示乱码 二.解决 2.1 编辑VIM的配置文件 vim ~/.vimrc #如果这个文件不存在,创建一个即可2.2 添加以下内容 添加完成以后就不会在出现中文乱码了 set fil…

爬虫的去重

去重基本原理 爬虫中什么业务需要使用去重 防止发出重复的请求防止存储重复的数据 在爬取网页数据时&#xff0c;避免对同一URL发起重复的请求&#xff0c;这样可以减少不必要的网络流量和服务器压力&#xff0c;提高爬虫的效率&#xff0c;在将爬取到的数据存储到数据库或其…

一个简单而绝妙的思维技巧

在文章的最开头&#xff0c;我想先问你一个问题&#xff1a; 你希望未来的你是什么样的&#xff1f;你希望未来的你比现在的你过得更好&#xff0c;还是过得更糟&#xff1f; 我想&#xff0c;应该没有人会选择后者吧&#xff1f; 尽管从客观上说&#xff0c;未来的我们很可能…