LeetCode
迷途小羔羊。
down to the earth
展开
-
90. 子集 II 回溯+去重
解题思路这题和78.子集不一样的地方在于:子集不能重复。我们需要先对集合进行排序,测试用例中其它样例不是按顺序排列的。依然是回溯三部曲。子集也是组合问题,这次如果同一层上不可以选取相同的元素。递归函数的参数:需要用到startIndex,因为在同一个集合里面,来记录搜索的起始位置。终止条件:搜索的起始位置>=数组长度。单层逻辑:从startIndex开始搜索nums。递归时i+1,因为这题不可以重复选取数组中的元素。 在里面做一个判断,如果nums[i] ==nums[i-1],就代表同.原创 2021-12-24 20:10:32 · 560 阅读 · 0 评论 -
LeetCode 78. 子集 回溯
思路:依然是回溯三部曲。子集也是组合问题,之前的都是收集叶子结点,现在是收集树的所有结点。递归函数的参数:需要用到startIndex,因为在同一个集合里面,来记录搜索的起始位置终止条件:搜索的起始位置>=数组长度单层逻辑:和前面的一样。要注意的是copy()函数必须放在最前面,不然会漏掉集合为空的情况。int *path;int pathTop;int **result;int resultTop;int *length;void copy(){ int *tem.原创 2021-12-20 00:15:08 · 279 阅读 · 0 评论 -
LeetCode 131. 分割回文串
思路:这题知道用回溯,但是不知道该怎么切割。比如:切割线如何模拟?如何截取切割后的子串?如何判断回文?我在b站上看了代码随想录的视频,然后才明白,明白后发现和前面的组合还是挺类似的。依然是回溯三部曲:1.递归函参:char *s,int startIndex.因为是在同一个集合中,需要用到startIndex。.终止条件:startIndex >=strlen(s).观察树形结构图可以发现,切割线到了字符串的最后面,就是本轮递归的终止条件。startIndex是切割线。单层搜索:(int .原创 2021-12-19 01:37:53 · 284 阅读 · 0 评论 -
LeetCode 40. 组合总和 II 回溯+去重
思路:这题和前面的39.组合 有区别,当前数组有重复元素,并且每个数字在组合中只能使用一次。我们要让其没有重复的组合,就相当于在每一层中不可重复选取同一个元素。我们首先要做的就是对数组排序,关于快速排序:C语言:qsort()解析还是一样的回溯三部曲。参数:需要sum来计算总和和startIndex来控制开始的位置。终止条件:当sum==target时,以及sum>target时。单层逻辑:从startIndex开始搜索candidates。对比之前,递归时j+1,因为这题不可以重复选取.原创 2021-12-18 12:05:35 · 1121 阅读 · 0 评论 -
LeetCode 39. 组合总和 回溯算法+剪枝
和216 组合总和 III不同之处在于 这题数组中的数字可以重复使用多次,并且没有数量要求。定义两个全局变量,result存放结果集,path存放任何条件的结果。index来指示开始的位置,length来记录每一个path数组的长度(因为每一个符合target的数组的长度不一样)。还是一样的回溯三部曲。参数:需要sum来计算总和和index来控制开始的位置。终止条件:当sum==target时,以及sum>target时。.单层逻辑:从index开始搜索candidates。对比之前,递.原创 2021-12-16 00:36:17 · 1638 阅读 · 0 评论 -
LeetCode 17. 电话号码的字母组合
思路:这题是在不同的集合里面求组合。回溯三部曲:定义两个全局变量,result存放结果集,path存放任何条件的结果。index是来获取dighits字符串数组中的具体数组,用来记录遍历的数字。终止条件:当到达叶子节点,即index==strlen(digits)时,遍历的数字等于输入的个数时,result收集path,return。单层搜索过程。处理节点、递归函数、回溯操作。char *path;int pathTop;char **result;int resultTop;ch.原创 2021-12-15 15:40:25 · 1417 阅读 · 0 评论 -
LeetCode 216. 组合总和 III
和77. 组合差不多,区别在于这题目是求k个数之和=n,并且不存在重复的数字。思路:回溯三部曲:定义两个全局变量,result存放结果集,path存放如何条件的结果。 startIndex 记录下一层递归搜索的起始位置。终止条件:当到达叶子节点,即pathTop == k时,result收集path,return。单层搜索过程。处理节点、递归函数、回溯操作。关于剪枝操作:画图可以观察出,要完成剪枝操作,只需在单层搜索过程中改动即可。搜索起点的上界 = n-还需要的元素个数 +1; 即 j&l.原创 2021-12-15 00:29:32 · 1406 阅读 · 0 评论 -
LeetCode 77. 组合 回溯算法+剪枝
思路:回溯三部曲:定义两个全局变量,result存放结果集,path存放如何条件的结果。 startIndex 记录下一层递归搜索的起始位置。终止条件:当到达叶子节点,即pathTop == k时,result收集path,return。单层搜索过程。int *path;int pathTop;int **result;int resultTop;void backTrack(int n,int k,int startIndex){ if(pathTop == k){ .原创 2021-12-14 15:54:06 · 708 阅读 · 0 评论 -
LeetCode 222. 完全二叉树的节点个数
思路:层序遍历的思路去做。每取出一个节点,计数一次就好了。int countNodes(struct TreeNode* root){ if(root==NULL) return 0; struct TreeNode *queue[100000]; struct TreeNode *cur; int front = 0,rear=0; int count = 0; queue[rear++] = root; while(front!.原创 2021-12-12 17:09:37 · 396 阅读 · 0 评论 -
LeetCode 101. 对称二叉树
思路:看题目,镜像对称的,要比较的不是左右节点,要比较的是root的最里侧和最外侧相等。即左节点的左节点和右节点的右节点,以及左节点的右节点和右节点的左节点。bool compare(struct TreeNode *left,struct TreeNode *right){ if(left==NULL && right==NULL) return true; if(left==NULL || right ==NULL) return f.原创 2021-12-12 11:46:58 · 366 阅读 · 0 评论 -
LeetCode 111. 二叉树的最小深度 BFS
思路:叶子节点是左右孩子节点为空,直接返回。int minDepth(struct TreeNode* root){ if(root==NULL) return 0; struct TreeNode *cur; struct TreeNode *queue[10000]; int front = 0, rear = 0; int count = 0; queue[rear++] = root; while(front != rear.原创 2021-12-11 23:02:58 · 177 阅读 · 0 评论 -
LeetCode 104. 二叉树的最大深度
思路:BFS。很简单,只用在每循环一层时,计数一次就好了int maxDepth(struct TreeNode* root){ if(root==NULL) return 0; struct TreeNode *cur; struct TreeNode *queue[10000]; int front = 0, rear = 0; int count = 0; queue[rear++] = root; while(front!=.原创 2021-12-11 22:34:55 · 264 阅读 · 0 评论 -
LeetCode117. 填充每个节点的下一个右侧节点指针 II
思路:和116题一模一样struct Node* connect(struct Node* root) { if(root==NULL) return root; struct Node *queue[10000]; struct Node *cur; int front = 0, rear = 0; queue[rear++] = root; while(front!=rear){ int last = rear; .原创 2021-12-11 22:18:49 · 257 阅读 · 0 评论 -
LeetCode 116. 填充每个节点的下一个右侧节点指针
思路:依然是BFS。关键就在这里: if(i < size - 1){ cur->next = queue[front]; }size表示每一层中节点的个数。struct Node* connect(struct Node* root) { if(root==NULL) return root; struct Node *queue[10000]; struct Node *cur; int front = .原创 2021-12-11 22:09:07 · 348 阅读 · 0 评论 -
LeetCode 515. 在每个树行中找最大值
思路:在层序遍历的基础上,与前面不同的就是借助一个中间变量max来保存最大值,然后存入数组中。 if(cur->val > max) max = cur->val int* largestValues(struct TreeNode* root, int* returnSize){ *returnSize = 0; int *res = malloc(sizeof(int)*10000); if(root == NULL) .原创 2021-12-11 16:30:44 · 324 阅读 · 0 评论 -
LeetCode 429. N 叉树的层序遍历
先看注释,numChildren为孩子节点数量,children为存放的孩子节点。思路:在掌握了二叉树的层序遍历的基础上,在两个while循环里多加一个循环,循环结束条件为i<numChildren,然后判断孩子节点是否存在,若存在则存入队列中。其余操作和前面的差不多。int** levelOrder(struct Node* root, int* returnSize, int** returnColumnSizes) { *returnSize = 0; if(root==.原创 2021-12-10 21:11:07 · 688 阅读 · 0 评论 -
LeetCode 637. 二叉树的层平均值
在BFS层序遍历的基础上,计算每一层的平均值并存入数组中。double* averageOfLevels(struct TreeNode* root, int* returnSize){ *returnSize = 0; if(root==NULL) return ; double *res = malloc(sizeof(int)*10000); struct TreeNode *queue[10000]; struct TreeNode *cu.原创 2021-12-10 16:42:56 · 282 阅读 · 0 评论 -
LeetCode 199. 二叉树的右视图
思路:用BFS层序遍历完成,len表示每一层中节点的个数,在for循环中加个判断,在每层中遍历到最后一个值时才遍历其节点的值,就实现了右视图的功能。int* rightSideView(struct TreeNode* root, int* returnSize){ *returnSize = 0; if(root==NULL) return NULL; int *res = malloc(sizeof(int)*2000); struct TreeNod.原创 2021-12-10 15:48:23 · 363 阅读 · 0 评论 -
LeetCode 107. 二叉树的层序遍历 II
思路:在102题的基础上修改代码,增加一个反转就可以了。int** levelOrderBottom(struct TreeNode* root, int* returnSize, int** returnColumnSizes){ *returnSize = 0; if(root==NULL) return NULL; int **res =malloc(sizeof(int*)*2000); *returnColumnSizes = malloc(si.原创 2021-12-10 12:31:12 · 843 阅读 · 0 评论 -
LeetCode 226. 翻转二叉树
struct TreeNode* invertTree(struct TreeNode* root){ if(root==NULL) return root; struct TreeNode *temp ; temp = root->left; root->left = root->right; root->right = temp; invertTree(root->left); invertTree(.原创 2021-12-10 09:55:51 · 312 阅读 · 0 评论 -
LeetCode 102. 二叉树的层序遍历
思路:层序遍历的操作用队列完成。用C语言来写比较麻烦,你必须很清楚二维数组与二级指针的关系。二维数组若要用指针表示,必须用数组指针来表示。前面都先执行初始化操作,并判断树是否为空。生成队头指针,队尾指针,并生成一个cur指针来表示指向当前遍历的节点。用front==rear来表示循环结束的条件,即队列为空。colSize表示每层节点的个数,其实就相当于二维数组的列号。last来表示每一层中最后节点的指针。当front<last时,就代表遍历一层,先将front出队,然后判断左右孩子。每.原创 2021-12-08 19:51:52 · 291 阅读 · 0 评论 -
LeetCode 剑指 Offer 05. 替换空格
第一种解法:通过新生成一个数组来完成,新数组长度是原数组长度的3倍+1。char* replaceSpace(char* s){ int len = strlen(s); char *a =malloc(sizeof(char)*len*3+1); int size =0; for(int i=0;i<len;i++){ if(s[i]==' '){ a[size++]='%'; a[size++]='.原创 2021-12-05 16:13:36 · 301 阅读 · 0 评论 -
LeetCode 541. 反转字符串 II
思路:我觉得这道题有两个难点。在每个[0,2k]区间内,只反转前k个字符。然后是剩余字符该如何表示?第一个我们可以找规律,让i每次递增2k就好。第二个剩余字符,一开始想不出来该如何判断。举了几个例子模拟一下就明白了,处理2k长度以及剩余字符是可以合并的,左区间都是i。右区间则在剩余字符小于k还是在[k,2k)区间内判断,就相当于在i+k和len中选择小的来进行反转。void swap(char *a,char*b){ char t=*a; *a = *b; *b =.原创 2021-12-05 15:55:17 · 160 阅读 · 0 评论 -
LeetCode 344. 反转字符串
思路:借助双指针,分别指向首尾。void reverseString(char* s, int sSize){ int fast=sSize-1; int slow=0; while(slow<fast){ char c =s[slow]; s[slow]=s[fast]; s[fast]=c; slow++; fast--; }}...原创 2021-12-04 01:31:46 · 245 阅读 · 0 评论 -
LeetCode 19. 删除链表的倒数第 N 个结点
思路:通过双指针+虚拟头节点来完成。struct ListNode* removeNthFromEnd(struct ListNode* head, int n){ struct ListNode *dummyHead = malloc(sizeof(struct ListNode)); dummyHead->next = head; struct ListNode *first = dummyHead; struct ListNode *second=dummyH.原创 2021-12-03 21:21:34 · 215 阅读 · 0 评论 -
LeetCode 24. 两两交换链表中的节点
思路:借助虚拟头节点,会方便很多。可以先想局部是如何完成交换操作的,示例1中交换1、2节点,有3步:struct ListNode* swapPairs(struct ListNode* head){ struct ListNode *dummyHead =malloc(sizeof(struct ListNode)); dummyHead->next = head; struct ListNode *pre = dummyHead; while(pre->.原创 2021-12-03 01:24:09 · 364 阅读 · 0 评论 -
LeetCode 977. 有序数组的平方
思路:双指针,由于数组是有序的且会出现负数,那么只有两种情况,最大数只可能出现在最左边或者最右边。定义左指针从0开始,右指针从最后开始,逆序把元素存入新数组。int* sortedSquares(int* nums, int numsSize, int* returnSize){ int *a =(int*)malloc(sizeof(int)*numsSize); *returnSize = numsSize; int l=0,r=numsSize-1; int po.原创 2021-12-02 12:44:56 · 220 阅读 · 0 评论 -
LeetCode 283. 移动零
思路:借助双指针来完成,两个指针都从0开始,必须保证的是左指针左边的数全部为非零元素,右指针到左指针之间的为零元素。当循环开始时,若右指针指向的数为0时,则右指针自增.若右指针指向的为非零元素,则交换左右指针指向的元素。void swap(int *a,int *b){ int t =*a; *a = *b; *b=t;}void moveZeroes(int* nums, int numsSize){ int left=0,right =0; while(.原创 2021-12-02 12:42:28 · 133 阅读 · 0 评论 -
LeetCode 367. 有效的完全平方数
用二分法来做。bool isPerfectSquare(int num){ int left = 0,right = num , mid ; while(left<=right){ mid = (left+right) /2 ; long square =(long) mid * mid ; if(num<square){ right = mid - 1; }else if(num>.原创 2021-12-01 16:36:10 · 208 阅读 · 0 评论 -
LeetCode 704. 二分查找
二分查找,很简单,思路就不写了int search(int* nums, int numsSize, int target){ int left = 0,right = numsSize-1; while(left<=right){ int mid = (left+right)/2; if(target <nums[mid]){ right = mid -1; }else if(target ==nums.原创 2021-11-30 15:28:29 · 229 阅读 · 0 评论 -
LeetCode 69. Sqrt(x)
如果这题用int型来做,会出现溢出的报错提醒,不然就会运行超时,所以我直接选择用long类型来做。还是用二分法来完成。int mySqrt(int x){ if(x==0) return 0; if(x==1) return 1; long left = 0,right = x; while(left<=right){ long mid = left+(right-left)/2; long sqrt=.原创 2021-11-30 00:58:48 · 272 阅读 · 0 评论 -
LeetCode 225. 用队列实现栈
思路:题目要求了用两个队列来完成实现栈的操作,借助两个队列,q1存储stack元素,q2用队列的方法实现完成入栈操作。#define Len 20typedef struct Queue{ int data[Len]; int head; int rear; int size;}Queue;typedef struct { Queue *q1,*q2;} MyStack;Queue *InitQueue(int k){ Queue *obj .原创 2021-11-29 01:12:18 · 215 阅读 · 0 评论 -
LeetCode 145. 二叉树的后序遍历
第一种解法:递归。void postorder(struct TreeNode *root,int *res,int *returnSize){ if(root==NULL) return ; postorder(root->left,res,returnSize); postorder(root->right,res,returnSize); res[(*returnSize) ++] =root->val ;}int* post.原创 2021-11-28 00:24:15 · 237 阅读 · 0 评论 -
LeetCode 94. 二叉树的中序遍历
第一种解法:递归。void inorder(struct TreeNode* root ,int *res, int *resSize){ //res为数组,resSize为数组长度 if(!root) return ; inorder(root->left,res,resSize); res[(*resSize)++] = root->val; inorder(root->right,res,resSize);}in.原创 2021-11-27 22:00:43 · 237 阅读 · 0 评论 -
LeetCode 144. 二叉树的前序遍历
第一种解法:递归。这没啥好说的了,主要看模拟栈的。要注意的是C语言如何解引用。void preorder(struct TreeNode *root,int res[],int *resSize){ if(!root) return ; res[(*resSize)++] = root->val; preorder(root->left,res,resSize); preorder(root->right,res,resSize);}.原创 2021-11-27 18:39:32 · 137 阅读 · 0 评论 -
LeetCode 206. 反转链表
思路:先思考局部反转如何实现。定义cur和pre两个指针,cur指向空,pre指向头结点。借助一个辅助结点来存储pre->next的,每次让pre->next指向cur,就实现了局部反转。然后再让cur和pre往前移动一个位置,为下一次反转做准备。struct ListNode* reverseList(struct ListNode* head){ struct ListNode *cur =NULL; struct ListNode *pre =head; wh.原创 2021-11-25 22:11:36 · 195 阅读 · 0 评论 -
LeetCode 203. 移除链表元素
思路:存在两种情况头结点是需要移除删除的元素,可以用循环来执行操作,直到头结点不是需要移除的元素为止。也可以新建结点为虚拟头结点。下面我用的是前一种方法。已判断完头结点是不需要移除的元素,后面的操作就很简单了,相当于断开连接。/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */struct ListNode* .原创 2021-11-25 21:20:03 · 206 阅读 · 0 评论 -
LeetCode 160. 相交链表
思路:若两链表不相交,不管两链表的长度是否一样,则它们都会到达尾结点,因此可以理解为相遇处是NULL。若两链表相交,链表A: a+c, 链表B : b+c,c为公共结点。a+c+b+c = b+c+a+c,则会在相交结点相遇。/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */struct ListNode *g.原创 2021-11-25 20:24:35 · 316 阅读 · 0 评论 -
LeetCode 141. 环形链表
思路:这题我使用了快慢指针来完成,题目中的pos不用理它,pre为快指针,p为慢指针。假设它是环形链表,如果快指针和慢指针步伐不一样(快指针一次前进两步,慢指针一次前进一步),那么它们总会在某一位置相遇。/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */bool hasCycle(struct ListNode *he.原创 2021-11-25 17:52:08 · 308 阅读 · 0 评论 -
LeetCode 83. 删除排序链表中的重复元素
我的刷题顺序:大概是这样,数组 ->字符串 ->链表->二分查找->排序->哈希表-> 栈->队列 ->树 、递归、回溯 -> 堆。第一遍全部从简单题开始做起。这题很简单,就不写思路了。/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */struct ListNo原创 2021-11-25 17:26:15 · 221 阅读 · 0 评论