这是一个猎头发来的算法题,写了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<word.length; 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; i<arr.count - 1; i++) {
NSString *firstWord = arr[i];
NSString *secondeWord = arr[i+1];
//记录有几个字母不同
NSInteger diffCount = 0;
for (int i = 0; i<firstWord.length; 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; i<arr.count - 1; i++) {
for (NSInteger j=i+1; j<arr.count; j++) {
if ([self isEqualArr1:arr[i] Arr2:arr[j]]) {
[indexArr addObject:@(j)];
}
}
}
//给index数组降序排序
for (NSInteger i=0; i<indexArr.count-1; i++) {
for (NSInteger j=i+1; j<indexArr.count; 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<indexArr.count; 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<arr1.count; 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