nod*_*nja 8 cocoa-touch permutation objective-c nsnumber nsarray
假设我有一个像这样的NSNr NSArray:1,2,3
那么所有可能排列的集合看起来像这样:
1,2,3
1,3,2
2,1,3
2,3,1
3,1,2
3,2,1
在objective-c中执行此操作的好方法是什么?
我使用了Wevah上面的答案中的代码并发现了它的一些问题所以我在这里进行了一些改进以使其正常工作:
NSArray的+ Permutation.h
@interface NSArray(Permutation)
- (NSArray *)allPermutations;
@end
Run Code Online (Sandbox Code Playgroud)
NSArray的+ Permutation.m
#import "NSArray+Permutation.h"
#define MAX_PERMUTATION_COUNT 20000
NSInteger *pc_next_permutation(NSInteger *perm, const NSInteger size);
NSInteger *pc_next_permutation(NSInteger *perm, const NSInteger size)
{
// slide down the array looking for where we're smaller than the next guy
NSInteger pos1;
for (pos1 = size - 1; perm[pos1] >= perm[pos1 + 1] && pos1 > -1; --pos1);
// if this doesn't occur, we've finished our permutations
// the array is reversed: (1, 2, 3, 4) => (4, 3, 2, 1)
if (pos1 == -1)
return NULL;
assert(pos1 >= 0 && pos1 <= size);
NSInteger pos2;
// slide down the array looking for a bigger number than what we found before
for (pos2 = size; perm[pos2] <= perm[pos1] && pos2 > 0; --pos2);
assert(pos2 >= 0 && pos2 <= size);
// swap them
NSInteger tmp = perm[pos1]; perm[pos1] = perm[pos2]; perm[pos2] = tmp;
// now reverse the elements in between by swapping the ends
for (++pos1, pos2 = size; pos1 < pos2; ++pos1, --pos2) {
assert(pos1 >= 0 && pos1 <= size);
assert(pos2 >= 0 && pos2 <= size);
tmp = perm[pos1]; perm[pos1] = perm[pos2]; perm[pos2] = tmp;
}
return perm;
}
@implementation NSArray(Permutation)
- (NSArray *)allPermutations
{
NSInteger size = [self count];
NSInteger *perm = malloc(size * sizeof(NSInteger));
for (NSInteger idx = 0; idx < size; ++idx)
perm[idx] = idx;
NSInteger permutationCount = 0;
--size;
NSMutableArray *perms = [NSMutableArray array];
do {
NSMutableArray *newPerm = [NSMutableArray array];
for (NSInteger i = 0; i <= size; ++i)
[newPerm addObject:[self objectAtIndex:perm[i]]];
[perms addObject:newPerm];
} while ((perm = pc_next_permutation(perm, size)) && ++permutationCount < MAX_PERMUTATION_COUNT);
free(perm);
return perms;
}
@end
Run Code Online (Sandbox Code Playgroud)
可能有更好的方法(就地或其他),但这似乎有效:
标题:
@interface NSArray (PermutationAdditions)
- (NSArray *)allPermutations;
@end
Run Code Online (Sandbox Code Playgroud)
Implemetation:
@implementation NSArray (PermutationAdditions)
NSInteger *pc_next_permutation(NSInteger *p, const NSInteger size) {
// slide down the array looking for where we're smaller than the next guy
NSInteger i;
for (i = size - 1; p[i] >= p[i + 1]; --i) { }
// if this doesn't occur, we've finished our permutations
// the array is reversed: (1, 2, 3, 4) => (4, 3, 2, 1)
if (i == -1)
return NULL;
NSInteger j;
// slide down the array looking for a bigger number than what we found before
for (j = size; p[j] <= p[i]; --j) { }
// swap them
NSInteger tmp = p[i]; p[i] = p[j]; p[j] = tmp;
// now reverse the elements in between by swapping the ends
for (++i, j = size; i < j; ++i, --j) {
tmp = p[i]; p[i] = p[j]; p[j] = tmp;
}
return p;
}
- (NSArray *)allPermutations {
NSInteger size = [self count];
NSInteger *perm = malloc(size * sizeof(NSInteger));
for (NSInteger idx = 0; idx < size; ++idx)
perm[idx] = idx;
NSInteger j = 0;
--size;
NSMutableArray *perms = [NSMutableArray array];
do {
NSMutableArray *newPerm = [NSMutableArray array];
for (NSInteger i = 0; i <= size; ++i)
[newPerm addObject:[self objectAtIndex:perm[i]]];
[perms addObject:newPerm];
} while ((perm = pc_next_permutation(perm, size)) && ++j);
return perms;
}
@end
Run Code Online (Sandbox Code Playgroud)
要使用它,只#import需要头文件,然后调用[yourArray allPermutations]; 该方法将返回包含每个排列的数组的数组.
[代码改编自PHP代码在这里.]
您可以更改NSString *characters为id something并将其用于任何类型的对象
NSArray *array = [NSArray arrayWithObjects:@"a",@"b",@"c", nil];
NSMutableArray *permutations = nil;
int i = 0;
for (i = 0; i < array.count ; i++){
if (!permutations){
permutations = [NSMutableArray array];
for (NSString *character in array){
[permutations addObject:[NSArray arrayWithObject:character]];
}
} else {
//make copy of permutations array and clean og array
NSMutableArray *aCopy = [permutations mutableCopy];
[permutations removeAllObjects];
for (NSString *character in array){
//loop through the copy
for (NSArray *oldArray in aCopy){
//check if old string contains looping char..
if ([oldArray containsObject:character] == NO){
//update array
NSMutableArray *newArray = [NSMutableArray arrayWithArray:oldArray];
[newArray addObject:character];
//add to permutations
[permutations addObject:newArray];
}
}
}
}
}
NSLog(@"permutations = \n %@",permutations);
Run Code Online (Sandbox Code Playgroud)