面试必备经典算法题目(c语言实现)

目录

前言:本章将会介绍三道来自leetcode上的经典题目,涉及到的思路主:双指针  

1:剑指 Offer 58 - II. 左旋转字符串 - 力扣(LeetCode)

2: 977. 有序数组的平方 - 力扣(LeetCode)                                                                                    

3:27. 移除元素 - 力扣(LeetCode)                                                                                                             

                               


          题目描述:

        给我们一个字符串,和给一个整数n要求我们将字符串中前n个字符旋转到字符串后面去。

        

下面我来介绍这道题的解法:-->

        解法1:暴力解法       时间复杂度为o(n^2)  

        思路:我们首先写出左旋1个字符的代码,然后在执行n次就行了。

                左旋一个字符的思路:我们先将首元素用tmp变量将它给保存起来,让后将首元素后面的元素移动到前面来,然后再将tmp放到最后一个位置。

       图:

        代码:

        

  while(n--)
    {
        char tmp=*s;
        int i =1;
        for(i=1;i<strlen(s);i++)
        {
            s[i-1]=s[i];//挪动元素
        }
        //最后一个字符改为原来的第一个
        s[i-1]=tmp;
    }

但是暴力解法在leetcode跑步过去,因为时间复杂度太高了。

        所以我们得换一种解法。

解法2:3步逆序字符串法     时间复杂度为O(N)   空间O(1)

        思路:我们先将字符串中前n个字符给逆序,在将n后面的字符串给逆序,最后在整体逆序就行了。原地修改字符串.

        在写代码的时候我们得注意字符串下标最大为n-1。

代码:

void reverse(char** pps,int left,int right)
{
    while(left<right)
    {
        char tmp=(*pps)[left];
        (*pps)[left]=(*pps)[right];
        (*pps)[right]=tmp;
        left++;
        right--;
    }
}

char* reverseLeftWords(char* s, int n){
    reverse(&s,0,n-1);//逆置前n个
    reverse(&s,n,strlen(s)-1);//逆置n后面
    reverse(&s,0,strlen(s)-1);//整体逆置
    return s;
}

解法三:切割+合并  时间O(n)   空间O(n)

        思路:将前n个字符给拿出来,且增加一个'\0'字符,剩下的字符也存储起来,最后将两个合并就行,后n个字符放在前面,前n个拼接在后面,就能够实现。

        代码:

char* reverseLeftWords(char* s, int n){
    n=n%(strlen(s)+1);
    char* ret1=(char*)malloc(sizeof(char)*(n+1));//放要旋转的字符还得放'\0'
    char* ret2=(char*)malloc(sizeof(char)*(strlen(s)+1));
    //先放要旋转的字符串
    int i=0;
    int j=0;
    for(i=0;i<n;i++)
    {
        ret1[j]=s[i];
        j++;
    }
    ret1[j]='\0';
    j=0;
    for(i=n;i<strlen(s);i++)
    {
        ret2[j]=s[i];
        j++;
    }
    int k =0;
    while(ret1[k]!='\0')
    {
        ret2[j++]=ret1[k++];

    }
    ret2[j]='\0';
  
    return ret2;

}

总结:在这三个方法中,第二种方法毫无疑问是最好的,但也是最难想到的。

        本题的分享完毕,让我们进入下一题。 

    

2: 977. 有序数组的平方 - 力扣(LeetCode)                                                                                                                                                                                                方法1:排序加遍历                                                                                                                      
思路:我们先将数组中的元素全部平方,然后在加个快速排序就可以解决了。                                时间复杂度:O(nlogn)                                                                                                                         代码实现:
 //时间复杂度O(n),空间复杂度O(n),双指针
int* sortedSquares(int* nums, int numsSize, int* returnSize){
    int left=0;
    int right=numsSize-1;
    while(left<=right)
    {  
        if(nums[left]*nums[left]>nums[right]*nums[right])
        {
            int tmp=nums[right];
            nums[right--]=nums[left]*nums[left];
            nums[left]=tmp;
        }
        else
        {
           nums[right--]=nums[right]*nums[right];
        }
    }
    * returnSize=numsSize;
    return nums;
}
图:                                                                                                                                                     
      
 方法2:  因为我们知道这个数组是一个有序数组,所以越往两边,平方的值越大,所以我们采用双指针的方法来进行求解,将大的元素给放在最后。
图:
  代码:
 //时间复杂度O(n),空间复杂度O(n),双指针
int* sortedSquares(int* nums, int numsSize, int* returnSize){
    //新开辟的一块空间,
    int* ret=(int*)malloc(sizeof(int)*numsSize);
    int i =numsSize-1;
    int left=0;
    int right=numsSize-1;
    while(left<=right)
    {
        if(nums[left]<0)
            nums[left]=-nums[left];
        if(nums[left]>nums[right])
        {
            ret[i--]=nums[left]*nums[left];
            left++;            
        }
        else
        {
             ret[i--]=nums[right]*nums[right];
            right--;           
        }
    }
    * returnSize=numsSize;
    return ret;
}
本题分享完毕--_--

3:27. 移除元素 - 力扣(LeetCode)                                                                                                     

 

   移除相同的元素:这题我们直接讲解双指针法,暴力解法我们就不讲了。

        双指针法:我们使用两个指针1个指针用来遍历整个数组的元素,另外一个指针用来修改数组中的元素。

 

        代码:

int removeElement(int* nums, int numsSize, int val){
    int fast=0;
    int slow=0;
    while(fast<numsSize)
    {
        if(nums[fast]!=val)
        {
            nums[slow]=nums[fast];
            slow++;
        }
        fast++;
    }
    return slow;
}

 本章经典算法题结束,如果你觉得对你有用的话,可以点个赞哦!

        如果有什么错误的地方,欢迎大佬来指点。

        

                               

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值