From dcaadf24df08ba60efbf746e6e6dbf2dd88beeb7 Mon Sep 17 00:00:00 2001 From: Mengmeng Zhang Date: Sat, 20 Apr 2019 14:29:40 +0800 Subject: [PATCH 1/5] 010-Geek Signed-off-by: Mengmeng Zhang --- Week_01/id_10/allSortMethodAndBiSearch.m | 467 ++++++++++ Week_01/id_10/deleteDuplicates.c | 36 + Week_01/id_10/isValid.c | 29 + ...25\347\254\254\344\270\200\345\221\250.md" | 839 ++++++++++++++++++ 4 files changed, 1371 insertions(+) create mode 100644 Week_01/id_10/allSortMethodAndBiSearch.m create mode 100644 Week_01/id_10/deleteDuplicates.c create mode 100644 Week_01/id_10/isValid.c create mode 100644 "Week_01/id_10/\347\256\227\346\263\225\347\254\254\344\270\200\345\221\250.md" diff --git a/Week_01/id_10/allSortMethodAndBiSearch.m b/Week_01/id_10/allSortMethodAndBiSearch.m new file mode 100644 index 00000000..904f3f3c --- /dev/null +++ b/Week_01/id_10/allSortMethodAndBiSearch.m @@ -0,0 +1,467 @@ +// +// ViewController.m +// Lesson1 +// +// Created by Mengmeng Zhang on 2019/4/18. +// Copyright © 2019年 Mengmeng Zhang. All rights reserved. +// + +#import "ViewController.h" + +@interface ViewController () +@property (nonatomic,strong)NSMutableArray * reslutArray; +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. + NSMutableArray * array = [NSMutableArray arrayWithObjects:@2,@22,@12,@12,@12,@224,@112,@32,@62,@63,@3, nil]; + + + self.reslutArray = [NSMutableArray arrayWithCapacity:0]; + // [self mergeArray:[NSMutableArray arrayWithObjects:@1,@11,@16,@19,@110, nil] right:[NSMutableArray arrayWithObjects:@2,@21,@36,@49,@100,@101, nil] result:self.reslutArray]; + // [self mergeSort:array]; + + NSLog(@"pos-%ld",[self binarySearch:array value:112]) ; + NSLog(@"posfirst-%ld",[self binarySearch:array firstValue:12]) ; + NSLog(@"poslast-%ld",[self binarySearch:array lastValue:13]) ; + NSLog(@"posfirstbig-%ld",[self binarySearch:array firstBigValue:23]); + NSLog(@"poslastsmall-%ld",[self binarySearch:array lastSmallValue:23]); + //求第K小 + NSLog(@"findk:%ld",[self findK:array begin:0 end:array.count-1 indexOfK:6]); + // [self quickSort:array left:0 right:array.count-1 k:8]; + [self quickSort:array begin:0 end:array.count-1]; + NSLog(@"%@",array); + [self quickSort:array left:0 right:array.count-1]; + NSLog(@"%@",array); +} +//bubblesort +/* + 注意值得比较 比较方式:相邻元素比较 + 优化:1.比较次数 2.提前退出标志 + */ +- (void)bubbleSort:(NSMutableArray*)array { + if (array == nil) { + return; + } + if (array.count <= 1) { + return; + } + for (NSInteger i = 0;i < array.count;i++) { + NSInteger flag = 0; + for (NSInteger j = 0;j < array.count-1-i;j++) { + if ([array[j] integerValue] > [array[j+1] integerValue]) { + NSInteger temp = [array[j] integerValue]; + array[j] = array[j+1]; + array[j+1] = [NSNumber numberWithInteger:temp]; + flag = 1; + } + } + if (!flag) { + return; + } + } +} +//selectSort +/* + 比较方式:每个位置依次找到最大最小值,依次比较 + 优化:记录最小值位置,交换次数优化 + */ +- (void)selectSort:(NSMutableArray*)array { + if (array == nil) { + return; + } + if (array.count <= 1) { + return; + } + for (NSInteger i = 0;i < array.count;i++) { + NSInteger minPos = i; + for (NSInteger j = i+1; j < array.count;j++) { + if ( [array[minPos] integerValue] > [array[j] integerValue]) { + minPos = j; + } + if (j == array.count - 1) { + NSInteger temp = [array[minPos] integerValue]; + array[minPos] = array[i]; + array[i] = [NSNumber numberWithInteger:temp]; + } + } + + } + +} +//insertSort +/* + 元素比较,元素移动 + 已排序区间 + */ +- (void)insertSort:(NSMutableArray*)array { + if (array == nil) { + return; + } + if (array.count <= 1) { + return; + } + for (NSInteger i = 1;i < array.count;i++) { + //要插入的数据 + NSInteger temp = [array[i] integerValue]; + NSInteger j = i-1; + //已排序区间 + for (;j >= 0;--j) { + //查找插入位置 + if ([array[j] integerValue] > temp) { + //依次向后移动 + array[j+1] = array[j]; + } + else { + break; + } + + } + array[j+1] = [NSNumber numberWithInteger:temp]; + } +} +//归并排序 +- (void)mergeSort:(NSMutableArray*)array { + NSMutableArray * res = [self mergeSort:array begin:0 end:array.count-1]; + NSLog(@"res--%@",res); +} +- (NSMutableArray*)mergeSort:(NSMutableArray*)array begin:(NSInteger)begin end:(NSInteger)end { + if (begin >= end) { + return [NSMutableArray arrayWithObjects:array[begin], nil]; + } + NSInteger middle = (begin+end)/2; + NSMutableArray * leftArray = [self devidArray:array begin:begin end:middle]; + NSMutableArray * rightArray = [self devidArray:array begin:middle+1 end:end]; + [self mergeSort:leftArray begin:0 end:leftArray.count-1]; + [self mergeSort:rightArray begin:0 end:rightArray.count-1]; + NSMutableArray * res = [self mergeArray:leftArray right:rightArray ]; + return res; +} +//分割数组 +- (NSMutableArray*)devidArray:(NSMutableArray*)array begin:(NSInteger)begin end:(NSInteger)end { + NSMutableArray * reslutArray = [NSMutableArray arrayWithCapacity:0]; + for (NSInteger i = begin;i <= end;i++) { + [reslutArray addObject:array[i]]; + } + return reslutArray; +} +//合并数组 +- (NSMutableArray*)mergeArray:(NSMutableArray*)left right:(NSMutableArray*)right { + NSMutableArray * resultArray = [NSMutableArray arrayWithCapacity:0]; + NSInteger i = 0; + NSInteger j = 0; + while (i < left.count && j < right.count) { + NSInteger valueL = [left[i] integerValue]; + NSInteger valueR = [right[j] integerValue]; + if (valueL < valueR) { + [resultArray addObject:[NSNumber numberWithInteger:valueL]]; + i++; + } + else { + [resultArray addObject:[NSNumber numberWithInteger:valueR]]; + j++; + } + } + if (i < left.count) { + for (;i value) { + tail = middle - 1; + } + else if ([array[middle] integerValue] < value) { + head = middle + 1; + } + else { + return middle; + } + } + return -1; +} +//变形问题 +/* + 查找第一个值等于给定值的元素 + 查找最后一个值等于给定值得元素 + 查找第一个大于等于给定值的元素 + 查找最后一个小于等于给定值的元素 + */ +//最后一个小于等于给定值的元素 +- (NSInteger)binarySearch:(NSMutableArray*)array lastSmallValue:(NSInteger)value { + NSInteger head = 0; + NSInteger tail = array.count - 1; + while (head <= tail) { + NSInteger middle = head + (tail-head)/2; + if ([array[middle] integerValue] <= value) { + if (middle == array.count - 1) { + return middle; + } + else if (middle + 1 <= array.count - 1) { + if ([array[middle+1] integerValue] > value) { + return middle; + } + else { + head = middle + 1; + } + } + else { + head = middle + 1; + } + + } + else if ([array[middle] integerValue] > value) { + + tail = middle - 1; + } + } + return -1; +} +//第一个大于等于给定值 +- (NSInteger)binarySearch:(NSMutableArray*)array firstBigValue:(NSInteger)value { + NSInteger head = 0; + NSInteger tail = array.count - 1; + while (head <= tail) { + NSInteger middle = head + (tail-head)/2; + if ([array[middle] integerValue] >= value) { + if (middle == 0) { + return middle; + } + else if (middle - 1 >= 0) { + if ([array[middle-1] integerValue] < value) { + return middle; + } + else { + tail = middle - 1; + } + } + else { + tail = middle - 1; + } + + } + else if ([array[middle] integerValue] value) { + tail = middle - 1; + } + else if ([array[middle] integerValue] = 1) { + if ([array[middle - 1] integerValue] != value) { + return middle; + } + else { + //向前找 + tail = middle - 1; + } + } + else { + //向前找 + tail = middle - 1; + } + } + } + return -1; +} +/* + 1.是不是最后一个元素 + 2.后一个元素是不是也是value + */ +- (NSInteger)binarySearch:(NSMutableArray*)array lastValue:(NSInteger)value { + NSInteger head = 0; + NSInteger tail = array.count - 1; + while (head <= tail) { + NSInteger middle = head + (tail-head)/2; + if ([array[middle] integerValue] > value) { + tail = middle - 1; + } + else if ([array[middle] integerValue] array.count) { + return -1; + } + NSInteger pivot = [self pivot:array]; + NSInteger count = 0; + for (NSInteger i = 0;i < array.count - 1; i++) { + if ([array[i] integerValue] <= [array[pivot] integerValue]) { + [array addObject:array[i]]; + [array removeObjectAtIndex:i]; + //记录每一次插入后面的个数,则array.count - count即为当前位置是第几大 + count++; + } + } + NSInteger index = array.count - count ; + if (index == k) { + return [array[index-1] integerValue]; + } + NSMutableArray * nextArray = nil; + if (index < k) { + k = k - index; + nextArray = [self devidArray:array begin:index end:array.count-1]; + } + else { + nextArray = [self devidArray:array begin:0 end:index-2]; + } + return [self findKInArray:nextArray k:k]; +} +//简单分区函数-以数组最后一个位置为分区 +- (NSInteger)pivot:(NSArray*)array { + return array.count - 1; +} +//求第K小 +- (NSInteger)findK:(NSMutableArray*)array begin:(NSInteger)begin end:(NSInteger)end indexOfK:(NSInteger)k { + if (begin >= end) { + return -1; + } + NSInteger partition = [self partition:array left:begin right:end]; + if (partition+1 == k) { + return [array[partition] integerValue]; + } + else if (k > partition+1) { + return [self findK:array begin:partition+1 end:end indexOfK:k]; + } + else { + return [self findK:array begin:begin end:partition-1 indexOfK:k]; + } + return -1; + +} +//快速排序一 +- (void)quickSort:(NSMutableArray*)array begin:(NSInteger)begin end:(NSInteger)end { + if (begin >= end) { + return; + } + // NSInteger partition = [self partition:array left:begin right:end]; + + NSInteger i = begin; + NSInteger j = end; + NSInteger key = end; + while (i != j) { + //注意前后顺序 下面顺序反了,所以错了, 如果key改为end,则能正确输出 + //key从头,先遍历尾;key从尾,先遍历头 + while (i= [array[key] integerValue]) { + j--; + } + + if (i < j) { + [array exchangeObjectAtIndex:i withObjectAtIndex:j]; + } + + } + [array exchangeObjectAtIndex:i withObjectAtIndex:end]; + + [self quickSort:array begin:begin end:i - 1]; + [self quickSort:array begin:i + 1 end:end]; +} +//快速排序二 +- (void)quickSort:(NSMutableArray*)array left:(NSInteger)left right:(NSInteger)right { + if (left >= right) { + return; + } + NSInteger partition = [self partition:array left:left right:right]; + //继续左边的排序 + [self quickSort:array left:left right:partition - 1]; + //继续右边的排序 + [self quickSort:array left:partition + 1 right:right]; +} +//复杂分区函数 +- (NSInteger)partition:(NSMutableArray*)array left:(NSInteger)left right:(NSInteger)right { + NSInteger key = left; + NSInteger i = left; + NSInteger j = right; + while (i != j) { + while (i= [array[i] integerValue]) { + i++; + } + if (i互换位置 + [array exchangeObjectAtIndex:i withObjectAtIndex:left]; + return i; +} + + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + + +@end diff --git a/Week_01/id_10/deleteDuplicates.c b/Week_01/id_10/deleteDuplicates.c new file mode 100644 index 00000000..f4449c67 --- /dev/null +++ b/Week_01/id_10/deleteDuplicates.c @@ -0,0 +1,36 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * struct ListNode *next; + * }; + */ +struct ListNode* deleteDuplicates(struct ListNode* head) { + if (head == NULL ||head->next == NULL) { + return head; + } + struct ListNode* p = head; + int value = p->val; + while(p->next != NULL) { + if(p->next->val == value) { + deleteNode(p); + } + //边界条件 + if (p->next != NULL) { + if (p->next->val > value) { + p = p->next; + value = p->val; + } + } + } + return head; +} +//删除节点p的后继节点 +void deleteNode(struct ListNode* p) { + struct ListNode* q; + if (p->next != NULL) { + q = p->next; + p->next = q->next; + q = NULL; + } +} \ No newline at end of file diff --git a/Week_01/id_10/isValid.c b/Week_01/id_10/isValid.c new file mode 100644 index 00000000..62fe381f --- /dev/null +++ b/Week_01/id_10/isValid.c @@ -0,0 +1,29 @@ +bool isValid(char* s) { + int length = strlen(s); + char* temp = (char*)malloc(length); + int tail = 0; + for (int i = 0;i < length;i++) { + char value = s[i]; + if (value == '(' || value == '{' || value == '[' ) { + temp[tail] = value; + tail++; + } + else { + if (tail == 0) { + return false; + } + char now = temp[tail - 1]; + if ((now == '(' && value == ')') || (now == '{' && value == '}') || (now == '[' && value == ']')) { + + } + else { + return false; + } + tail--; + } + } + if (tail != 0) { + return false; + } + return true; +} \ No newline at end of file diff --git "a/Week_01/id_10/\347\256\227\346\263\225\347\254\254\344\270\200\345\221\250.md" "b/Week_01/id_10/\347\256\227\346\263\225\347\254\254\344\270\200\345\221\250.md" new file mode 100644 index 00000000..28913f9a --- /dev/null +++ "b/Week_01/id_10/\347\256\227\346\263\225\347\254\254\344\270\200\345\221\250.md" @@ -0,0 +1,839 @@ +要求 +每周至少完成给定题目中的两道算法题 +围绕每周重点学习的算法知识点,撰写一篇有观点和思考的技术文章(字数不限) +注意事项 +下面列出的题目中,按照知识点进行了简单分类,但并不意味着使用相应的数据结构或算法一定是解决该题目的最优解,这样分类只是为了方便大家有针对性的练习; +有的题目可能需要结合多个算法或数据结构进行求解。 +第一周题目 +链表 +~简单: +~简单: +中等: +中等: +困难: +数组 +~简单: +~简单: +中等: +中等: +困难: +栈 +~简单: +中等: +困难: +递归 +简单: +中等: +困难: +排序 +~简单: +中等: +困难: +二分查找 +~简单: +中等: +困难: +作业提交规则 +在提交作业之前,请先阅读这里的 README 文档: +然后在此 Issues 下按照如下格式回复(示例见一楼): +学号 + GitHub Username +作业代码的 GitHub 链接(填写自己仓库下对应的作业链接即可,同时记得给本仓库提交 pull request) +发表自己本周的学习感言 issues,并提交链接,issues 标题格式:“【学号后三位-week1】+文章标题”,格式参考:[#9](https://github.com/algorithm001/algorithm/issues/9) + +​ + +​ + + + +# 算法第一周总结 + +1.语言:C/OC + +2.环境:Leetcode/Xcode + + + +#1.数组 + +1.连续存储空间,对内存友好; + +2.随机访问第K个元素,时间复杂度O(1); + +3.删除,插入操作时间复杂度取决于移动元素,O(n); + +小栗子: + +#### [905. 按奇偶排序数组](https://leetcode-cn.com/problems/sort-array-by-parity/) + +``` +/** + * Return an array of size *returnSize. + * Note: The returned array must be malloced, assume caller calls free(). + */ +#include + +int* sortArrayByParity(int* A, int ASize, int* returnSize) { + *returnSize=ASize; + int* temp=(int*)malloc(ASize*sizeof(int)); + for (int i = 0,j = 0,k = ASize-1;i < ASize;i++) { + if (A[i] % 2 == 0) { + temp[j] = A[i]; + j++; + } + else { + temp[k] = A[i]; + k--; + } + } + return temp; +} +``` + + + +#### [922. 按奇偶排序数组 II](https://leetcode-cn.com/problems/sort-array-by-parity-ii/) + +``` +/** + * Return an array of size *returnSize. + * Note: The returned array must be malloced, assume caller calls free(). + */ +int* sortArrayByParityII(int* A, int ASize, int* returnSize) { + *returnSize=ASize; + int* temp=(int*)malloc(ASize*sizeof(int)); + for (int i = 0,j = 0,k = 1;i < ASize;i++) { + if (A[i]%2 == 0) { + temp[j] = A[i]; + j +=2; + } + else { + temp[k] = A[i]; + k += 2; + } + } + return temp; +} +``` + + + +# 2.链表 + +1.非连续存储空间,链式结构,对内存不友好; + +2.访问第K个元素,时间复杂度O(n); + +3.删除某个节点后的后继节点时间复杂度O(1),在某个节点后插入节点时间复杂度O(1); + +4.双向链表,环形链表; + + + +小栗子: + +#### [83. 删除排序链表中的重复元素](https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/) + +``` +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * struct ListNode *next; + * }; + */ +struct ListNode* deleteDuplicates(struct ListNode* head) { + if (head == NULL ||head->next == NULL) { + return head; + } + struct ListNode* p = head; + int value = p->val; + while(p->next != NULL) { + if(p->next->val == value) { + deleteNode(p); + } + //边界条件 + if (p->next != NULL) { + if (p->next->val > value) { + p = p->next; + value = p->val; + } + } + } + return head; +} +//删除节点p的后继节点 +void deleteNode(struct ListNode* p) { + struct ListNode* q; + if (p->next != NULL) { + q = p->next; + p->next = q->next; + q = NULL; + } +} +``` + + + +#### [21. 合并两个有序链表](https://leetcode-cn.com/problems/merge-two-sorted-lists/) + +``` + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * struct ListNode *next; + * }; + */ +struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) { + //向第一个比较小的链表插入,注意链表长度可能不等 + struct ListNode* w ,*head; + if (l1 == NULL) { + return l2; + } + if (l2 == NULL) { + return l1; + } + if (l1->val < l2->val) { + head = l1; + l1 = l1->next; + } + else { + head = l2; + l2 = l2->next; + } + w = head; + while(l1 != NULL && l2 != NULL) { + if (l1->val < l2->val) { + w->next = l1; + l1 = l1->next; + } + else { + w->next = l2; + l2 = l2->next; + } + w = w->next; + } + if (l1 != NULL) { + w->next = l1; + } + if (l2 != NULL) { + w->next = l2; + } + return head; +} + +``` + + + +# 3.栈与队列 + +1.栈:先进后出FILO,应用场景(1.iOS中页面导航,前进与后退;2.函数方法调用栈) + +2.队列:先进先出,应用场景(1.线程队列) + +小栗子: + +[20. 有效的括号](https://leetcode-cn.com/problems/valid-parentheses/) + +``` +bool isValid(char* s) { + int length = strlen(s); + char* temp = (char*)malloc(length); + int tail = 0; + for (int i = 0;i < length;i++) { + char value = s[i]; + if (value == '(' || value == '{' || value == '[' ) { + temp[tail] = value; + tail++; + } + else { + if (tail == 0) { + return false; + } + char now = temp[tail - 1]; + if ((now == '(' && value == ')') || (now == '{' && value == '}') || (now == '[' && value == ']')) { + + } + else { + return false; + } + tail--; + } + } + if (tail != 0) { + return false; + } + return true; +} +``` + + + +# 4.递归思想 + +1.如何写递归代码? + +1.1 递归终止条件; + +1.2 递推公式; + +小栗子:见下面归并排序,快速排序。 + +# 5.排序 + +1.时间复杂度为O(n*n): + +1.1冒泡排序(相邻元素交换,优化:1.当没有交换发生提前退出2.注意排序区间,减少遍历次数); + +``` +/* + 注意值得比较 比较方式:相邻元素比较 + 优化:1.比较次数 2.提前退出标志 + */ +- (void)bubbleSort:(NSMutableArray*)array { + if (array == nil) { + return; + } + if (array.count <= 1) { + return; + } + for (NSInteger i = 0;i < array.count;i++) { + NSInteger flag = 0; + for (NSInteger j = 0;j < array.count-1-i;j++) { + if ([array[j] integerValue] > [array[j+1] integerValue]) { + NSInteger temp = [array[j] integerValue]; + array[j] = array[j+1]; + array[j+1] = [NSNumber numberWithInteger:temp]; + flag = 1; + } + } + if (!flag) { + return; + } + } +} +``` + +1.2选择排序(基于比较,交换,每次遍历找到未排序区间最大/最小值); + +``` +/* + 比较方式:每个位置依次找到最大最小值,依次比较 + 优化:记录最小值位置,交换次数优化 + */ +- (void)selectSort:(NSMutableArray*)array { + if (array == nil) { + return; + } + if (array.count <= 1) { + return; + } + for (NSInteger i = 0;i < array.count;i++) { + NSInteger minPos = i; + for (NSInteger j = i+1; j < array.count;j++) { + if ( [array[minPos] integerValue] > [array[j] integerValue]) { + minPos = j; + } + if (j == array.count - 1) { + NSInteger temp = [array[minPos] integerValue]; + array[minPos] = array[i]; + array[i] = [NSNumber numberWithInteger:temp]; + } + } + + } + +} +``` + +1.3选择排序(基于比较,移动元素); + +``` +/* + 元素比较,元素移动 + 已排序区间 + */ +- (void)insertSort:(NSMutableArray*)array { + if (array == nil) { + return; + } + if (array.count <= 1) { + return; + } + for (NSInteger i = 1;i < array.count;i++) { + //要插入的数据 + NSInteger temp = [array[i] integerValue]; + NSInteger j = i-1; + //已排序区间 + for (;j >= 0;--j) { + //查找插入位置 + if ([array[j] integerValue] > temp) { + //依次向后移动 + array[j+1] = array[j]; + } + else { + break; + } + + } + array[j+1] = [NSNumber numberWithInteger:temp]; + } +} +``` + +2.时间复杂度O(nlogn): + +2.1归并排序(1.基于分治思想,递归思想主要关注点在merge函数,两个有序数组合并2.每次需要临时数组存储空间,不是原地排序算法3.稳定排序算法:顺序不变); + +``` +//归并排序 +- (void)mergeSort:(NSMutableArray*)array { + NSMutableArray * res = [self mergeSort:array begin:0 end:array.count-1]; + NSLog(@"res--%@",res); +} +- (NSMutableArray*)mergeSort:(NSMutableArray*)array begin:(NSInteger)begin end:(NSInteger)end { + if (begin >= end) { + return [NSMutableArray arrayWithObjects:array[begin], nil]; + } + NSInteger middle = (begin+end)/2; + NSMutableArray * leftArray = [self devidArray:array begin:begin end:middle]; + NSMutableArray * rightArray = [self devidArray:array begin:middle+1 end:end]; + [self mergeSort:leftArray begin:0 end:leftArray.count-1]; + [self mergeSort:rightArray begin:0 end:rightArray.count-1]; + NSMutableArray * res = [self mergeArray:leftArray right:rightArray ]; + return res; +} +//分割数组 +- (NSMutableArray*)devidArray:(NSMutableArray*)array begin:(NSInteger)begin end:(NSInteger)end { + NSMutableArray * reslutArray = [NSMutableArray arrayWithCapacity:0]; + for (NSInteger i = begin;i <= end;i++) { + [reslutArray addObject:array[i]]; + } + return reslutArray; +} +//合并数组 +- (NSMutableArray*)mergeArray:(NSMutableArray*)left right:(NSMutableArray*)right { + NSMutableArray * resultArray = [NSMutableArray arrayWithCapacity:0]; + NSInteger i = 0; + NSInteger j = 0; + while (i < left.count && j < right.count) { + NSInteger valueL = [left[i] integerValue]; + NSInteger valueR = [right[j] integerValue]; + if (valueL < valueR) { + [resultArray addObject:[NSNumber numberWithInteger:valueL]]; + i++; + } + else { + [resultArray addObject:[NSNumber numberWithInteger:valueR]]; + j++; + } + } + if (i < left.count) { + for (;i= end) { + return; + } + // NSInteger partition = [self partition:array left:begin right:end]; + + NSInteger i = begin; + NSInteger j = end; + NSInteger key = end; + while (i != j) { + //注意前后顺序 下面顺序反了,所以错了, 如果key改为end,则能正确输出 + //key从头,先遍历尾;key从尾,先遍历头 + while (i= [array[key] integerValue]) { + j--; + } + + if (i < j) { + [array exchangeObjectAtIndex:i withObjectAtIndex:j]; + } + + } + [array exchangeObjectAtIndex:i withObjectAtIndex:end]; + + [self quickSort:array begin:begin end:i - 1]; + [self quickSort:array begin:i + 1 end:end]; +} +``` + +快速排序: + +``` +- (NSInteger)partition:(NSMutableArray*)array left:(NSInteger)left right:(NSInteger)right { + NSInteger key = left; + NSInteger i = left; + NSInteger j = right; + while (i != j) { + while (i= [array[i] integerValue]) { + i++; + } + if (i互换位置 + [array exchangeObjectAtIndex:i withObjectAtIndex:left]; + return i; +} +- (void)quickSort:(NSMutableArray*)array left:(NSInteger)left right:(NSInteger)right k:(NSInteger)k{ + if (left >= right) { + return; + } + NSInteger partition = [self partition:array left:left right:right]; + //继续左边的排序 + [self quickSort:array left:left right:partition - 1 k:k]; + //继续右边的排序 + [self quickSort:array left:partition + 1 right:right k:k]; +} +``` + +快排思想运用:O(n)时间复杂度求第K小(大) + +``` +//求第K小 +- (NSInteger)findK:(NSMutableArray*)array begin:(NSInteger)begin end:(NSInteger)end indexOfK:(NSInteger)k { + if (begin >= end) { + return -1; + } + NSInteger partition = [self partition:array left:begin right:end]; + if (partition+1 == k) { + return [array[partition] integerValue]; + } + else if (k > partition+1) { + return [self findK:array begin:partition+1 end:end indexOfK:k]; + } + else { + return [self findK:array begin:begin end:partition-1 indexOfK:k]; + } + return -1; + +} +``` + +3.线性排序/时间复杂度O(n) + +3.1桶排序/计数排序 :针对数据范围不大的数据,将数据划分成不同的桶来实现排序; + +3.2基数排序:要求数据可以划分成高低位,位之间有递进关系。 + +小栗子: + +#### [242. 有效的字母异位词](https://leetcode-cn.com/problems/valid-anagram/) + +``` +给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。 + +示例 1: + + 输入: s = "anagram", t = "nagaram" + 输出: true + +示例 2: + + 输入: s = "rat", t = "car" + 输出: false + +说明: + +你可以假设字符串只包含小写字母。 + +进阶: + +如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况? + +bool isAnagram(char* s, char* t) { + + int sLength = strlen(s); + int tLength = strlen(t); + if (sLength != tLength) { + return false; + } + int ts[26] = { 0 }; + int st[26] = { 0 }; + for (int i = 0;i < sLength;i++) { + ts[s[i] - 'a'] ++; + st[t[i] - 'a'] ++; + } + for (int i = 0;i < 26;i++) { + if (ts[i] != st[i]) { + return false; + } + } + return true; + +} +``` + + + +# 6.二分查找 + +1.适用场景有序集合,查找某一个元素时间复杂度O(logn); + +2.基于分治思想; + +基础二分查找 + +``` +- (NSInteger)binarySearch:(NSMutableArray*)array value:(NSInteger)value { + NSInteger head = 0; + NSInteger tail = array.count - 1; + + while (head <= tail) { + NSInteger middle = head+(tail-head)/2; + if ([array[middle] integerValue] > value) { + tail = middle - 1; + } + else if ([array[middle] integerValue] < value) { + head = middle + 1; + } + else { + return middle; + } + } + return -1; +} +``` + +查找一个小于等于给定值得元素 + +``` +- (NSInteger)binarySearch:(NSMutableArray*)array lastSmallValue:(NSInteger)value { + NSInteger head = 0; + NSInteger tail = array.count - 1; + while (head <= tail) { + NSInteger middle = head + (tail-head)/2; + if ([array[middle] integerValue] <= value) { + if (middle == array.count - 1) { + return middle; + } + else if (middle + 1 <= array.count - 1) { + if ([array[middle+1] integerValue] > value) { + return middle; + } + else { + head = middle + 1; + } + } + else { + head = middle + 1; + } + + } + else if ([array[middle] integerValue] > value) { + + tail = middle - 1; + } + } + return -1; +} +``` + +第一个大于等于给定值 + +``` +- (NSInteger)binarySearch:(NSMutableArray*)array firstBigValue:(NSInteger)value { + NSInteger head = 0; + NSInteger tail = array.count - 1; + while (head <= tail) { + NSInteger middle = head + (tail-head)/2; + if ([array[middle] integerValue] >= value) { + if (middle == 0) { + return middle; + } + else if (middle - 1 >= 0) { + if ([array[middle-1] integerValue] < value) { + return middle; + } + else { + tail = middle - 1; + } + } + else { + tail = middle - 1; + } + + } + else if ([array[middle] integerValue] value) { + tail = middle - 1; + } + else if ([array[middle] integerValue] = 1) { + if ([array[middle - 1] integerValue] != value) { + return middle; + } + else { + //向前找 + tail = middle - 1; + } + } + else { + //向前找 + tail = middle - 1; + } + } + } + return -1; +} +``` + +最后一个值等于给定值 + +``` +/* + 1.是不是最后一个元素 + 2.后一个元素是不是也是value + */ +- (NSInteger)binarySearch:(NSMutableArray*)array lastValue:(NSInteger)value { + NSInteger head = 0; + NSInteger tail = array.count - 1; + while (head <= tail) { + NSInteger middle = head + (tail-head)/2; + if ([array[middle] integerValue] > value) { + tail = middle - 1; + } + else if ([array[middle] integerValue] >1); + sum = ((mid&1) == 0) ? (mid/2) * (mid + 1) : ((mid + 1)/2) *mid; + if (sum == n) { + return mid; + } + else if(sum > n) { + high = mid - 1; + } + else { + low = mid + 1; + } + } + return sum > n ? mid-1 : mid; + +} + + + +``` + + + + + From f21d5b64dfa57bc9d080d0212565b46955b89235 Mon Sep 17 00:00:00 2001 From: Mengmeng Zhang Date: Sun, 28 Apr 2019 21:03:42 +0800 Subject: [PATCH 2/5] week02_10_work Signed-off-by: Mengmeng Zhang --- Week_02/id_10/LeetCode_173_10.c | 56 +++++++++++++++++++ Week_02/id_10/LeetCode_242_10.m | 75 +++++++++++++++++++++++++ Week_02/id_10/LeetCode_692_10.m | 99 +++++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+) create mode 100644 Week_02/id_10/LeetCode_173_10.c create mode 100644 Week_02/id_10/LeetCode_242_10.m create mode 100644 Week_02/id_10/LeetCode_692_10.m diff --git a/Week_02/id_10/LeetCode_173_10.c b/Week_02/id_10/LeetCode_173_10.c new file mode 100644 index 00000000..01fdb91c --- /dev/null +++ b/Week_02/id_10/LeetCode_173_10.c @@ -0,0 +1,56 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * struct TreeNode *left; + * struct TreeNode *right; + * }; + 二叉树节点之间最小距离(二叉搜索树,中序遍历) + */ +int minDiffInBST(struct TreeNode* root) { + int *nums = (int*)malloc(sizeof(int)*199); + int k = 0; + int minValue = 1000; + struct TreeNode* p = root; + if (p == NULL) { + return 0; + } + inOrderTarvle(p,&minValue,nums,&k); + for (int i = 0;i+1 < k;i++) { + if (nums[i+1] - nums[i] < minValue) { + minValue = nums[i+1] - nums[i]; + } + } + return minValue; +} +void inOrderTarvle(struct TreeNode* root,int *min,int *nums,int *k) { + if (root == NULL) { + return NULL; + } + + inOrderTarvle(root->left,min,nums,k); + // minNode(root,min); + nums[*k] = root->val; + (*k)++; + inOrderTarvle(root->right,min,nums,k); + +} + +//计算差值,并返回最小值 +void minNode(struct TreeNode* p,int *minValue) { + int min = 0,leftMin = 100,rightMin = 100; + if (p == NULL) { + return NULL; + } + if (p->left != NULL) { + leftMin = p->val - p->left->val; + } + if (p->right != NULL) { + rightMin = p->right->val - p->val; + } + min = leftMin < rightMin?leftMin:rightMin; + if (min < *minValue) { + *minValue = min; + } + +} \ No newline at end of file diff --git a/Week_02/id_10/LeetCode_242_10.m b/Week_02/id_10/LeetCode_242_10.m new file mode 100644 index 00000000..b6ce654a --- /dev/null +++ b/Week_02/id_10/LeetCode_242_10.m @@ -0,0 +1,75 @@ +/* + 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。 + 输入: s = "anagram", t = "nagaram" + 输出: true + */ +//242有效的字母异位词 +- (BOOL)isAnagram:(NSString*)stringA withStringB:(NSString*)stringB { + if (stringA == nil || stringB == nil) { + return NO; + } + if (stringB.length != stringA.length) { + return NO; + } + NSMutableDictionary * dictA = [NSMutableDictionary dictionaryWithCapacity:0]; + NSMutableDictionary * dictB = [NSMutableDictionary dictionaryWithCapacity:0]; + NSInteger maxCount = 0; + + //构建哈希表 + for (NSInteger i = 0;i< stringA.length;i++) { + char valueA = [stringA characterAtIndex:i]; + [self addCountWithKey:[NSString stringWithFormat:@"%c",valueA] inDict:dictA]; + // [self isContainsKey:[NSString stringWithFormat:@"%c",valueB] inDict:dictB]; + } + //匹配减值操作哈希表 + for (NSInteger i = 0;i < stringB.length;i++) { + char valueB = [stringB characterAtIndex:i]; + [self removeCountWithKey:[NSString stringWithFormat:@"%c",valueB] inDict:dictA]; + } + if (dictA.allKeys.count != 0) { + return NO; + } + +// if (dictB.allKeys.count != dictA.allKeys.count) { +// return NO; +// } +// //匹配哈希表算法 +// for (NSString * key in dictB) { +// NSNumber * valueA = [dictA objectForKey:key]; +// if (valueA) { +// NSNumber * valueB = [dictB objectForKey:key]; +// if ([valueB integerValue] != [valueA integerValue]) { +// return NO; +// } +// } +// else { +// return NO; +// } +// +// } + + return YES; +} +- (void)addCountWithKey:(NSString*)key inDict:(NSMutableDictionary*)dict { + if ([dict valueForKey:key]) { + NSInteger count = [[dict valueForKey:key] integerValue]; + count++; + [dict setValue:[NSNumber numberWithInteger:count] forKey:key]; + } + else { + [dict setValue:[NSNumber numberWithInteger:1] forKey:key]; + } +} +- (void)removeCountWithKey:(NSString*)key inDict:(NSMutableDictionary*)dict { + if ([dict valueForKey:key]) { + NSInteger count = [[dict valueForKey:key] integerValue]; + if (count > 1) { + count--; + [dict setValue:[NSNumber numberWithInteger:count] forKey:key]; + } + else { + [dict removeObjectForKey:key]; + } + + } +} \ No newline at end of file diff --git a/Week_02/id_10/LeetCode_692_10.m b/Week_02/id_10/LeetCode_692_10.m new file mode 100644 index 00000000..fa9fed39 --- /dev/null +++ b/Week_02/id_10/LeetCode_692_10.m @@ -0,0 +1,99 @@ +/** + * Return an array of size *returnSize. + * Note: The returned array must be malloced, assume caller calls free(). + */ + //按单词出现次数排序 +/* + leetcode 692 + ["i", "love", "leetcode", "i", "love", "coding"] + 输出前k个出现次数最多的单词 + */ +- (NSMutableArray*)topKFrequent:(NSMutableArray*)array k:(NSInteger)k { + if (k <= 0) { + return array; + } + if (array.count == 0 || array.count < k) { + return array; + } + NSMutableArray * resultArray = [NSMutableArray arrayWithCapacity:0]; + NSMutableDictionary * dict = [NSMutableDictionary dictionaryWithCapacity:0]; + NSMutableArray * heap = [NSMutableArray arrayWithCapacity:0]; + [heap addObject:@"root"];//第0个位置占位 + for (NSInteger i = 0;i < array.count;i++) { + NSString * key = array[i]; + [self isContainsKey:key inDict:dict]; + } + //大顶堆构建 + for (NSString * key in dict) { + [self buildHeap:dict key:key withArray:heap]; + } + //输出大顶 + for (NSInteger i = 0;i < k;i++) { + [resultArray addObject:heap[1]]; + [self removeTopWithHeap:heap dict:dict];// 删除大丁 或者 限制堆化范围 + + } + return resultArray; +} +//插入元素 自下往上堆化 +- (void)buildHeap:(NSMutableDictionary*)dict key:(NSString*)key withArray:(NSMutableArray*)array { + NSInteger index = array.count; + array[index] = key; + while (index/2>0 && [[dict valueForKey:array[index]] integerValue] >[[dict valueForKey:array[index/2]] integerValue]) { + [array exchangeObjectAtIndex:index withObjectAtIndex:index/2]; + index /= 2; + } + +} +//删除堆顶元素 +- (void)removeTopWithHeap:(NSMutableArray*)heap dict:(NSMutableDictionary*)dict { + [heap exchangeObjectAtIndex:1 withObjectAtIndex:heap.count-1]; + [heap removeObjectAtIndex:heap.count-1]; + [self heapify:heap withDict:dict index:1]; +} +//堆化操作,自上往下堆化 +//堆化index位置 +- (void)heapify:(NSMutableArray*)heap maxRange:(NSInteger)maxRange withDict:(NSMutableDictionary*)dict index:(NSInteger)index { + while (true) { + NSInteger maxPos = index; + if (index*2 < maxRange && [[dict objectForKey:heap[index]] integerValue] < [[dict objectForKey:heap[index*2]] integerValue]) { + maxPos = index*2; + } + if (index*2+1 < maxRange && [[dict objectForKey:heap[index]] integerValue] < [[dict objectForKey:heap[index*2+1]] integerValue]) { + maxPos = index*2+1; + } + if (maxPos == index) { + break;//堆化结束标志 + } + [heap exchangeObjectAtIndex:index withObjectAtIndex:maxPos]; //第一次比较之后交换 + index = maxPos;//继续下一位置堆化 + } +} +- (void)heapify:(NSMutableArray*)heap withDict:(NSMutableDictionary*)dict index:(NSInteger)index { + while (true) { + NSInteger maxPos = index; + if (index*2 < heap.count && [[dict objectForKey:heap[index]] integerValue] < [[dict objectForKey:heap[index*2]] integerValue]) { + maxPos = index*2; + } + if (index*2+1 < heap.count && [[dict objectForKey:heap[index]] integerValue] < [[dict objectForKey:heap[index*2+1]] integerValue]) { + maxPos = index*2+1; + } + if (maxPos == index) { + break;//堆化结束标志 + } + [heap exchangeObjectAtIndex:index withObjectAtIndex:maxPos]; //第一次比较之后交换 + index = maxPos;//继续下一位置堆化 + } +} +//检测dict是否包含key +//如果包含更新,不包含新增 +- (void)isContainsKey:(NSString*)key inDict:(NSMutableDictionary*)dict { + if ([dict valueForKey:key]) { + NSInteger count = [[dict valueForKey:key] integerValue]; + count++; + [dict setValue:[NSNumber numberWithInteger:count] forKey:key]; + } + else { + [dict setValue:[NSNumber numberWithInteger:1] forKey:key]; + } +} From 2d1642a2254257189efc17ca6e1883eadcc69360 Mon Sep 17 00:00:00 2001 From: Mengmeng Zhang Date: Sun, 5 May 2019 20:16:01 +0800 Subject: [PATCH 3/5] week03 homework --- Week_03/id_10/LeetCode_200_10.m | 77 ++++++++++++++++++++++++++ Week_03/id_10/LeetCode_703_10.m | 96 +++++++++++++++++++++++++++++++++ Week_03/id_10/week3_10.md | 69 ++++++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 Week_03/id_10/LeetCode_200_10.m create mode 100644 Week_03/id_10/LeetCode_703_10.m create mode 100644 Week_03/id_10/week3_10.md diff --git a/Week_03/id_10/LeetCode_200_10.m b/Week_03/id_10/LeetCode_200_10.m new file mode 100644 index 00000000..f891c50b --- /dev/null +++ b/Week_03/id_10/LeetCode_200_10.m @@ -0,0 +1,77 @@ +/* + 200.岛屿的个数 + 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。 + + 示例 1: + + 输入: + 11110 + 11010 + 11000 + 00000 + + 输出: 1 + + 示例 2: + + 输入: + 11000 + 11000 + 00100 + 00011 + + 输出: 3 + + 算法核心框架:深度搜索+递归 + + 深度搜索:整个岛屿是一个“二维矩阵”(vector>),使用深度优先搜索遍历一遍整个矩阵; + 递归:当扫描到'1'时,调用infect()函数,将该 ‘1’ 上下左右相邻的位置都感染为 ‘2’,递归调用infect()的结果是从起始的 ‘1’ 开始而相连的一片‘1’都被感染为 ‘2’; + + */ +- (void)testNumOfLand { + NSMutableArray * array1 = [NSMutableArray arrayWithObjects:@1,@1,@0,@0,@0, nil]; + NSMutableArray * islandArray = [NSMutableArray arrayWithCapacity:0]; + [islandArray addObject:array1]; + [islandArray addObject:array1]; + NSMutableArray * array2 = [NSMutableArray arrayWithObjects:@0,@0,@1,@0,@1, nil]; + NSMutableArray * array3 = [NSMutableArray arrayWithObjects:@0,@0,@0,@1,@0, nil]; + [islandArray addObject:array2]; + [islandArray addObject:array3]; + NSLog(@"islandnums%ld",[self numIsLands:islandArray]) ; +} +- (NSInteger)numIsLands:(NSMutableArray*)island { + NSInteger res = 0; + if (island.count == 0) { + return 0; + } + NSMutableArray * array = island[0]; + if (array.count == 0) { + return 0; + } + //深度优先,暴力破解,回溯 + for (NSInteger i = 0;i < island.count;i++) { + NSMutableArray * yArray = island[i]; + for (NSInteger j = 0; j < yArray.count; j++) { + if ([yArray[j] integerValue] == 1) { + res++; + //递归 + [self infect:i xCount:island.count y:j yCount:yArray.count array:island]; + } + } + } + return res; +} +- (void)infect:(NSInteger)x xCount:(NSInteger)xCount y:(NSInteger)y yCount:(NSInteger)yCount array:(NSMutableArray*)array { + if (x < 0 || y < 0 || x > xCount-1 || y > yCount-1) { + return; + } + NSMutableArray * xArray = array[x]; + if ([xArray[y] integerValue] != 1) { + return; + } + xArray[y] = [NSNumber numberWithInteger:2]; + [self infect:x+1 xCount:xCount y:y yCount:yCount array:array]; + [self infect:x-1 xCount:xCount y:y yCount:yCount array:array]; + [self infect:x xCount:xCount y:y-1 yCount:yCount array:array]; + [self infect:x xCount:xCount y:y+1 yCount:yCount array:array]; +} \ No newline at end of file diff --git a/Week_03/id_10/LeetCode_703_10.m b/Week_03/id_10/LeetCode_703_10.m new file mode 100644 index 00000000..e504a019 --- /dev/null +++ b/Week_03/id_10/LeetCode_703_10.m @@ -0,0 +1,96 @@ +/* + 703.数据流中第K大元素 + 设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。 + + 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用 KthLargest.add,返回当前数据流中第K大的元素。 + + 示例: + + int k = 3; + int[] arr = [4,5,8,2]; + KthLargest kthLargest = new KthLargest(3, arr); + kthLargest.add(3); // returns 4 + kthLargest.add(5); // returns 5 + kthLargest.add(10); // returns 5 + kthLargest.add(9); // returns 8 + kthLargest.add(4); // returns 8 + + 说明: + 你可以假设 nums 的长度≥ k-1 且k ≥ 1。 +思路: + 1.构建大小为k的小顶堆,存储后k个元素 + 2.构建小顶堆,k之前插入堆化 + 3.k之后比较,如果比堆顶大,插入r元素,交换位置(最后位置与堆顶交换),删除末尾元素(前堆顶) + 4.遍历到末尾,则小顶堆构建完毕 + 5.新增元素,与堆顶元素比较,如果比堆顶大, + */ +- (void)testkthLargest { + NSInteger k = 3; + NSMutableArray * sourceArray = [NSMutableArray arrayWithObjects:@"4",@"5",@"8",@"2", nil]; + if (k > sourceArray.count) { + return; + } + NSMutableArray * heap = [NSMutableArray arrayWithCapacity:0]; + [heap addObject:@"root"]; + [sourceArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [self buildHeap:heap withValue:[obj integerValue] withK:k]; + if (sourceArray.count - 1 == idx) { + *stop = YES; + } + }]; + NSLog(@"3testkthLargest%ld",[self insertValue:3 heap:heap]); + NSLog(@"5testkthLargest%ld",[self insertValue:5 heap:heap]); + NSLog(@"10testkthLargest%ld",[self insertValue:10 heap:heap]); + NSLog(@"9testkthLargest%ld",[self insertValue:9 heap:heap]); + NSLog(@"4testkthLargest%ld",[self insertValue:4 heap:heap]); + +} +- (void)buildHeap:(NSMutableArray*)heap withValue:(NSInteger)value withK:(NSInteger)k { + //如果kx大于数据源count直接返回 + if (heap.count < k+1) { + //构建堆 + NSInteger index = heap.count; + heap[index] = [NSNumber numberWithInteger:value]; + while (index/2 > 0 && [heap[index] integerValue] < [heap[index/2] integerValue]) { + [heap exchangeObjectAtIndex:index withObjectAtIndex:index/2]; + index /= 2; + } + + } + else { + [self insertValue:value heap:heap]; + } +} +- (NSInteger)insertValue:(NSInteger)value heap:(NSMutableArray*)heap { + //向堆中插入元素 + NSInteger topValue = [heap[1] integerValue]; + if (value > topValue) { + NSInteger index = heap.count; + //末尾插入元素 + heap[index] = [NSNumber numberWithInteger:value]; + //交换元素位置 + [heap exchangeObjectAtIndex:1 withObjectAtIndex:index]; + //移除末尾元素,原来的堆顶元素 + [heap removeObjectAtIndex:index]; + //堆化 + NSInteger topIndex = 1; + while (true) { + NSInteger minPos = topIndex; + if (topIndex*2 < heap.count && [heap[topIndex] integerValue] > [heap[topIndex*2] integerValue]) { + minPos = topIndex*2; + [heap exchangeObjectAtIndex:topIndex withObjectAtIndex:minPos]; //第一次比较之后交换 + + } + if (topIndex*2+1 < heap.count && [heap[topIndex] integerValue] > [heap[topIndex*2+1] integerValue]) { + minPos = topIndex*2+1; + [heap exchangeObjectAtIndex:topIndex withObjectAtIndex:minPos]; //第一次比较之后交换 + } + if (minPos == topIndex) { + break;//堆化结束标志 + } + topIndex = minPos;//继续下一位置堆化 + } + + } + return [heap[1] integerValue]; +} \ No newline at end of file diff --git a/Week_03/id_10/week3_10.md b/Week_03/id_10/week3_10.md new file mode 100644 index 00000000..dd7918c1 --- /dev/null +++ b/Week_03/id_10/week3_10.md @@ -0,0 +1,69 @@ +# 堆排序与优先级队列 + +堆排序(heapsort)是一种比较快速的排序方式,它的时间复杂度为O(nlgn),而且堆排序具有空间原址性:即任何时候只需要有限(常数个)的空间来存储临时数据。而且堆排序还被应用在构造优先级队列中。 + +堆排序是一个优秀的算法,在操作系统中可以利用最大堆实现最大优先队列来实现共享计算机系统的作业调度。最大优先队列记录各个作业之间的相对优先级,当某个作业中断后选出具有最高优先级的队列来执行。 + +常用操作OC实现如下( LeetCode703.数据流中第K大元素): + +1.构建堆(自下而上的堆化) + +``` +- (void)buildHeap:(NSMutableArray*)heap withValue:(NSInteger)value withK:(NSInteger)k { + //如果kx大于数据源count直接返回 + if (heap.count < k+1) { + //构建堆 + NSInteger index = heap.count; + heap[index] = [NSNumber numberWithInteger:value]; + while (index/2 > 0 && [heap[index] integerValue] < [heap[index/2] integerValue]) { + [heap exchangeObjectAtIndex:index withObjectAtIndex:index/2]; + index /= 2; + } + + } + else { + [self insertValue:value heap:heap]; + } +} +``` + +2.插入元素(以更新堆顶元素举例)(自上而下的堆化) + +``` +- (NSInteger)insertValue:(NSInteger)value heap:(NSMutableArray*)heap { + //向堆中插入元素 + NSInteger topValue = [heap[1] integerValue]; + if (value > topValue) { + NSInteger index = heap.count; + //末尾插入元素 + heap[index] = [NSNumber numberWithInteger:value]; + //交换元素位置 + [heap exchangeObjectAtIndex:1 withObjectAtIndex:index]; + //移除末尾元素,原来的堆顶元素 + [heap removeObjectAtIndex:index]; + //堆化 + NSInteger topIndex = 1; + while (true) { + NSInteger minPos = topIndex; + if (topIndex*2 < heap.count && [heap[topIndex] integerValue] > [heap[topIndex*2] integerValue]) { + minPos = topIndex*2; + [heap exchangeObjectAtIndex:topIndex withObjectAtIndex:minPos]; //第一次比较之后交换 + + } + if (topIndex*2+1 < heap.count && [heap[topIndex] integerValue] > [heap[topIndex*2+1] integerValue]) { + minPos = topIndex*2+1; + [heap exchangeObjectAtIndex:topIndex withObjectAtIndex:minPos]; //第一次比较之后交换 + } + if (minPos == topIndex) { + break;//堆化结束标志 + } + topIndex = minPos;//继续下一位置堆化 + } + + } + return [heap[1] integerValue]; +} +``` + +3.堆排序,借助堆化(不断取出堆顶元素,每次取出元素后堆化操作logn,所以总时间复杂对nlogn)。 + From 89e7455772e164466a69c887f71ea005cc3d0094 Mon Sep 17 00:00:00 2001 From: Mengmeng Zhang Date: Sun, 5 May 2019 20:21:12 +0800 Subject: [PATCH 4/5] Week01 change --- Week_01/id_10/{isValid.c => LeetCode_20_10.c} | 0 Week_01/id_10/{deleteDuplicates.c => LeetCode_83_10.c} | 0 Week_01/id_10/{allSortMethodAndBiSearch.m => LeetCode_sort_10.m} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Week_01/id_10/{isValid.c => LeetCode_20_10.c} (100%) rename Week_01/id_10/{deleteDuplicates.c => LeetCode_83_10.c} (100%) rename Week_01/id_10/{allSortMethodAndBiSearch.m => LeetCode_sort_10.m} (100%) diff --git a/Week_01/id_10/isValid.c b/Week_01/id_10/LeetCode_20_10.c similarity index 100% rename from Week_01/id_10/isValid.c rename to Week_01/id_10/LeetCode_20_10.c diff --git a/Week_01/id_10/deleteDuplicates.c b/Week_01/id_10/LeetCode_83_10.c similarity index 100% rename from Week_01/id_10/deleteDuplicates.c rename to Week_01/id_10/LeetCode_83_10.c diff --git a/Week_01/id_10/allSortMethodAndBiSearch.m b/Week_01/id_10/LeetCode_sort_10.m similarity index 100% rename from Week_01/id_10/allSortMethodAndBiSearch.m rename to Week_01/id_10/LeetCode_sort_10.m From f1a258329dc9573a21a7ef8ba0b03e3f74d763cc Mon Sep 17 00:00:00 2001 From: Mengmeng Zhang Date: Sun, 12 May 2019 21:00:23 +0800 Subject: [PATCH 5/5] week04 homework --- Week_04/id_10/LeetCode_169_10.m | 57 ++++++++++ Week_04/id_10/LeetCode_312_10.m | 86 ++++++++++++++ Week_04/id_10/LeetCode_455_10.m | 56 +++++++++ ...33\345\221\250\346\200\273\347\273\223.md" | 106 ++++++++++++++++++ 4 files changed, 305 insertions(+) create mode 100644 Week_04/id_10/LeetCode_169_10.m create mode 100644 Week_04/id_10/LeetCode_312_10.m create mode 100644 Week_04/id_10/LeetCode_455_10.m create mode 100644 "Week_04/id_10/\347\254\254\345\233\233\345\221\250\346\200\273\347\273\223.md" diff --git a/Week_04/id_10/LeetCode_169_10.m b/Week_04/id_10/LeetCode_169_10.m new file mode 100644 index 00000000..14bbdb18 --- /dev/null +++ b/Week_04/id_10/LeetCode_169_10.m @@ -0,0 +1,57 @@ +/* + 169. 求众数 + 题目描述 + 评论 (329) + 题解New + 提交记录 + + 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 + + 你可以假设数组是非空的,并且给定的数组总是存在众数。 + + 示例 1: + + 输入: [3,2,3] + 输出: 3 + + 示例 2: + + 输入: [2,2,1,1,1,2,2] + 输出: 2 + + 1.哈希表统计出现次数 + 2.加一减一 摩尔投票 + 3.二分法,一直取中间值 + + */ +- (void)testMajorityElement { + NSLog(@"众数为%ld",[self majorityElement:[NSMutableArray arrayWithObjects:@1,@1,@1,@1,@1,@2,@2,@2, nil]]) ; +} +- (NSInteger)majorityElement:(NSMutableArray*)array { + if (array == nil) { + return -1; + } + if (array.count == 0) { + return -1; + } + if (array.count == 1) { + return [array[0] integerValue]; + } + __block NSInteger moore = [array[0] integerValue]; + __block NSInteger count = 0; + [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (count == 0) { + moore = [obj integerValue]; + } + if ([obj integerValue] == moore) { + count++; + } + else { + count--; + } + if (idx == array.count - 1) { + *stop = YES; + } + }]; + return moore; +} diff --git a/Week_04/id_10/LeetCode_312_10.m b/Week_04/id_10/LeetCode_312_10.m new file mode 100644 index 00000000..0a252f62 --- /dev/null +++ b/Week_04/id_10/LeetCode_312_10.m @@ -0,0 +1,86 @@ +/* + 312戳气球 + 有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。 + + 现在要求你戳破所有的气球。每当你戳破一个气球 i 时,你可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。 + + 求所能获得硬币的最大数量。 + + 说明: + + 你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。 + 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100 + + 示例: + + 输入: [3,1,5,8] + 输出: 167 + 解释: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] + coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167 + + + */ +- (NSInteger)maxCoins:(NSMutableArray*)array { + + self.maxCoins = 0; + [self helper:array coins:0 ans:self.maxCoins]; + return self.maxCoins; +} +//回溯法 +- (void)helper:(NSMutableArray*)array coins:(NSInteger)coins ans:(NSInteger)ans { + //boundary + if (array.count == 0) { + self.maxCoins = MAX(self.maxCoins,coins); + return; + } + //search + for (NSInteger i = 0;i < array.count;i++) { + NSInteger temp = [array[i] integerValue]; + NSInteger delta = temp * (i - 1 < 0 ?1:[array[i-1] integerValue]) * (i + 1 > array.count - 1 ? 1:[array[i+1] integerValue] ); + //戳破气球 + [array removeObjectAtIndex:i]; + //递归调用 + [self helper:array coins:coins+delta ans:self.maxCoins]; + //回溯 + [array insertObject:@(temp) atIndex:i]; + } +} +//动态规划 记忆法(备忘录法) +/* +最优子结构,状态转移方程 + */ +- (NSInteger)dpMaxCoins:(NSMutableArray*)array { + self.dpStateArray = [NSMutableArray arrayWithCapacity:0]; + NSInteger size = array.count; + [array insertObject:@1 atIndex:0]; + [array addObject:@1]; + //构造状态记录数组 + for (NSInteger i = 0;i < size+2;i++) { + NSMutableArray * lineArray = [NSMutableArray arrayWithCapacity:0]; + for (NSInteger j = 0;j < size+2;j++) { + [lineArray addObject:@0]; + } + [self.dpStateArray addObject:lineArray]; + } + + NSInteger ans = [self dpHelper:array i:1 j:size]; + return ans; +} +- (NSInteger)dpHelper:(NSMutableArray*)array i:(NSInteger)i j:(NSInteger)j { + //boundary + if (i > j) { + return 0; + } + //缓存加速 + if ([self.dpStateArray[i][j] integerValue] > 0) { + return [self.dpStateArray[i][j] integerValue]; + } + //search + for (NSInteger k = i;k <= j;++k) { + NSInteger left = [self dpHelper:array i:i j:k-1]; + NSInteger right = [self dpHelper:array i:k+1 j:j]; + NSInteger delta = [array[k] integerValue] * [array[i-1] integerValue] * [array[j+1] integerValue]; + self.dpStateArray[i][j] = @(MAX( [self.dpStateArray[i][j] integerValue], left+right+delta)); + } + return [self.dpStateArray[i][j] integerValue]; +} \ No newline at end of file diff --git a/Week_04/id_10/LeetCode_455_10.m b/Week_04/id_10/LeetCode_455_10.m new file mode 100644 index 00000000..eb8cd081 --- /dev/null +++ b/Week_04/id_10/LeetCode_455_10.m @@ -0,0 +1,56 @@ +/* + 455分发饼干 + 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。 + + 注意: + + 你可以假设胃口值为正。 + 一个小朋友最多只能拥有一块饼干。 + + 示例 1: + + 输入: [1,2,3], [1,1] + + 输出: 1 + + 解释: + 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 + 虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 + 所以你应该输出1。 + + 示例 2: + + 输入: [1,2], [1,2,3] + + 输出: 2 + + 解释: + 你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 + 你拥有的饼干数量和尺寸都足以让所有孩子满足。 + 所以你应该输出2. + +思路:贪心算法,优先满足需求小的孩子,每满足一个孩子,贡献值相同 + */ +- (void)testfindContentChildren { + NSInteger value = [self findContentChildren:[NSMutableArray arrayWithObjects:@1,@2,@3, nil] sArray:[NSMutableArray arrayWithObjects:@2,@2, nil]]; + NSLog(@"findContentChildren%ld",value); +} +- (NSInteger)findContentChildren:(NSMutableArray*)gArray sArray:(NSMutableArray*)sArray { + //胃口排序 + [gArray sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { + return NSOrderedAscending; + }]; + //饼干排序 + [sArray sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { + return NSOrderedAscending; + }]; + NSInteger count = 0; + //遍历饼干,如果满足则遍历胃口,满足数加1;不满足等待 + for (NSInteger i = 0,j = 0;(i < sArray.count)&&(j < gArray.count);i++) { + if ([gArray[j] integerValue] <= [sArray[i] integerValue]) { + j++; + count++; + } + } + return count; +} diff --git "a/Week_04/id_10/\347\254\254\345\233\233\345\221\250\346\200\273\347\273\223.md" "b/Week_04/id_10/\347\254\254\345\233\233\345\221\250\346\200\273\347\273\223.md" new file mode 100644 index 00000000..0e519ee8 --- /dev/null +++ "b/Week_04/id_10/\347\254\254\345\233\233\345\221\250\346\200\273\347\273\223.md" @@ -0,0 +1,106 @@ +#动态规划解题思路 + +思路一: + +回溯算法实现-定义状态-画递归树-找重复子问题-画状态转移表-根据递推关系填表-将填表过程翻译成代码 + +思路二: + +找最优子结构-写状态转移方程-将状态转移方程翻译成代码 + +举个栗子: + +``` +LeetCode-312 戳气球 + 有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。 + + 现在要求你戳破所有的气球。每当你戳破一个气球 i 时,你可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。 + + 求所能获得硬币的最大数量。 + + 说明: + + 你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。 + 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100 + + 示例: + + 输入: [3,1,5,8] + 输出: 167 + 解释: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] + coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167 + +``` + +回溯法: + +``` +- (NSInteger)maxCoins:(NSMutableArray*)array { + self.maxCoins = 0; + [self helper:array coins:0 ans:self.maxCoins]; + return self.maxCoins; +} +//回溯法 +- (void)helper:(NSMutableArray*)array coins:(NSInteger)coins ans:(NSInteger)ans { + //boundary + if (array.count == 0) { + self.maxCoins = MAX(self.maxCoins,coins); + return; + } + //search + for (NSInteger i = 0;i < array.count;i++) { + NSInteger temp = [array[i] integerValue]; + NSInteger delta = temp * (i - 1 < 0 ?1:[array[i-1] integerValue]) * (i + 1 > array.count - 1 ? 1:[array[i+1] integerValue] ); + //戳破气球 + [array removeObjectAtIndex:i]; + //递归调用 + [self helper:array coins:coins+delta ans:self.maxCoins]; + //回溯 + [array insertObject:@(temp) atIndex:i]; + } +} +``` + +动态规划: + +``` +/* +最优子结构,状态转移方程 + */ +- (NSInteger)dpMaxCoins:(NSMutableArray*)array { + self.dpStateArray = [NSMutableArray arrayWithCapacity:0]; + NSInteger size = array.count; + [array insertObject:@1 atIndex:0]; + [array addObject:@1]; + //构造状态记录数组 + for (NSInteger i = 0;i < size+2;i++) { + NSMutableArray * lineArray = [NSMutableArray arrayWithCapacity:0]; + for (NSInteger j = 0;j < size+2;j++) { + [lineArray addObject:@0]; + } + [self.dpStateArray addObject:lineArray]; + } + + NSInteger ans = [self dpHelper:array i:1 j:size]; + return ans; +} +- (NSInteger)dpHelper:(NSMutableArray*)array i:(NSInteger)i j:(NSInteger)j { + //boundary + if (i > j) { + return 0; + } + //缓存加速 + if ([self.dpStateArray[i][j] integerValue] > 0) { + return [self.dpStateArray[i][j] integerValue]; + } + //search + for (NSInteger k = i;k <= j;++k) { + NSInteger left = [self dpHelper:array i:i j:k-1]; + NSInteger right = [self dpHelper:array i:k+1 j:j]; + NSInteger delta = [array[k] integerValue] * [array[i-1] integerValue] * [array[j+1] integerValue]; + self.dpStateArray[i][j] = @(MAX( [self.dpStateArray[i][j] integerValue], left+right+delta)); + } + return [self.dpStateArray[i][j] integerValue]; +} +``` +