【一刷《剑指Offer》】面试题 28:字符串的排列

牛客对应题目链接:字符串的排列_牛客题霸_牛客网 (nowcoder.com)

力扣对应题目链接:LCR 157. 套餐内商品的排列顺序 - 力扣(LeetCode)

核心考点 :全排列问题, DFS。

一、《剑指Offer》对应内容


二、分析题目

全排列问题,可以看做如下多叉树形态:

很明显,我们想要得到合适的排列组合,一定是深度优先的。该问题可以把目标串理解成两部分:

  • 第一部分:以哪个字符开头。
  • 第二部分:剩下的是子问题。
所以,我们要让每个字符都要做一遍开头,然后再求解子问题。

三、代码

//牛客
//写法一
class Solution {
private:
    set<string> ans;
    vector<string> res;
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param str string字符串 
     * @return string字符串vector
     */
    void swap(string &str, int i, int j)
    {
        char temp=str[i];
        str[i]=str[j];
        str[j]=temp;
    }
    void dfs(string &str, int start)
    {
        if(start==str.length()-1)
        {
            ans.insert(str);
            return;
        }
        for(int i=start; i<str.size(); i++)
        {
            swap(str, start, i);
            dfs(str, start+1);
            swap(str, start, i);
        }
    }
    vector<string> Permutation(string str) {
        int n=str.size();
        if(n<1) return {""};
        dfs(str, 0);
        for(auto s : ans)
            res.push_back(s);
        return res;
    }
};

//写法二
class Solution {
private:
    set<string> ans;
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param str string字符串 
     * @return string字符串vector
     */
    void dfs(string &str, int pos)
    {
        if(pos==str.length()-1)
        {
            ans.insert(str);
            return;
        }
        for(int i=pos; i<str.size(); i++)
        {
            swap(str[pos], str[i]);
            dfs(str, pos+1);
            swap(str[pos], str[i]);
        }
    }
    vector<string> Permutation(string str) {
        if(str.size()<1) return {""};
        dfs(str, 0);
        return vector<string>({ans.begin(), ans.end()});
    }
};

//力扣
class Solution {
private:
    set<string> ans;
    vector<string> res;
public:
    void dfs(string& goods, int pos)
    {
        if(pos==goods.size()-1)
        {
            ans.insert(goods);
            return;
        }
        for(int i=pos; i<goods.size(); i++)
        {
            swap(goods[pos], goods[i]);
            dfs(goods, pos+1);
            swap(goods[pos], goods[i]);
        }
    }
    vector<string> goodsOrder(string goods) {
        dfs(goods, 0);
        for(auto s : ans)
            res.push_back(s);
        return res;
    }
};

四、扩展


五、相关题目

1、正方体的三面和

输入一个含有 8 个数字的数组,判断有没有可能把这 8 个数字分别放到正方体的 8 个顶点上(如图 4.15 所示),使得正方体上三组相对的面上的 4 个顶点的和都相等。

这相当于先得到 a1、a2、a3、a4、a5、a6、a7 和 a8 这 8 个数字的所有排列,然后判断有没有某一个的排列符合题目给定的条件,即 a1+a2+a3+a4==a5+a6+a7+a8,a1+a3+a5+a7==a2+a4+a6+a8,并且 a1+a2+a5+a6==a3+a4+a7+a8。


2、八皇后

在 8 X 8 的国际象棋上摆放 8 个皇后,使其不能相互攻击,即任意两个皇后不得处在同一行、同一列或者同一对角线上。图 4.16 中的每个黑色格子表示一个皇后,这就是一种符合条件的摆放方法。请问总共有多少种符合条件的摆法?

由于 8 个皇后的任意两个不能处在同一行,那么肯定是每一个皇后占据一行。于是我们可以定义一个数组 ColumnIndex[8],数组中第 i 个数字表示位于第 i 行的皇后的列号。先把 ColumnIndex 的 8 个数字分别用 0~7 初始化,接下来就是对数组 ColumnIndex 做全排列。因为我们是不同的数字初始化数组,所以任意两个皇后肯定不同列。我们只需判断每一个排列对应的 8 个皇后是不是在同意对角线上,也就是对于数组的两个下标 i 和 j,是不是 i-j==ColumnIndex[i]-ColumnIndex[j] 或者 j-i==ColumnIndex[i]-ColumnIndex[j]。


力扣对应类似题目链接:51. N 皇后 - 力扣(LeetCode)

//写法一
class Solution {
private:
    vector<string> path;
    vector<vector<string>> res;
    vector<bool> checkCol, checkDg, checkUdg;
public:
    void dfs(int row, int n)
    {
        if(row==n)
        {
            res.push_back(path);
            return;
        }
        for(int col=0; col<n; col++)
        {
            if (!checkCol[col] && !checkDg[row-col+n] && !checkUdg[row+col])
            {
                path[row][col]='Q';
                checkCol[col]=checkDg[row-col+n]=checkUdg[row+col]=true;
                dfs(row+1, n);
                checkCol[col]=checkDg[row-col+n]=checkUdg[row+col]=false;
                path[row][col]='.';
            }
        }
    }
    vector<vector<string>> solveNQueens(int n) {
        checkCol = vector<bool>(n, false);
        checkDg = vector<bool>(2*n, false);
        checkUdg = vector<bool>(2*n, false);
        path.resize(n);
        for(int i=0; i<n; i++)
            path[i].append(n, '.');
        dfs(0, n);
        return res;
    }
};

