2013-06-07 11 views
5

私はNSMutableArrayを保持しています。NSStringsです。 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}最適化された配列シフト方法

ラッピングで要素を移動したいと考えています。

1を中心に移動し、すべての要素をシフトし、残りの要素(境界をまたぐ)を先頭に折り返します。 10を中心にする。

{7, 8, 9, 10, 1, 2, 3, 4, 5, 6}{6, 7, 8, 9, 10, 1, 2, 3, 4, 5}

これは、既存のように最適化されたsort方法はありますか?

+1

-insertObjects:atIndexes: 0 7-10。配列の大きさである 'k + m = n'である。しかし、私はそのような標準的なアルゴリズムを認識していません。 –

+0

@PraveenS - 'trueIndex =(オフセット+インデックス)%array.count'。私はそれが線形時間よりも優れていると思う。 –

答えて

2

最も効率的なアプローチは、配列の現在の "原点"を維持し、その原点をモジュロにしてインデックスを再解釈するラッパーオブジェクトを作成することです。実際、アレイが少数の場所でのみアクセスされる場合、これは1-2行のコードをインラインで簡単に実行できます。

-(id)objectForIndex:(NSInteger) index { 
    NSInteger realIndex = (origin + index) % array.count; 
    return [array objectAtIndex:realIndex]; 
} 

(これはNS(変更可能な)アレイを拡張する場合、「アレイ」は、「スーパー」である。のみラッパーは、次いで、「アレイ」は、インスタンスVARである場合、「原点」はいずれの場合も、インスタンスVAR /プロパティであります。)

+0

スマートで、突然変異する必要はありません。 – jarryd

+0

モジュロ!天才! –

0

Nで移動している場合は、最後にNの配列要素を取り、正面に貼り付けてください。

他の方法でシフトしている場合は、正面を取って後ろに置いてください。

2

私は、このためにNSArray上の任意の方法を知らないんだけど、:

static NSArray *shiftArray(NSArray *array, NSInteger pos) 
{ 
    NSInteger length = [array count]; 
    NSArray *post = [array subarrayWithRange:(NSRange){ .location = length - pos, .length = pos }]; 
    NSArray *pre = [array subarrayWithRange:(NSRange){ .location = 0, .length = length - pos}]; 
    return [post arrayByAddingObjectsFromArray:pre]; 
} 

例えば:

NSArray *array = @[@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I"]; 
NSLog(@"array = %@",shiftArray(array, 4)); 

はあなたが記述何をすべき。コンソールへ

ログ:パフォーマンス

array = (
    F, 
    G, 
    H, 
    I, 
    A, 
    B, 
    C, 
    D, 
    E 
) 

そうにありません。

0

回転は、基本的に、配列の一端からN個の要素を取り、代わりにそれらを配置することによって行われます。必要ならば不変の配列でこれを行うことができますが、可変配列はややクリーンな実装を提供します。左ローテート用

、最も簡単な方法は、単に、おそらくです:

// Make sure we don't overrun the array if the rotation is larger. 
numberOfObjectsToRotateLeft %= array.count; 

NSRange range = NSMakeRange(0, numberOfObjectsToRotateLeft); 
NSMutableArray * rotatedArray = [array mutableCopy]; 

[rotatedArray addObjectsFromArray:[rotatedArray subarrayWithRange:range]]; 
[rotatedArray removeObjectsInRange:range]; 

// now return or use rotatedArray 

回し右似ていますが、範囲が配列の末尾になり、そしてあなたは、インデックスから始まるオブジェクトを挿入したいです私たちは1 `for`ループ、1と線形時間で最初の` K 'の要素が残っている' M 'の要素、すなわち1-6と次を言うためにそれを行うことができると思い

// Make sure we don't overrun the array if the rotation is larger. 
numberOfObjectsToRotateRight %= array.count; 

NSRange range = NSMakeRange(array.count - numberOfObjectsToRotateRight, numberOfObjectsToRotateRight); 
NSMutableArray * rotatedArray = [array mutableCopy]; 

NSArray * movedObjects = [rotatedArray subarrayWithRange:range]; 
[rotatedArray removeObjectsInRange:range]; 
[rotatedArray insertObjects:movedObjects atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, numberOfObjectsToRotateRight)]]; 

// now return or use rotatedArray 
1
-(NSArray*)shiftForward:(BOOL)forward withbits:(int)bit 
{ 
    NSInteger length = [array count]; 
    NSArray *right; 
    NSArray *left; 

    if (forward) { 
     //code for right shift 
     right = [array subarrayWithRange:(NSRange){ .location = length - bit, .length = bit }]; 
     left = [array subarrayWithRange:(NSRange){ .location = 0, .length = length - bit}]; 
     return [right arrayByAddingObjectsFromArray:left]; 
    }else{ 
     //code for left shift 
     left = [array subarrayWithRange:(NSRange){ .location =0, .length = bit }]; 
     right= [array subarrayWithRange:(NSRange){ .location = bit, .length = length - bit}]; 
     return [right arrayByAddingObjectsFromArray:left]; 
    } 
} 

- (void)viewDidLoad 
{ 
    array = @[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9"]; 
    NSLog(@"array is %@",[self shiftForward:YES withbits:3]); 
} 
関連する問題