美文网首页iOS 开发 Objective-C 信息
第十四篇:Objective-C 知识回顾架算法

第十四篇:Objective-C 知识回顾架算法

作者: 望穿秋水小作坊 | 来源:发表于2019-12-12 10:46 被阅读0次
主要算法大纲
问题一: 请实现字符串反转的算法。

主要思路:两个指针分别指向字符串的一头一尾地址,然后交换两个指针的内容,交换完毕后,指针从两端向中间移动,重复交换和移动操作。直到 begin 指针的地址大于等于 end 指针,就结束程序完成交互。

// code 
void characterReverse(char* cha) {
    char* begin = &cha[0];
    char* end = cha + strlen(cha) - 1;
    
    while (begin < end) {
        char temp = *begin;
        *(begin++) = *end;
        *(end--) = temp;
    }
}

// usage
- (void)learnCharacterReverse {
    char cha[]= "Hello,World";
    characterReverse(cha);
    printf("reverse result is %s \n", cha);
}
问题二: 请实现链表的反转。

主要思路:创建两个指针,一个用来存放反转的新链表,一个用来存当前链表。利用头插法,把旧链表上的数据一个个插入新链表的头部。特别注意一点在于,要先存链表的下一个结点,不然插入之后会丢失链表数据。

// .h
#import <Foundation/Foundation.h>
struct Node {
    int data;
    struct Node* next;
};
@interface ChainReverse : NSObject
// 链表反转
struct Node* chain_reverse(struct Node* head);
// 构建一个列表
struct Node* constructionChains(void);
// 打印链表
void printChain(struct Node *head);
@end


// .m文件
#import "ChainReverse.h"
@implementation ChainReverse
// 链表反转
struct Node* chain_reverse(struct Node* head) {
    // 定义遍历指针,初始化头结点
    struct Node* p = head;
    // 反转后的链表头部
    struct Node *newH = NULL;
    
    // 遍历链表
    while (p != NULL) {
        // 先记录下一个结点
        struct Node* temp = p->next;
        // 当前结点的 nex 执行新链表的头部
        p->next = newH;
        // 更改新链表头部为当前结点
        newH = p;
        // 移动 p 指针
        p = temp;
    }
    return newH;
};
// 构建一个列表
struct Node* constructionChains(void) {
    struct Node* head = NULL;
    struct Node* cur = NULL;
    
    for (int i = 1 ; i < 5;  i++) {
        struct Node *node = malloc(sizeof(struct Node));
        node->data = i;
        node->next = NULL;
        
        if (head == NULL) {
            head = node;
        } else {
            cur->next = node;
        }
        cur = node;
    }
    return head;
}
// 打印链表
void printChain(struct Node *head) {
    struct Node* cur = NULL;
    cur = head;
    
    while (cur != NULL) {
        printf("%i \n", cur->data);
        cur = cur->next;
    };
    printf("===============\n");
}

@end


// 用法

- (void)learnChainReverse {
    struct Node* head = constructionChains();
    printChain(head);
    struct Node* newHead = chain_reverse(head);
    printChain(newHead);
}

问题三:请实现两个有序数组合并成一个有序数据的算法。

算法思路:分别从两个有序数组头部开始取数组,对比大小,把小的值插入新数组,然后小的值所在数据角标+1,如此重复,直到其中一方数组没有数据了,把另一个数组剩余的值全部插入新数组,完成合并。


// 将有序数据 a 和 b 的值合并到一个数据 result当中,且仍然保持有序
void mergeList(int a[], int aLen, int b[], int bLen, int result[]) {
    int p = 0; // 记录数组 a 的位置
    int q = 0; // j遍历数组 b 的位置
    int i = 0; // 记录当前存储 z 位置
    while (p < aLen && q < bLen) {
        if (a[p] < b[q]) {
            result[i] = a[p];
            p++;
        } else {
            result[i] = b[q];
            q++;
        }
        i++;
    }
    while (p < aLen) {
        result[i] = a[p];
        p++;
        i++;
    }
    
    while (q < bLen) {
        result[i] = b[q];
        q++;
        i++;
    }
}
问题四:请用哈希算法来实现查找字符串中第一个只出现一次的字符。

算法思路:所谓 hash 算法,就是利用哈希函数做一个映射,从而由 key 经过 f(key) 高效的找到结果。所以我们可以把字符当成 ASCII 码作为 key 并且当成一个数组的脚本,数组的 value 就是出现的次数。

char findFirstChar(char *cha) {
    // 用来移动的指针
    char *p = cha;
    // 初始化一个数组
    int array[256];
    for (int i = 0 ; i < 256; i++) {
        array[i] = 0;
    }
    // 结果存放处
    char result = '\0';
    // 遍历并且给数组赋值
    while (*p != '\0') {
        array[*(p++)]++;
    }
    p = cha;
    // 查找value 为 1 的字符
    while (*p != '\0') {
        if (array[*p] == 1) {
            result = *p;
            break;
        }
        p++;
    }
    return result;
}

问题五:查找两个子视图的共同父视图。

算法思路:先遍历找出两个子视图的所有父视图,存于两个数组;将两个数组进行反序,然后从下标 0 的位置开始对比两个数组,将相同的视图存在另一个新数组中,直到两个数组第一次出现不同视图,就可以终止循环。

- (void)learnFindCommonSupperView {
    NSMutableArray *mutableArray_A = [NSMutableArray new];
    NSMutableArray *mutableArray_B = [NSMutableArray new];
    NSMutableArray *mutableArray_Common = [NSMutableArray new];
    
    UIView *currentA = self.labelA;
    while (currentA.superview != nil) {
        [mutableArray_A addObject:currentA.superview];
        currentA = currentA.superview;
    }
    
    UIView *currentB = self.labelB;
    while (currentB.superview != nil) {
        [mutableArray_B addObject:currentB.superview];
        currentB = currentB.superview;
    }
    // 步骤的关键在于反序查找,直到第一个不同的视图终止
    mutableArray_A = [[[mutableArray_A reverseObjectEnumerator] allObjects] mutableCopy];
    mutableArray_B = [[[mutableArray_B reverseObjectEnumerator] allObjects] mutableCopy];
    
    for (int i = 0; i < mutableArray_A.count && i < mutableArray_B.count; i++) {
        UIView *a = mutableArray_A[i];
        UIView *b = mutableArray_B[i];
        
        if (a == b) {
            [mutableArray_Common addObject:a];
            // 为了标记已经找到的共同父视图,标记为红色
            a.backgroundColor = [UIColor redColor];
            a.layer.borderWidth = 1;
            a.layer.borderColor = [UIColor whiteColor].CGColor;
        } else {
            break;
        }
    }
    
    NSLog(@"一共有 %lu 个父视图", (unsigned long)mutableArray_Common.count);
}

相关文章

网友评论

    本文标题:第十四篇:Objective-C 知识回顾架算法

    本文链接:https://www.haomeiwen.com/subject/nfrggctx.html