//写法二
class Solution {
public:
    vector<vector<string>> res;
    void dfs(int x, int n, vector<string>& chessboard)
    {
        if(x==n)
        {
            res.push_back(chessboard);
            return;
        }
        for (int y=0; y<n; y++)
        {
            if (isValid(x, y, n, chessboard))
            {
                chessboard[x][y]='Q';
                dfs(x+1, n, chessboard);
                chessboard[x][y]='.';
            }
        }
    }

    bool isValid(int x, int y, int n, vector<string>& chessboard)
    {
        // 检查列
        for (int i=0; i<x; i++)
        {
            if (chessboard[i][y]=='Q')
                return false;
        }
        // 检查 45度角是否有皇后
        for (int i=x-1, j=y-1; i>=0 && j>=0; i--, j--)
        {
            if (chessboard[i][j]=='Q')
                return false;
        }
        // 检查 135度角是否有皇后
        for(int i=x-1, j=y+1; i>=0 && j<n; i--, j++)
        {
            if (chessboard[i][j]=='Q')
                return false;
        }
        return true;
    }

    vector<vector<string>> solveNQueens(int n) {
        vector<string> chessboard(n, string(n, '.'));
        dfs(0, n, chessboard);
        return res;
    }
};

六、举一反三

如果面试题是按照一定要求摆放若干个数字,我们可以先求出这些数字的所有排列,然后再一一判断每个排列是不是满足题目给定的要求。

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

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

相关文章

关于留痕的使用常见的问题

1. 登录微信 登录要导出数据的微信&#xff08;不支持微信多开&#xff0c;不支持部分老版本微信&#xff09; 相关信息 想把手机端的微信聊天记录转移到电脑上可以使用微信自带的聊天记录迁移功能 操作步骤&#xff1a; 安卓&#xff1a; 手机微信->我->设置->聊…

AI解密:语言模型生成下一个词的概率从何而来

在这个信息爆炸的时代&#xff0c;你是否曾好奇过&#xff0c;当你与聊天机器人流畅对话时&#xff0c;那些机智回复的背后&#xff0c;究竟隐藏着怎样的秘密&#xff1f;今天&#xff0c;就让我们一起乘坐时光机&#xff0c;深入语言模型的神秘腹地&#xff0c;揭开它预测下一…

【spring】第二篇 bean实例化

对象已经能交给Spring的IOC容器来创建了&#xff0c;但是容器是如何来创建对象的呢? 就需要研究下bean的实例化过程&#xff0c;在这块内容中主要解决两部分内容&#xff0c;分别是 bean是如何创建的 实例化bean的三种方式&#xff0c;构造方法,静态工厂和实例工厂 在讲解这…

iOS——类与对象底层探索

类和对象的本质 当我们使用OC创建一个testClass类并在main函数创建它的实例对象的时候&#xff0c;OC的底层到底是什么样的呢&#xff1f; 首先&#xff0c;我们要了解OC对象的底层结构&#xff0c;那么我们就得知道&#xff1a;OC本质底层实现转化其实都是C/C代码。 使用下面…

详解 Spark SQL 核心编程知识

一、SparkSQL 概述 1. 概念 Spark SQL 是 Spark 用于结构化数据 (structured data) 处理的 Spark 模块&#xff0c;使用 SQL 的方式简化 RDD 的开发 2. Hive VS SparkSQL Hive 是早期唯一运行在 Hadoop 上的 SQL-on-Hadoop 工具&#xff0c;但是 MapReduce 计算过程中大量的中…

java高并发实战<2>

##>>> 我们解决我们重复下单的问题 我们可以使用mysql 的唯一索引 &#xff0c;在我们的数据库层面保证不能重复下单 我可以控制是唯一的 同一个用户 针对于同一个商品只可以买一个 重复下单 优化 我们 >1.使用数据库唯一索引 一旦是 2个请求 因为mysql 有行级…

万物皆有定数

前段时间&#xff0c;测算一个女孩的婚姻&#xff0c;她年底或明年必有婚姻&#xff0c;因为蛇冲猪日&#xff0c;冲动夫宫&#xff0c;就有婚姻出现。不过&#xff0c;按照她总体八字分析&#xff0c;是要晚婚的&#xff0c;但这个运已到&#xff0c;所以&#xff0c;就要允许…

【文献阅读】汽车上的信息安全工程

