生成NSArray元素的排列

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中执行此操作的好方法是什么?

Peg*_*lon 8

我使用了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)


Wev*_*vah 5

可能有更好的方法(就地或其他),但这似乎有效:

标题:

@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代码在这里.]


ssj*_*ssj 5

您可以更改NSString *charactersid 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)