回溯法枚舉,輸入任意整數N,返回由相同數字組成的大於該整數N的最小整數

輸入任意整數N,返回由相同數字組成的大於該整數N的最小整數, 比如,輸入15432 ,輸出 21345.

剛開始拿到這個題很懵,沒有什麼思路 , 最小的肯定是這些數字升序 -> 12345 , 最大的是這些數字降序排列 ->54321 , 至於中間的數字有什麼規律,確實沒有找到 ,索性 最差咱們還有枚舉法,總是能求出來的.
既然是枚舉類型,最常用的就是用for循環枚舉,但是這個比較特別,因爲這個N的位數是不確定的,看樣子只能用遞歸了.計算出一個結果後,還需要去掉本次計算痕跡, 這是最基礎的枚舉,後面可以利用這個枚舉做篩選排序,找出最小值.


- (void)viewDidLoad {
    [super viewDidLoad];
    

    NSArray * array = @[@1,@2,@3,@4,@5,];
    
    [self getNumWithCurrent:0 WithLeftArray:array];
    
    NSLog(@"self.resultArray.count : %lu",(unsigned long)self.resultArray.count);
    
}

/// 遞歸計算出一個數字
- (NSInteger)getNumWithCurrent:(NSInteger)currentNum WithLeftArray:(NSArray *)leftArray {
    
    // 數組中沒有元素了,說明遍歷完成,返回當前值即可
    if (leftArray.count==0) {
        return currentNum;
    }
    
    // 遍歷剩餘的數組
    for (NSNumber * num in leftArray) {
        // 把currentNum*10 , 取出數組的元素,加到最後一位
        currentNum *= 10;
        currentNum += [num integerValue];
        
        // 剩餘數組中移除選中的元素,進行下一次遞歸
        NSMutableArray * next = [leftArray mutableCopy];
        [next removeObjectAtIndex:[next indexOfObject:num]];
        NSInteger result =  [self getNumWithCurrent:currentNum WithLeftArray:next];
        
        // 遞歸有了結果,保存結果
        if (result != 0) {
            NSLog(@"遞歸計算出結果:%@",@(result));
            [self.resultArray addObject:@(result)];
        }
        
        // 回溯到初始位置,準備下一次的循環
        currentNum -=[num integerValue];
        currentNum /=10;

    }
    return 0;
}

- (NSMutableArray<NSNumber *> *)resultArray {
    if (_resultArray == nil) {
        _resultArray = [NSMutableArray array];
    }
    return _resultArray;
}

有了枚舉的方法 , 剩下的就簡單了, 核心在於枚舉方法,(遞歸+回溯)
1.把原始數字分解成NSNumber加入到數組
2.枚舉出所有的結果,把比原始數字大的加入到result數組
3.遍歷找出result數組中的最小值.


#import "ViewController.h"

@interface ViewController ()

@property (nonatomic,strong) NSMutableArray<NSNumber *> * resultArray ;

@property (nonatomic,assign) NSInteger originalNum ;

@end

@implementation ViewController



- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self findBiggerNum:15432];
    
}

- (NSInteger)findBiggerNum:(NSInteger)oldNum {
    
    _originalNum = oldNum ;
    NSMutableArray * array = [NSMutableArray array];
    while (oldNum>0) {
        NSInteger temp = oldNum%10;
        [array addObject:@(temp)];
        oldNum = oldNum/10;
    }
    
    [self getNumWithCurrent:0 WithLeftArray:array];
    
    NSLog(@"self.resultArray.count : %lu",(unsigned long)self.resultArray.count);
    
    
    // 找出數組中的最小值
//    NSInteger result = NSIntegerMax;
//    for (NSNumber * temp in self.resultArray) {
//        if (temp.integerValue<result) {
//            result = temp.integerValue;
//        }
//    }
    // 騷方法,找出最小值
    NSInteger result = [[self.resultArray valueForKeyPath:@"@min.integerValue"] integerValue];

    NSLog(@"找到了 : %@",@(result) );

    return result;
}


/// 遞歸計算出一個數字
- (NSInteger)getNumWithCurrent:(NSInteger)currentNum WithLeftArray:(NSArray *)leftArray {
    
    // 數組中沒有元素了,說明遍歷完成,返回當前值即可
    if (leftArray.count==0) {
        return currentNum;
    }
    
    // 遍歷剩餘的數組
    for (NSNumber * num in leftArray) {
        // 把currentNum*10 , 取出數組的元素,加到最後一位
        currentNum *= 10;
        currentNum += [num integerValue];
        
        // 剩餘數組中移除選中的元素,進行下一次遞歸
        NSMutableArray * next = [leftArray mutableCopy];
        [next removeObjectAtIndex:[next indexOfObject:num]];
        NSInteger result =  [self getNumWithCurrent:currentNum WithLeftArray:next];
        
        // 遞歸有了結果,保存結果
        if (result != 0) {
            NSLog(@"遞歸計算出結果:%@",@(result));
            if (result>_originalNum) {
                [self.resultArray addObject:@(result)];
            }
            
        }
        
        // 回溯到初始位置,準備下一次的循環
        currentNum -=[num integerValue];
        currentNum /=10;

    }
    return 0;
}

- (NSMutableArray<NSNumber *> *)resultArray {
    if (_resultArray == nil) {
        _resultArray = [NSMutableArray array];
    }
    return _resultArray;
}

@end

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章