인터뷰 프로그래밍 (일반적으로 인터뷰 경험이 아닌)의 일반적인 작업은 문자열 또는 정수를 사용하여 가능한 모든 순열을 나열하는 것입니다.
이것이 어떻게 수행되는지와 그러한 문제를 해결하는 논리의 예가 있습니까?
몇 가지 코드 스 니펫을 보았지만 주석 처리가 잘되지 않았으므로 따르기가 어렵습니다.
답변
우선 : 물론 재귀 냄새가납니다 !
당신은 또한 그 원리를 알고 싶었 기 때문에 나는 그것을 인간의 언어로 설명하기 위해 최선을 다했습니다. 나는 재귀가 대부분 매우 쉽다고 생각합니다. 두 단계 만 파악하면됩니다.
- 첫 번째 단계
- 다른 모든 단계 (모두 동일한 논리)
에서 인간의 언어 :
간단히 말해 :
1. 1 요소의 순열은 하나의 요소입니다.
2. 요소 집합의 순열은 각 요소의 목록이며 다른 요소의 모든 순열과 연결됩니다.예:
세트에 하나의 요소가 있으면
반환하십시오.
파마 (a)-> a집합에 두 개의 문자가있는 경우 : 각 요소에 대해 다음과 같이 나머지 요소의 순열을 추가하여 요소를 반환하십시오.
파마 (ab)->
a + 파마 (b)-> ab
b + 파마 (a)-> ba
또한 : 세트의 각 문자에 대해 :> 세트의 나머지로 연결된 문자를 반환합니다.
파마 (abc)->
a + perm (bc)-> abc , acb
b + 파마 (ac)-> bac , bca
c + perm (ab)-> 택시 , cba
perm (abc … z)->
a + perm (…), b + perm (….)
….
http://www.programmersheaven.com/mb/Algorithms/369713/369713/permutation-algorithm-help/ 에서 의사 코드 를 찾았습니다 .
makePermutations(permutation) {
if (length permutation < required length) {
for (i = min digit to max digit) {
if (i not in permutation) {
makePermutations(permutation+i)
}
}
}
else {
add permutation to list
}
}
씨#
OK, http://radio.weblogs.com/0111551/stories/2002/10/14/permutations.html 에서보다 정교한 (그리고 c # 태그가 붙어 있기 때문에) 다소 길지만 복사하기로 결정했습니다. 어쨌든 게시물은 원본에 의존하지 않습니다.
이 함수는 문자열을 가져와 정확한 문자열의 가능한 모든 순열을 기록합니다. 예를 들어 “ABC”가 제공된 경우 유출해야합니다.
ABC, ACB, BAC, BCA, CAB, CBA.
암호:
class Program
{
private static void Swap(ref char a, ref char b)
{
if (a == b) return;
var temp = a;
a = b;
b = temp;
}
public static void GetPer(char[] list)
{
int x = list.Length - 1;
GetPer(list, 0, x);
}
private static void GetPer(char[] list, int k, int m)
{
if (k == m)
{
Console.Write(list);
}
else
for (int i = k; i <= m; i++)
{
Swap(ref list[k], ref list[i]);
GetPer(list, k + 1, m);
Swap(ref list[k], ref list[i]);
}
}
static void Main()
{
string str = "sagiv";
char[] arr = str.ToCharArray();
GetPer(arr);
}
}
답변
LINQ를 사용할 수 있으면 두 줄의 코드입니다. 여기에 내 답변을 참조 하십시오 .
편집하다
다음은 T 목록에서 모든 순열 (조합이 아닌)을 반환 할 수있는 일반 함수입니다.
static IEnumerable<IEnumerable<T>>
GetPermutations<T>(IEnumerable<T> list, int length)
{
if (length == 1) return list.Select(t => new T[] { t });
return GetPermutations(list, length - 1)
.SelectMany(t => list.Where(e => !t.Contains(e)),
(t1, t2) => t1.Concat(new T[] { t2 }));
}
예:
IEnumerable<IEnumerable<int>> result =
GetPermutations(Enumerable.Range(1, 3), 3);
출력-정수 목록 :
{1,2,3} {1,3,2} {2,1,3} {2,3,1} {3,1,2} {3,2,1}
이 함수는 LINQ를 사용하므로 .net 3.5 이상이 필요합니다.
답변
여기에서 해결책을 찾았습니다. Java로 작성되었지만 C #으로 변환했습니다. 도움이 되길 바랍니다.
C #의 코드는 다음과 같습니다.
static void Main(string[] args)
{
string str = "ABC";
char[] charArry = str.ToCharArray();
Permute(charArry, 0, 2);
Console.ReadKey();
}
static void Permute(char[] arry, int i, int n)
{
int j;
if (i==n)
Console.WriteLine(arry);
else
{
for(j = i; j <=n; j++)
{
Swap(ref arry[i],ref arry[j]);
Permute(arry,i+1,n);
Swap(ref arry[i], ref arry[j]); //backtrack
}
}
}
static void Swap(ref char a, ref char b)
{
char tmp;
tmp = a;
a=b;
b = tmp;
}
답변
재귀 는 필요하지 않습니다. 여기 에이 솔루션에 대한 좋은 정보가 있습니다.
var values1 = new[] { 1, 2, 3, 4, 5 };
foreach (var permutation in values1.GetPermutations())
{
Console.WriteLine(string.Join(", ", permutation));
}
var values2 = new[] { 'a', 'b', 'c', 'd', 'e' };
foreach (var permutation in values2.GetPermutations())
{
Console.WriteLine(string.Join(", ", permutation));
}
Console.ReadLine();
나는 수년 동안이 알고리즘을 사용해 왔으며 각 순열 을 계산하기 위해 O (N) 시간 과 공간이 복잡합니다 .
public static class SomeExtensions
{
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(this IEnumerable<T> enumerable)
{
var array = enumerable as T[] ?? enumerable.ToArray();
var factorials = Enumerable.Range(0, array.Length + 1)
.Select(Factorial)
.ToArray();
for (var i = 0L; i < factorials[array.Length]; i++)
{
var sequence = GenerateSequence(i, array.Length - 1, factorials);
yield return GeneratePermutation(array, sequence);
}
}
private static IEnumerable<T> GeneratePermutation<T>(T[] array, IReadOnlyList<int> sequence)
{
var clone = (T[]) array.Clone();
for (int i = 0; i < clone.Length - 1; i++)
{
Swap(ref clone[i], ref clone[i + sequence[i]]);
}
return clone;
}
private static int[] GenerateSequence(long number, int size, IReadOnlyList<long> factorials)
{
var sequence = new int[size];
for (var j = 0; j < sequence.Length; j++)
{
var facto = factorials[sequence.Length - j];
sequence[j] = (int)(number / facto);
number = (int)(number % facto);
}
return sequence;
}
static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
private static long Factorial(int n)
{
long result = n;
for (int i = 1; i < n; i++)
{
result = result * i;
}
return result;
}
}
답변
void permute (char *str, int ptr) {
int i, len;
len = strlen(str);
if (ptr == len) {
printf ("%s\n", str);
return;
}
for (i = ptr ; i < len ; i++) {
swap (&str[ptr], &str[i]);
permute (str, ptr + 1);
swap (&str[ptr], &str[i]);
}
}
교체 기능을 작성하여 문자를 교체 할 수 있습니다.
이것은 permute (string, 0);
답변
우선, 집합에는 문자열이나 정수가 아닌 순열이 있으므로 “문자열의 문자 집합”을 의미한다고 가정하겠습니다.
크기 n의 집합에는 n이 있습니다! n 순열.
k = 1 … n으로 호출 된 다음 의사 코드 (Wikipedia에서)! 모든 순열을 제공합니다.
function permutation(k, s) {
for j = 2 to length(s) {
swap s[(k mod j) + 1] with s[j]; // note that our array is indexed starting at 1
k := k / j; // integer division cuts off the remainder
}
return s;
}
다음은 동등한 파이썬 코드입니다 (0 기반 배열 인덱스 용).
def permutation(k, s):
r = s[:]
for j in range(2, len(s)+1):
r[j-1], r[k%j] = r[k%j], r[j-1]
k = k/j+1
return r
답변
C #에서 약간 수정 된 버전으로, 모든 유형의 배열에서 필요한 순열이 생성됩니다.
// USAGE: create an array of any type, and call Permutations()
var vals = new[] {"a", "bb", "ccc"};
foreach (var v in Permutations(vals))
Console.WriteLine(string.Join(",", v)); // Print values separated by comma
public static IEnumerable<T[]> Permutations<T>(T[] values, int fromInd = 0)
{
if (fromInd + 1 == values.Length)
yield return values;
else
{
foreach (var v in Permutations(values, fromInd + 1))
yield return v;
for (var i = fromInd + 1; i < values.Length; i++)
{
SwapValues(values, fromInd, i);
foreach (var v in Permutations(values, fromInd + 1))
yield return v;
SwapValues(values, fromInd, i);
}
}
}
private static void SwapValues<T>(T[] values, int pos1, int pos2)
{
if (pos1 != pos2)
{
T tmp = values[pos1];
values[pos1] = values[pos2];
values[pos2] = tmp;
}
}