词语接龙算法

这是一个猎头发来的算法题,写了4个小时终于写完了。




#import "ViewController.h"


@interface ViewController ()

//存放所有的排列组合的数组

@property (nonatomic, strong) NSMutableArray *allSorts;


//存放符合要求的组合的数组

@property (nonatomic, strong) NSMutableArray *result;

@end



@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    /*

     start = "hlt"

     end = "cag"

     dict = ["hat","dat","dag","lat","lag"]

     [

     ["hlt","hat","dat","dag","cag"],

     ["hlt","hat","lat","lag","cag"]

     ]

     •每次只有一个字母可以被改变

     •每个中间词必须存在于词典

     

     所有字具有相同的长度。

     所有关键词只包含小写字母。

     */

    

    NSMutableArray *dicList = [NSMutableArray arrayWithArray:@[@"hat",@"dat",@"dag",@"lat",@"lag"]];

    

    //调用了这个方法后,result数组中会存储所有符合条件数组。

    [self findPathWithStar:@"hlt" End:@"cag" dicList:dicList];

    

    if (self.result.count > 0) {

        NSLog(@"%@",self.result);

    } else {

        NSLog(@"没有符合条件的组合");

    }

    

}


#pragma mark: 执行此方法

- (void)findPathWithStar:(NSString *)start End:(NSString *)end dicList:(NSMutableArray *)list {

    if (![self checkWordISLowercase:start End:end dicList:list]) {

        NSLog(@"单词必须全是小写,请重新输入");

        return;

    }

    if (start.length == end.length) {

        for (NSString *word in list) {

            if (word.length != start.length) {

                //长度必须全部相同。

                NSLog(@"长度必须相同");

                return;

            }

        }

    }

    //获取所有的排列组合

    [self allSortsWithList:list Start:0 End:list.count - 1];

    

    for (NSMutableArray *arr in self.allSorts) {

        //首尾替换成 start end

        [arr replaceObjectAtIndex:0 withObject:start];

        [arr replaceObjectAtIndex:arr.count - 1 withObject:end];

        

        //比较相邻的连个单词,并保存符合条件的数组

        [self compareClosestWord:arr];

        

    }

    //去除重复的数组

    [self removeRepeatArr:self.result];

}


//检查所有单词是否全是小写

- (BOOL)checkWordISLowercase:(NSString *)start End:(NSString *)end dicList:(NSArray *)list {

    if ([self wordIsLowerCase:start] && [self wordIsLowerCase:end]) {

        for (NSString *word in list) {

            if (![self wordIsLowerCase:word]) {

                //NSLog(@"第一个不符合标准的单词:%@", word);

                return false;

            }

        }

        //NSLog(@"全是小写,符合条件");

        return true;

    }

    

    

    return false;

}


//检查单词是否全是小写

- (BOOL)wordIsLowerCase:(NSString *)word {

    for (int i=0; i

        char c = [word characterAtIndex:i];

        if (c < 'a' || c > 'z') {

            NSLog(@"单词不全是小写字母,返回False");

            return false;

        }

    }

    

    return true;

}


//获取所有的排列组合

- (void)allSortsWithList:(NSMutableArray *)list Start:(NSInteger)start End:(NSInteger)end {

    if (start == end) {

        // 为新的排列组合创建一个数组容器

        NSMutableArray *newArr = [NSMutableArray arrayWithCapacity:list.count];

        for (int i=0; i<=end; i++) {

            newArr[i] = list[i];

        }

        // 将新的排列组合存放起来

        [self.allSorts addObject:newArr];

    } else {

        for (NSInteger i = start; i<=end; i++) {

            // 交换数组第一个元素与后续的元素

            NSString *tempStr = list[start];

            list[start] = list[i];

            list[i] = tempStr;

            // 后续元素递归全排列

            [self allSortsWithList:list Start:start + 1 End:end];

            // 将交换后的数组还原

            list[i] = list[start];

            list[start] = tempStr;

        }

    }

}


//比较数组中相邻的连个单词,若全都只有一个字母不同,那么保存此数组

- (void)compareClosestWord:(NSArray *)arr {

    

    for (int i=0; i1; i++) {

        NSString *firstWord = arr[i];

        NSString *secondeWord = arr[i+1];

        //记录有几个字母不同

        NSInteger diffCount = 0;

        for (int i = 0; i

            NSString *c1 = [firstWord substringWithRange:NSMakeRange(i, 1)];

            NSString *c2 = [secondeWord substringWithRange:NSMakeRange(i, 1)];

            if (c1 != c2) {

                diffCount++;

                if (diffCount >= 2) {

                    return;

                }

            }

            

        }

    }

    [self.result addObject:arr];

}


//去除 result 中重复的数组

- (void)removeRepeatArr:(NSMutableArray *)arr {

    if (arr.count < 2) {

        // result 中的元素个数小于 2 个时,直接return

        return;

    }

    //这里用C语言数组更简单,但是声明C语言数组时必须指定长度,如果不指定长度,程序会莫名的崩掉

    NSMutableArray *indexArr = [NSMutableArray array];

    //比较出重复的数组,记录下标

    for (NSInteger i=0; i1; i++) {

        for (NSInteger j=i+1; j

            if ([self isEqualArr1:arr[i] Arr2:arr[j]]) {

                [indexArr addObject:@(j)];

            }

            

        }


        

    }

    

    //index数组降序排序

    for (NSInteger i=0; i1; i++) {

        for (NSInteger j=i+1; j

            NSInteger m = [indexArr[i] intValue];

            NSInteger n = [indexArr[j] intValue];

            if (m < n) {

                [indexArr replaceObjectAtIndex:i withObject:@(n)];

                [indexArr replaceObjectAtIndex:j withObject:@(m)];

                

            }

        }

    }

    //从后往前,移除重复元素

    for (NSInteger i=0; i

        [arr removeObjectAtIndex:[indexArr[i] intValue]];

    }

}


//比较两个数组中的元素是否相同(元素相同,元素排列顺序也相同)

- (BOOL)isEqualArr1:(NSArray *)arr1 Arr2:(NSArray *)arr2 {

    if (arr1.count != arr2.count) {

        return  false;

    }

    for (int i=0; i

        if (arr1[i] != arr2[i]) {

            return false;

        }

    }

    return true;

}

//懒加载创建存放所有排列组合的数组

- (NSMutableArray *)allSorts {

    if (!_allSorts) {

        _allSorts = [NSMutableArray array];

    }

    

    return _allSorts;

}


- (NSMutableArray *)result {

    if (!_result) {

        _result = [NSMutableArray array];

    }

    return _result;

}

@end



你可能感兴趣的:(iOS)