数据结构初阶——复杂度OJ练习题

第一题

对于该题,最能想到应该有四种方法:

1. 排序

可以将元素排序好,再遍历一遍数组看后一个是否是前一个元素的值+1,但是从对于初学者掌握的无非就是冒泡排序或者qsort

很遗憾,虽然但是,不满足题目的时间复杂为O(n),因为冒泡排序的时间复杂度为O(n^2),qsort的时间复杂度为O(nlogn)因此,因此不行

2. 映射

开辟一个数组并初始化为-1(因为有0的存在),把对应的数字放入对应的数组下标所对应的数组元素中,然后再遍历一遍数组,出现负数的那个元素则为缺少的数字

很遗憾,虽然但是,要使用数组开辟空间,空间复杂度为O(n),因此不行

3. 使用操作符 ^

使用异或操作符,利用它的两个特性,同样的数字异或以后为0,不论顺序,一个数字与0异或为本身,空间复杂度O(1),时间复杂度为O(n)

所以可以!附上代码

int missingNumber(int* nums, int numsSize) {
    int i = 0;
    int temp = 0;

    //先和数组异或
    for (i = 0; i < numsSize; i++)
    {
        temp ^= nums[i];
    }

    //再和0~n的数字异或,就得到缺少的数字
    for (i = 0; i <= numsSize; i++)
    {
        temp ^= i;
    }

    return temp;
}

4. 等差数列

因为是0~n的数字,因此,这是一个等差数列,所以先把0~n的数字求和,再减去数组中的所有元素,剩下的数字即为所缺数字,时间复杂为O(n),空间复杂度为O(1),因此可行,附上代码

int missingNumber(int* nums, int numsSize) {
    int i = 0;
    //等差数列求和
    int Sn = ((0 + (numsSize)) * (numsSize + 1)) / 2;
    //减去数组中的每个值,即剩下的就是缺少值
    for (i = 0; i < numsSize; i++)
    {
        Sn -= nums[i];
    }
    return Sn;
}

第二题

 题目要求至少三种方法,这道题最容易能想到能想到两种,第三种不太好想到

1. 右旋k次,依次移一个

先把数组最后一个元素先给放到一个临时变量temp中,然后将数组中的元素从第一个开始依次往后赋值,最后将temp中的值赋给第一个元素,即完成了一次的右旋,右旋k次即按这个思路进行k次

这个方法的空间复杂度是O(1), 但是,时间复杂度是O(n*k),为什么是k呢?

因为这种情况最好的结果是k=1,但是最坏的结果却是要旋转n-1次(k % N = N - 1),也就是说,时间复杂度最差能到O(n^2),受k影响过大,所以用k最好

很遗憾,虽然但是,这种方法leetcode不给过,时间超出限制,时间复杂度太差!

2. 额外开数组

开过个数组,然后把k个元素放过去,很简单

很遗憾,虽然但是,空间复杂度和时间复杂度都是O(n),不满足要求!

3. 逆置三次

前N~K个元素逆置,后K个逆置,然后整体逆置

时间复杂度为O(n),空间复杂度为O(1),满足

代码如下

void reverse(int* nums, int left, int right)
{
    while(left < right)
    {
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
        ++left;
        --right;
    }
}


void rotate(int* nums, int numsSize, int k){
    //防越界
    k %= numsSize;
    //前面部分逆置
    reverse(nums, 0, numsSize-k-1);
    //后面部分逆置
    reverse(nums, numsSize-k, numsSize-1);
    //全部逆置
    reverse(nums, 0, numsSize-1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hiland.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值