一.leetcode部分报错的含义
1.Char 5: fatal error: control may reach end of non-void function [-Wreturn-type] }
这表示:没有考虑所有可能的返回值情况
2.AddressSanitizer: heap-buffer-overflow on address 0x602000000040 at pc 0x000000406b5e bp 0x7ffc15cc0320 sp 0x7ffc15cc0318
这类报错表示:检查了是否存在内存非法访问,例如数组越界
3.AddressSanitizer:DEADLYSIGNAL
这表示数组越界
4.member access within null pointer of type 'TreeNode'
这类报错表示:未考虑参数空值异常
5.terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::substr
这类问题的解决方法:查找substr方法前后代码,排除可能的越界条件。
二.leetcode部分题目题解
T20.有用的括号
思路:由栈先入后出的特点与本题特点大致相似,即若遇到左括号入栈,遇到右括号时将对应栈顶左括号出栈,则遍历完所有括号后 stack 仍然为空;
遇到左括号入栈,遇到右括号和栈顶元素比较,若不匹配或栈空,直接返回false。
最后若栈非空,返回false,否则返回true
bool isValid(char * s){
if(!s||s[0]=='\0')
return true;
char *stack=(char *)malloc(strlen(s));
memset(stack,0,strlen(s));//初始化内存空间
int top=-1;//初始化顺序栈
int i;
for(i=0;s[i]!='\0';i++){
switch(s[i]){
case'(':
stack[++top]=s[i];//进栈
break;
case'{':
stack[++top]=s[i];//进栈
break;
case'[':
stack[++top]=s[i];//进栈
break;
case')':
if(top<0||stack[top--]!='(')//判断是否栈为空或与之匹配的字符不对应
return false;
break;
case'}':
if(top<0||stack[top--]!='{')//同上
return false;
break;
case']':
if(top<0||stack[top--]!='[')//同上
return false;
break;
}
}
if(top>=0)
return false;//说明栈中的元素未全部匹配
return true;
}}
2.T86.分隔链表
思路:对所有小于 x 的节点使用头插法并移动头结点到该节点处;等于 x 的节点头插完后不移动头结点
struct ListNode* partition(struct ListNode* head, int x){
if(head == NULL){
return head;
}
struct ListNode* HNode;
HNode = (struct ListNode*)malloc(sizeof(struct ListNode));
HNode->next = head;//创建头结点HNode指向该结点head,
struct ListNode* insertPos = HNode;
for(;insertPos->next && insertPos->next->val < x;insertPos = insertPos->next);//遍历到小与x的节点处
if(insertPos->next == NULL){
return head;
}
struct ListNode* left_pre = insertPos->next;
struct ListNode* right_cur = left_pre;
struct ListNode* split = left_pre;
while(left_pre->next != NULL){
if(left_pre->next->val >= x){
left_pre = left_pre->next;
right_cur = left_pre;
}
else if(right_cur->next && right_cur->next->val < x){
right_cur = right_cur->next;
}
else{
split = insertPos->next;
insertPos->next = left_pre->next;
left_pre->next = right_cur->next;
right_cur->next = split;
insertPos = right_cur;
}
}
head = HNode->next;
free(HNode);
return head;
}}
3.T100.相同的树
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
if(p == NULL && q == NULL) return true;
if(p != NULL && q != NULL){
if(p -> val != q -> val) return false;//判断数值是否相同
else{
return (isSameTree(p -> left, q -> left) && isSameTree(p -> right, q -> right));//使用递归的方法判断两个二叉树是否相同
}
}
else
return false;
}
4.T102.二叉树的层序遍历
思路:二叉树的层序遍历即按照从根节点开始逐层输出
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes){
int **rslt = NULL;
int *columnSize = NULL;
struct TreeNode *queue[NODE_SIZE] = {0}; /* 做队列使用 */
struct TreeNode *pNode = NULL;
int front = 0, rear = 0, pre_rear;
int i = 0, j = 0; /* i用来索引行,即层数,j用来索引列,即每层的结点个数 */
if (!root) {
*returnSize = 0;
return NULL;
}
queue[rear++] = root; /* 先把root结点入队 */
while (front < rear) { /* 外层循环:用来处理队列,队列不为空就循环处理 */
pre_rear = rear; /* 备份上一层的队尾指针 */
rslt = realloc(rslt, (i + 1)*sizeof(int *)); /* 外层循环实际就是层数,每次扩充1 */
rslt[i] = calloc(pre_rear - front, sizeof(int));
while(front < pre_rear) { /* 内层循环:遍历每一层结点,每次出队一个结点,同时并把该结点的孩子入队 */
pNode = queue[front++]; /* 出队 */
rslt[i][j++] = pNode->val; /* 存储结点值 */
if (pNode->left) /* 当前结点左、右孩子存在则将他们入队 */
queue[rear++] = pNode->left;
if (pNode->right)
queue[rear++] = pNode->right;
}
columnSize = realloc(columnSize, (i + 1)*sizeof(int)); /* columnSize数组用来存储每层结点个数 */
columnSize[i++] = j;
j = 0;
}
*returnSize = i; //这个参数用来“带回”层数 */
*returnColumnSizes = columnSize; /* 这个参数用来“带回”每层的结点个数 */
return rslt; /* 返回值存储了遍历的结果,上面两个参数用来描述这个结果,以便调用者打印树的形态 */
}
5.T225.用队列实现栈
一下是思路导图
思路解析:入栈操作时,首先获得入栈前的元素个数 n,然后将元素入队到队列,再将队列中的前 n 个元素(即除了新入栈的元素之外的全部元素)依次出队并入队到队列,此时队列的前端的元素即为新入栈的元素,且队列的前端和后端分别对应栈顶和栈底。
由于每次入栈操作都确保队列的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除队列的前端元素并返回即可,获得栈顶元素操作只需要获得队列的前端元素并返回即可(不移除元素)。
由于队列用于存储栈内的元素,判断栈是否为空时,只需要判断队列是否为空即可
typedef struct tagListNode {
struct tagListNode* next;
int val;
} ListNode;
typedef struct {
ListNode* top;
} MyStack;
MyStack* myStackCreate() {
MyStack* stk = calloc(1, sizeof(MyStack));
return stk;
}
void myStackPush(MyStack* obj, int x) {
ListNode* node = malloc(sizeof(ListNode));
node->val = x;
node->next = obj->top;
obj->top = node;
}
int myStackPop(MyStack* obj) {
ListNode* node = obj->top;
int val = node->val;
obj->top = node->next;
free(node);
return val;
}
int myStackTop(MyStack* obj) {
return obj->top->val;
}
bool myStackEmpty(MyStack* obj) {
return (obj->top == NULL);
}
void myStackFree(MyStack* obj) {
while (obj->top != NULL) {
ListNode* node = obj->top;
obj->top = obj->top->next;
free(node);
}
free(obj);
}
6.T455.分发饼干
int cmp(int*a,int *b)
{
return *a-*b;
}
int findContentChildren(int* g, int gSize, int* s, int sSize){
int i=0,j=0;
qsort(g,gSize,sizeof(int),cmp);//从小到大排序
qsort(s,sSize,sizeof(int),cmp);
while(i<gSize&&j<sSize){
if(g[i]<=s[j]) i++;
j++;
}
return i;
}
7.T459.重复的子字符串
首先给大家介绍一下kmp(字符串匹配算法),大家点下面这个链接,可看到详细的讲解
kmp
这是题目解答
#define MAX_NUM 10001
bool repeatedSubstringPattern(char * s){
int len = strlen(s);
if (len <= 1) {
return false;
}
int i;
int match = 0;
for (i = 1; i * 2 <= len; i++) {
if (len % i == 0) {
int j;
for (j = i; j < len; j++) {
if (s[j] == s[j - i]) {
match = 1;
} else {
match = 0;
break;
}
}
if (match == 1) {
return true;
}
}
}
return false;
}
8.T463.岛屿的周长
class Solution {
public:
int islandPerimeter(vector<vector<int>>& grid) {
int cnt = 0;
for(int i = 0; i < grid.size(); i++){
for(int j = 0; j < grid[i].size(); j++){
//如果当前值为1,加4(四条边)
if(grid[i][j] == 1){
cnt += 4;
}
//如果左边有1,减2(两条边重合),上面有1,减2。
if(j-1>=0 && grid[i][j] == 1 && grid[i][j-1] == 1){
cnt -= 2;
}
if(i-1>=0 && grid[i][j] == 1 && grid[i-1][j] == 1){
cnt -= 2;
}
}
}
return cnt;
}
};
今天的题解就写到这了。。。哒哒哒,拜拜