文章目录 前言 基本概念 信息安全评估 信息安全措施 测试验证 参考文献 前言 见《汽车电子——产品标准规范汇总和梳理&#xff08;信息安全&#xff09;》 基本概念 道路车辆信息安全 cybersecurity 使资产受到充分保护&#xff0c;免受道路车辆相关项、其功能及其电气或…

运放的自激振荡问题

运放的自激振荡指的是当运算放大器加电后&#xff0c;在没有外部信号输入的情况下&#xff0c;输出端会出现高频类似于正弦波的波形。 运算放大器产生自激的原因以及解决办法-CSDN博客 a)当振荡由分布电容、电感等引起时&#xff0c;可通过反馈端并联电容&#xff0c;抵消影响…

Java web应用性能分析之【java进程问题分析工具】

Java web应用性能分析之【java进程问题分析概叙】-CSDN博客 前面大概讲了java进程问题分析流程&#xff0c;这里再小结一下分析工具&#xff0c;后面也会小结一下java进程问题分析定位。 1.分析工具 1.1.linux命令工具 参考&#xff1a;Java web应用性能分析之【Linux服务器性…

汪小菲直播翻车亲儿子直言麻六记有异味网友热议引爆话题

汪小菲直播翻车&#xff01;亲儿子直言“麻六记”有“异味”&#xff0c;网友热议引爆话题在星光璀璨的娱乐圈&#xff0c;汪小菲一直以家庭幸福、事业有成的形象示人。然而&#xff0c;近日的一场直播让他遭遇了前所未有的尴尬。在直播中&#xff0c;汪小菲兴致勃勃地向观众跨…

创新实训2024.05.29日志:评测数据集与baseline测试

1. 评测工作 在大模型微调和RAG工作都在进行的同时&#xff0c;我们搭建了一套评测数据集。这套数据集有山东大学周易研究中心背书。主要考察大模型对于易学基本概念与常识的理解与掌握能力。 1.1. 构建评测集 在周易研究中心的指导下&#xff0c;我们构建出了一套用以考察大…

Linux系统下+jmeter分布式压测

一.配置jdk&#xff08;Linux机都需配置同一个版本&#xff09; 下载Linux系统的jdk&#xff0c;下载地址&#xff1a;https://repo.huaweicloud.com/java/jdk/ 下载后的jdk文件上传到 /opt目录下 进入opt目录&#xff0c;查看jdk文件 cd /opt ll 1.解压文件 tar xzvf jd…

为什么改变进制传输系统码长不变

目录 直接上图片 问题分析 传信率与传码率 多进制调制 码长不变的理解 误码率考量 总结 直接上图片 问题分析 在讨论这个问题时&#xff0c;通常是指在保持RB&#xff08;码元传输速率&#xff0c;传码率&#xff0c;符号率&#xff0c;波特率&#xff09;不变的情况下&a…

R语言探索与分析-美国房价及其影响因素分析

一、选题背景 以多元线性回归统计模型为基础&#xff0c;用R语言对美国部分地区房价数据进行建模预测&#xff0c;进而探究提高多元回 归线性模型精度的方法。先对数据进行探索性预处理&#xff0c;随后设置虚拟变量并建模得出预测结果&#xff0c;再使用方差膨胀因子对 多重共…

关于IDEA创建Maven一直爆红无法下载的问题

你能看到这我就知道你肯定已经试过了网上的很多方法了&#xff0c;我之前也是&#xff0c;试过了很多一直无法正常下载&#xff0c;我也是找人给 线下看了看解决了&#xff0c;我总结一下从头到尾排除问题&#xff0c;试到最后要是还解决不了你直接私信我&#xff0c;我给你看看…

【LeetCode刷题】前缀和解决问题:742.寻找数组的中心下标、238.除自身以外数组的乘积

【LeetCode刷题】Day 15 题目1&#xff1a;742.寻找数组的中心下标思路分析&#xff1a;思路1&#xff1a;前缀和思想 题目2&#xff1a;238.除自身以外数组的乘积思路分析思路1&#xff1a;前缀和思想 题目1&#xff1a;742.寻找数组的中心下标 思路分析&#xff1a; 其实题干…

时间序列的谱分解

refer&#xff1a;15.pdf (berkeley.edu) Stat 153 Fall 2010 (berkeley.edu)

xLSTM: Extended Long Short-Term Memory

更多内容&#xff0c;请关注微信公众号&#xff1a;NLP分享汇 原文链接&#xff1a;xLSTM: Extended Long Short-Term Memory 论文链接&#xff1a;https://arxiv.org/pdf/2405.04517 为什么要在27年后提出新的LSTM呢&#xff1f; LSTM&#xff08;长短期记忆网络&#xff09…

18 EEPROM读写

EEPROM 简介 EEPROM (Electrically Erasable Progammable Read Only Memory&#xff0c;E2PROM)即电可擦除可编程只读存储器&#xff0c;是一种常用的非易失性存储器&#xff08;掉电数据不丢失&#xff09;&#xff0c;EEPROM 有多种类型的产品&#xff0c;此次实验使用的是A…