【剑指offer-题38】

字符串排列

题目

输入一个字符串,输出该字符串的全排列。

思路

数学中的排列思想。算法步骤如下:

  • 求出所有可能出现在第一个位置的字符。将首字符依次与后面的字符交换,即可达到此目的。
  • 确定完第一个位置的字符之后,后面的字符作为一个新的字符串,求其全排列,也就是递归算法
  • 将某个字符与首字符交换,求解完它的所有全排列之后,需要将首字符放回原位,方便首字符与后面字符继续交换。
实现代码
void SwitchToFront(char* pStr, char* pPos)
{char chTemp = *pPos;*pPos = *pStr;*pStr = chTemp;
}//pStr - 待求取全排列的字符串
//pStart - 当前递归的首字符位置
void PermutationReversely(char* pStr, char* pStart)
{if (*(pStart + 1) == '\0'){cout << pStr << endl;}else{for (char *pCh = pStart; *pCh != '\0'; pCh++){//将首字符与其后字符交换SwitchToFront(pStart, pCh);//增加首字符指针,递归遍历后面的字符串PermutationReversely(pStr, pStart + 1);//将首字符回归原位,为后续字符交换做准备SwitchToFront(pStart, pCh);}}
}//主函数
void Permutation(char* pStr)
{if (!pStr || *pStr == '\0')return;PermutationReversely(pStr, pStr);
}

这里会有一个问题,如果字符串中有相同的字符时,会出现相同的排列。所以,应该先检查当前待交换字符之前是否已经出现过,如果出现过,则不进行任何处理,直接处理下一个字符。

修改后的代码
//判断当前字符是否已经出现过
bool CheckIfExist(char* pStr, const char* pCh)
{char* p = pStr;while (p != pCh){if (*p == *pCh)return true;p++;}return false;
}//pStr - 待求取全排列的字符串
//pStart - 当前递归的首字符位置
void PermutationReversely(char* pStr, char* pStart)
{if (*(pStart + 1) == '\0'){cout << pStr << endl;}else{for (char *pCh = pStart; *pCh != '\0'; pCh++){if (!CheckIfExist(pStart, pCh)){//将首字符与其后字符交换SwitchToFront(pStart, pCh);//增加首字符指针,递归遍历后面的字符串PermutationReversely(pStr, pStart + 1);//将首字符回归原位,为后续字符交换做准备SwitchToFront(pStart, pCh);}}}
}

字符串组合

题目

输入一个字符串,输出该字符串的所有组合。比如输入abc,则输出 a, b, c, ab, ac, bc, abc

思路
  • 假设字符串的长度为 n,那么首先要确定需要找出长度为 1~n的所有组合,采用循环。
  • 假设当前确定的组合长度为 m,那么有两种求法。第一,可以选择首字符,然后在剩下的字符串中找出长度为 m - 1的组合,可以采用 vector 容器保存当前选择的字符;第二,不选择首字符,直接在剩下的字符串中找出长度为 m 的组合。采用递归方式。但应该注意,如果剩下的字符串的首字符之前已经出现过,则应该跳过此次递归,否则会重复出现。
  • 判断递归边界条件。如果当前的字符串长度小于需要找到的组合长度,则应该直接返回。如果当前字符串的长度为0,则说明长度为 m 的组合寻找完毕,应该打印出 vector中的所有字符。
实现代码
//判断当前字符是否已经出现过
bool CheckIfExist(char* pStr, const char* pCh)
{char* p = pStr;while (p != pCh){if (*p == *pCh)return true;p++;}return false;
}//pStr - 当前需要确定组合的字符串
//pStart - 当前递归开始确定组合的字符串
//length - 需要确定的组合长度
//strVec - 保存的之前已经确定的字符
void PermutationReversely(char* pStr, char *pStart, int length, vector<char>& strVec)
{if (strlen(pStart) < length)return;if (!length){for (int i = 0; i < strVec.size(); i++){cout << strVec[i];}cout << endl;return;}strVec.push_back(*pStart);PermutationReversely(pStr, pStart + 1, length - 1, strVec);strVec.pop_back();//当下一个开始的字符串在之前没有出现时,才会递归if (!CheckIfExist(pStr, pStart + 1)){PermutationReversely(pStr, pStart + 1, length, strVec);}
}//主函数
void Permutation(char* pStr)
{if (!pStr || *pStr == '\0')return;int maxLength = strlen(pStr);vector<char> strVec;for (int length = 1; length <= maxLength; length++){PermutationReversely(pStr, pStr, length, strVec);}
}

八皇后问题

问题

在 8 乘 8 的国际象棋上拜访8个皇后,要求每个皇后不能处于同一行,不能处于同一列,且不能位于同一对角线,问有多少种摆放方法。

解题思路

这就是一个排列问题。

  • 每个皇后不能处于同一行,那么一定每一行都有一个皇后。所以定义一个数组 ColunmIndex[8],ColumnIndex[i]表示第 i 行皇后的列坐标。
  • ColumnIndex[8] 初始化为{0, 1, 2, 3, 4, 5 ,6, 7}。这样它们就满足了不位于同一行,和同一列
  • 最终的解就是 ColumnIndex 数组的所有全排列中,满足皇后不位于同一对角线的,即满足:abs(i - j) != abs(ColumnIndex[i] - ColumnIndex[j])。

字符串全排列与组合算法以及八皇后问题相关推荐

  1. 回溯算法解决八皇后_4皇后问题和使用回溯算法的解决方案

    回溯算法解决八皇后 4-皇后问题 (4 - Queen's problem) In 4- queens problem, we have 4 queens to be placed on a 4*4 ...

  2. 全排列算法(无重复数字全排列/有重复数字全排列)/ 组合算法/ 求子集算法

    写在前面 全排列 1 无重复数字全排列 1.1 紫书版本 1.2 回溯法 2 有重复数字全排列 复盘易错点(可跳过) 写在前面 很久很久以前就想写的一篇博客,因为懒一直没开工,但是学习全排列算法算是我 ...

  3. 数据结构与算法 / 回溯算法(八皇后、0 - 1 背包)

    回溯算法,顾名思义,就是在没有得到最优解的前提下,不断的返回至前面的岔路口位置,重新选择,直至遍历了所有的情况或者得到的预期最优解的情况下再结束. 与贪心算法不同的是,回溯算法理论上是可以得到最优解, ...

  4. 回溯算法-03八皇后问题

    八皇后问题 简介 回溯法的经典问题. 问题描述 有8*8=64个格子,每个格子里面可以放一个棋子,现在要求任意两个棋子不在一条横向.纵向或者斜向的直线上. 问题分析 显然,每一行.每一列都只有一个棋子 ...

  5. 数据结构 - 递归 回溯算法(八皇后问题)

    游戏地址自己写完了可以根据结果去测试一下. 算法分析 八皇后问题算法思路分析 1)第一个皇后先放第一行第一列 2)第二个皇后放在第二行第一列.然后判断是否OK, 如果不OK,继续放在.第二列.第三列. ...

  6. 爬山法、随机重启爬山法、模拟退火算法对八皇后问题和八数码问题的性能测试...

    代码地址:https://github.com/laiy/AI/tree/master/awesome-search 一些前提: 1. 首先要明确这些算法并不是用于解决传统的搜索问题的(环境是可观察的 ...

  7. 回溯算法解决八皇后问题(JAVA实现)

    送给程序猿们一句话 <拥有水滴石穿的坚持:懂得聚沙成塔的积累:磨练坚韧不拔的意志:学习脚踏实地的奋斗:提升立世做人的技巧:突破自我设限的障碍.> 文章目录 背景 问题解决 思路 什么是回溯 ...

  8. 算法总结——八皇后问题(三种解法)

    问题描述 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题. 对于某个满足要求的8 ...

  9. 用递归思想和回溯算法解决八皇后问题(java实现)

    八皇后问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处 ...

最新文章

  1. (转载)Linux信息资源
  2. Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解
  3. HDU2521 反素数【因子数量+打表】
  4. word通配符使用法详解
  5. 这九张动态图诠释什么是自然与科技的完美结合
  6. Flink : Cannot find compatible factory for specified execution.target (=local)
  7. Android生命周期帮助类,Android Service类与生命周期详细介绍_Android_脚本之家
  8. Python socket UDP
  9. CSS中min-height:100%问题
  10. 拓端tecdat|R语言中的多类别问题的绩效衡量:F1-score 和广义AUC
  11. 爬虫(二)-创建项目应用
  12. 2017百度之星资格赛总结
  13. 分享一下个人3年的运维经验
  14. python wheel是什么意思_python中wheel指的是什么
  15. 小白自学Java后端学习计划(附带学习视频)
  16. 微软中国CTO:手机里装的App一上网基本等于裸奔
  17. 移动端开发之Web App开发
  18. golang中结构体转成xml格式
  19. 网页素材大宝库:15套精美的用户头像图标素材
  20. 关于python的基础语法

热门文章

  1. Android9.0 Launcher启动Activity详解(一)
  2. 2013年山东省第四届ACM大学生程序设计竞赛 Problem I Thrall’s Dream 图,2n遍dfs
  3. 中央民族大学计算机房,中央民族大学第九届大学生人文知识竞赛 暨北京市第九届大学生人文知识竞赛选拔赛通知...
  4. Java面向对象之子类方法重写
  5. 利用Java计算多少次纸才能对折出珠峰高度
  6. cortellis数据库价格与价值分析
  7. 在线工作坊 | 人工智能之 AI on Azure
  8. 计算机科学转金融工程,计算机如何转金融与金融工程
  9. UWP控件与DataBind
  10. python中syntaxerror什么意思_在Python中,“SyntaxError:调用'print'时缺少括号”是什么意思?...