LeetCode做题记录

LeetCode做题记录

由于去年毕业写论文,后来参加工作,导致好久没有更新博客了,前段时间看到一个游客评论说让我加油坚持更新,于是打算开一个文章,来记录一下工作以后下班时间偶尔的做题记录。

28. 实现 strStr()

题目描述

本题在LeetCode上显示为简单,原因是出题人理解为可以直接调用API,但是如果用C语言实现,不调用API的情况下,需要使用字符串对比的KMP算法
在这里放一个B站讲解KMP算法原理的视频

//首先是构造next数组
void getnext(int *next,char *pattern)
{
    
    
    int k=-1,j=0;
    next[0]=-1;//next数组的0位设置为-1
    //计算pattern字符的长度
    char *p=pattern;
    int length=0;
    while(*p++!='\0')
        length++;
    //对于next数组的j位,设置其next[j]
    while(j<length)
    {
    
    
    	//如果k为-1,表示前面的字符串没有公共前后缀,将next[j+1]设置为0
    	//如果k不为-1,表示前面的字符串最大公共前后缀长度为k
    	//这时,如果pattern[j]==pattern[k],表示j处的最大公共前后缀的长度可以增加1,即设置next[j+1]=k+1;
    	//因此,将k++,j++,next[j]=k即可
        if(k==-1||pattern[j]==pattern[k]) 
        {
    
    
            j++;k++;
            next[j]=k;
        }
        //如果不匹配,将最大公共前后缀的长度进行回溯,让k=next[k],去next[k]的位置进行对比       
        else //pattern[j]!=pattern[k]
            k=next[k];
    }
    return;
}

int strStr(char *text,char *pattern)
{
    
    
	//记录text与pattern的字符串的长度
    int length1=0,length2=0;
    char *p;
    p=text;
    while(*p++!='\0')
        length1++;
    p=pattern;
    while(*p++!='\0')
        length2++;
    //构建next数组
    int *next=(int*)malloc((length2+1)*sizeof(int));
    getnext(next,pattern);
    //i代表text,j代表pattern
    int i=0,j=0;
    while(i<length1&&j<length2)
    {
    
    
    	//如果回溯到j==-1,表示要j要从0开始重新匹配,i从下一个位置进行匹配
    	//如果text[i]==pattern[j],i与j同时增加
        if(j==-1||text[i]==pattern[j])
        {
    
    
            i++;j++;
        }
        else//如果j!=-1,并且text[i]!=pattern[j]
        {
    
    
        	//j往前回溯到next[j]的位置i不变;
            j=next[j];
        }
    }
    //如果退出循环,有两种情况,1是j==length2,这是表示已经匹配到,返回i-j的位置为起始匹配到的位置
    if(j==length2)
        return i-j;
    //反之表示没有匹配上
    else
        return -1;
}

KMP算法比较难理解,网上很多文章写得晦涩难懂,这里建议多看看视频演示原理。

另外由于next的数组不同的教材有不同的写法,例如有的直接将最大公共前后缀长度设为next,有的将最大公共前后缀数组向右边移动一位,把0位设为-1,本质上原理是一样的,只是在代码实现上有所区别

本文采用的是0位设为-1的方法

27. 移除元素

题目描述

//27. 移除元素
int removeElement(int* nums, int numsSize, int val){
    
    
        int i=0;
        for(;i<numsSize;)
        {
    
    
            if(nums[i]==val)
            {
    
    
                nums[i]=nums[--numsSize];
            }
            else
                i++;
        }
        return numsSize;
}

当遇到相同的元素,直接删除,删除时将最后一个元素移动到该位置

26. 删除排序数组中的重复项

题目描述

扫描二维码关注公众号,回复: 12730760 查看本文章
int removeDuplicates(int* nums, int numsSize){
    
    
    if(numsSize<=1)
        return numsSize;
    int i=0,j=1;
    for(;j<numsSize;)
    {
    
    
        if(nums[j]==nums[i])
            j++;
        else
            nums[++i]=nums[j];
    }
    return i+1;
}

由于是有序数组,用两个指针标记原数组与新数组的位置即可

21. 合并两个有序链表

题目描述

非递归方法:指针的操作,这里使用三个指针分别指向L1,L2与合并后的L3,注意指针为空的情况

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    
    
    struct ListNode*ptr1,*ptr2,*ptr3,*head;
    ptr1=l1;
    ptr2=l2;
    if(!ptr1)
        return ptr2;
    if(!ptr2)
        return ptr1;
    if(ptr1->val<=ptr2->val)
    {
    
    
        head=ptr1;
        ptr1=ptr1->next;
    }
    else
    {
    
    
        head=ptr2;
        ptr2=ptr2->next;
    }  
    ptr3=head;
    while(ptr1&&ptr2)
    {
    
    
        if(ptr1->val<=ptr2->val)
        {
    
    
            ptr3->next=ptr1;
            ptr1=ptr1->next;
        }          
        else
        {
    
    
            ptr3->next=ptr2;
            ptr2=ptr2->next;
        }      
        ptr3=ptr3->next;
    }
    if(ptr1)
        ptr3->next=ptr1;
    if(ptr2)
        ptr3->next=ptr2;
    return head;
}

递归的方法

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    
    
    if(!l1)
        return l2;
    if(!l2)
        return l1;
    if(l1->val<=l2->val)
    {
    
    
    //l1头结点较小,将l1->next与l2合并后,将l1->next赋值为合并的链表
        l1->next=mergeTwoLists(l1->next,l2);
        return l1;
    }
    else
    {
    
    
    //l2头结点较小,将l2->next与l1合并后,将l2->next赋值为合并的链表
        l2->next=mergeTwoLists(l2->next,l1);
        return l2;
    }
}

20. 有效的括号

题目描述

入职以后基本都转为写C语言了,所以在这里也改用C语言来做题,不过思路方法都是相通的。

bool isValid(char * s){
    
    
    char stack[5001];
    int top=0;
    while(*s!='\0')
    {
    
    
        stack[top++]=*s++;
        if(top>=2)
        {
    
    
            if((stack[top-2]=='('&&stack[top-1]==')')||(stack[top-2]=='['&&stack[top-1]==']')||(stack[top-2]=='{'&&stack[top-1]=='}'))
                top-=2;
            else  if((stack[top-1]==')'&&stack[top-2]!='(')||(stack[top-1]==']'&&stack[top-2]!='[')||(stack[top-1]=='}'&&stack[top-2]!='{'))
                return false;
        }
    }
    if(top!=0)
        return false;
    return true;
}

题目是一个很简单的栈的题,构建一个栈,入栈时,对比栈顶的两个字符是否匹配即可。如果同为左括号则不比对,如果栈顶为右括号)]},则需比对栈顶与栈顶下的元素是否匹配,o。

猜你喜欢

转载自blog.csdn.net/qq_35779286/article/details/113447874