手撕算法题1(附代码和解析)

1.轮转数组

在这里插入图片描述
题目:轮转数组
定义程序目标

数组元素右移,当数组元素越界时回到数组开头。

设计程序

循环k次

保存数组的最后一个元素
每次将数组的所有元素右移一位
将数组首元素置为数组最后一个元素

void rotate(int* nums, int numsSize, int k) {
    k%=numsSize;
    while(k--)
    {
        int end=nums[numsSize-1];
        for(int i=numsSize-1;i>0;i--)
        {
            nums[i]=nums[i-1];
        }
        nums[0]=end;
    }
}

嵌套循环,时间复杂度为O(N 2


设计程序

开辟一个新数组
循环N次(元素总个数)

用题目所给数组[下标]对新数组[(数组下标+右移次数)%元素总数]进行赋值

循环N次

用新数组[下标]]对题目所给数组数组[下标]进行赋值。

void rotate(int* nums, int numsSize, int k) {
    int*NewArr=(int*)malloc(sizeof(int)*numsSize);
    for(int i=0;i<numsSize;i++)
    {
        NewArr[(i+k)%numsSize]=nums[i];
    }
    for(int i=0;i<numsSize;i++)
    {
        nums[i]=NewArr[i];
    }
    }

时间复杂度为O(N)


设计程序

提供一个接口对数组进行逆置

将(N-K%7)元素逆置
将(K%7)元素逆置
将所有元素逆置

void reverse(int* nums,int left,int right)//进行逆置
{
    while(left<right)
    {
        int tmp=nums[left];
        nums[left]=nums[right];
        nums[right]=tmp;
        left++;
        right--;
    }
}


void rotate(int* nums, int numsSize, int k) {
    k%=numsSize;
   reverse(nums,0,numsSize-1-k);
   reverse(nums,numsSize-k,numsSize-1);
   reverse(nums,0,numsSize-1);
}

时间复杂度为O(1)


2.移除元素

在这里插入图片描述
移除元素
设计程序

定义两个指针soure和des,同时指向开头
遍历数组

当source不等于val时,soure和des同时++,将soure赋值给des
当source数值等于val时,des不变,soure++。
重复以上过程直到soure遍历完数组,此时des的大小就是有效数据的大小

返回des

int removeElement(int* nums, int numsSize, int val) {
    int src = 0, dst = 0;
    while (src < numsSize) {
        if (nums[src] == val) {
            src++;
        } else {
            nums[dst] = nums[src];
            dst++;
            src++;
        }
    }
    return dst;
}

当然还可以优化用for循环

int removeElement(int* nums, int numsSize, int val) {
   int des=0,src=0;
    for(;src<numsSize;src++)
    {
        if(nums[src]!=val)
        {
            nums[des]=nums[src];
            des++;
        }
    }
    return des;
}

3.删除有序数组中的重复项

在这里插入图片描述
删除有序数组中的重复项
设计程序

大题思路与上一道题相同
定义两个指针soure和des,同时des指向开头,soure指向后一个元素
遍历数组

当source等于des时有重复元素了,soure++。
当source数值不等于des时,des++,将source赋值给++后的des,source++。
重复以上过程知道soure遍历完数组,此时des+1的大小就是有效数据的大小

返回des+1。

int removeDuplicates(int* nums, int numsSize) {
    int des=0,src=1;
    for(;src<numsSize;src++)
    {
        if(nums[src]!=nums[des])
        {
            des++;
            nums[des]=nums[src];
        }
    }
    return des+1;
}

我就不赘述while循环怎么写了


4.合并两个有序数组

在这里插入图片描述
合并两个有序数组
设计程序

定义三个指针l1,l2,l3。l1指向num1(小)的末尾,l2指向num2的末尾,l3指向num1(大)的末尾
遍历数组(注意非递减顺序也就是递增末尾数据为最大)
当l1>l2,将l1(小)赋给l1(大)的末尾,l1–,l3–。
当l1<l2,将l2赋给l1(大)的末尾,l2–,l3–。
重复以上过程

退出循环此时要么l1(小)遍历完了,要么l2遍历完了。如果是l2遍历完了程序结束,如果是l1遍历完了,还要将l2剩余的元素赋给l1(大)自己代入数据就会很清楚为什么我们只处理l2不处理l1(小)了
在这里插入图片描述

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int l1=m-1,l2=n-1,l3=m+n-1;
    while(l1>=0&&l2>=0)
    {
        if(nums1[l1]>nums2[l2])
        {
            nums1[l3--]=nums1[l1--];
        }
        else
        nums1[l3--]=nums2[l2--];
    }
        while(l2>=0)
        {
            nums1[l3--]=nums2[l2--];
        }
}
  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值