给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路:
回溯+递归
以一个ABC的图为例。首先从ABC中选一个,可以选A、B、C分别是第二层的绿色表示。然后则剩余BC 、AC和BA。对于每一个分支,依次选择其中一个与之前的进行连接,过程直到被选集只剩下一个的时候。这个过程本质上是回溯。
那么代码中怎么实现“选一个”和拼接的动作呢?
“选一个”实际上是通过循环遍历完成的。for循环,从开始到结束依次取。怎么完成的拼接呢?本质上是交换完成的。一个个“选一个”和拼接又是怎么完成的?通过递归完成。
【以ACB为例】
第一次递归,传入ABC,开始i为0,和长度3
for循环写作for(int j = i ; j < n ; j++)首先是j=0,也就是选了A作为第一个,然后完成交换,字符串仍为ABC,递归下一层,也就是从BC中选一个后与A连接。所以第二次递归,传入还是ABC,但是开始为1,总长度仍为3
此时,j = 1 但不是要举的ABC的例子,所以跳过。当 j = 2 时,意味着选择C作为当前要排在A后的,怎么实现排在A后?通过交换完成,把C换做BC串的第一个,成为CB。字符串变为ACB。此时继续递归。
第三次递归,开始i为2,总长度为3,意味着此时是最后一个,最后一个不需选择,直接拼接,可以将当前的结果作为一个对象,完成ACB的生成。
然后依次返回到递归调用处,重新把字母交换回来,恢复原状。
因此,字母的全排列代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <vector>
using namespace std;
void per(string str, int i , int n){
if (i == n-1) {
cout << str << endl;
return;
}
for (int j = i ; j < n ; j++) {
swap(str[i], str[j]);
per(str, i+1, n);
swap(str[i], str[j]);
}
}
int main(){
per("ABC", 0, 3);
return 0;
}
力扣题目代码如下:
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
string s = "";
if(strs.size() == 0) return s;
int length = strs[0].size();
for(int i = 0 ; i < strs.size() ; i++){
if(strs[i].size() < length) length = strs[i].size();
}
int m = 0 , n = 0 ; char temp;
while(n < length){
temp = strs[0][n];
for(m = 1 ; m < strs.size() ; m++){
if(strs[m][n] != temp) return s;
}
s+=temp;
n++;
}
return s;
}
};