【时间复杂度】

旋转数组
题目
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

/*
解题思路:使用三次逆转法,让数组旋转k次
1. 先整体逆转
// 1,2,3,4,5,6,7
// 7 6 5 4 3 2 1
2. 逆转子数组[0, k - 1]
// 5 6 7 4 3 2 1
3. 逆转子数组[k, size - 1]
// 5 6 7 1 2 3 4
*/
void reverse(int* nums, int begin, int end)
{
    while(begin < end)
    {
        int tmp = nums[begin];
        nums[begin] = nums[end];
        nums[end] = tmp;

        ++begin;
        --end;
    }
}

// 三趟逆置倒的思路
void rotate(int* nums, int numsSize, int k){
    if(k > numsSize)
    {
        k %= numsSize;
    }
    
    reverse(nums, 0, numsSize-1);
    reverse(nums, 0, k-1);
    reverse(nums, k, numsSize-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--;
    }
    return ;
}


void rotate(int* nums, int numsSize, int k){
    //如果k大于numsSize
    // if(k>=numsSize)
    //     k = k%numsSize;
    reverse(nums,numsSize-k,numsSize-1);
    reverse(nums,0,numsSize-k-1);
    reverse(nums,0,numsSize-1);
    return ;
}

总结:
这道题目有两种思路(对于这种三次逆序的解法)

案例:nums = [1,2,3,4,5,6,7], k = 3 [5,6,7,1,2,3,4]
思路1:先去整体逆序、再去逆序0到k-1和k到n-1(后两个的顺序都可以,主要是得先去逆序0到n-1)
思路2:先去逆序(n-k)到n-1和(0到n-k-1),再去逆序0到n-1(需要最后去逆序整体0到n-1)
综上所述:先去逆序整体再去逆序两部分和先去逆序两部分再去逆序整体两种思路

当然还可以通过以空间换取时间的解决方法

void rotate(int* nums, int numsSize, int k){
    // 新的思路:使用拷贝+开辟新空间
    int n = numsSize;
    int* temp = (int*)malloc(n*sizeof(int));

    k%=n;
    //拷贝三步走
    
    memcpy(temp,nums+n-k,sizeof(int)*k);
    // 拷贝n-k到n-1
    memcpy(temp+k,nums,sizeof(int)*(n-k));
    // 拷贝0到k个 
    memcpy(nums,temp,sizeof(int)*n);
    // 将temp拷贝回去nums
    free(temp);
    temp = NULL;
}

消失的数字
题目
数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?

int missingNumber(int* nums, int numsSize) {
    int t = 0;
    for(int i=0;i<numsSize+1;i++)
    {
        t^=i;
    }
    for(int j=0;j<numsSize;j++)
    {
        t^=nums[j];
    }
    return t;
}

给定一个整数sum,从有N个有序元素的数组中寻找元素a,b,使得a+b的结果最接近sum,最快的平均时间复杂度是( )

使用双指针法来解决。(整个数组被搜索一遍,就可以得到结果)
双指针法的时间复杂度是O(N),其中N是数组的长度。
具体的做法是,初始化两个指针left和right,分别指向数组的起始位置和结束位置。
然后,通过不断移动指针来逼近sum。每次比较a+b与sum的差值的绝对值,更新最接近sum的结果。

具体步骤如下:
1. 初始化两个指针left和right,分别指向数组的起始位置和结束位置。
2. 初始化最接近sum的结果为无穷大。
3. 进入循环,直到left大于等于right为止:
   - 计算当前指针所指的元素a和b的和sum_ab。
   - 如果sum_ab等于sum,直接返回a和b。
   - 否则,更新最接近sum的结果,如果当前差值的绝对值小于之前的最小差值,则更新结果。
   - 如果sum_ab小于sum,将left指针向右移动一位。
   - 如果sum_ab大于sum,将right指针向左移动一位。
4. 返回最接近sum的结果。
总结起来,使用双指针法可以在最快的平均时间复杂度O(N)内解决这个问题。

设某算法的递推公式是T(n)=T(n-1)+n,T(0)=1,则求该算法中第n项的时间复杂度为()

该算法的递推公式是T(n) = T(n-1) + n,初始条件是T(0) = 1。
根据递推公式,我们可以展开算法的时间复杂度如下:
 T(n) = T(n-1) + n
     = (T(n-2) + (n-1)) + n
     = T(n-2) + (n-1) + n
     = T(n-3) + (n-2) + (n-1) + n
     = ...
     = T(0) + 1 + 2 + 3 + ... + (n-2) + (n-1) + n

我们知道等差数列的求和公式是:S = (n/2)(a + l),其中n是项数,a是首项,l是末项。
在这个算法中,首项a=1,末项l=n,项数n。将这些值代入公式,我们可以得到:
 T(n) = 1 + 2 + 3 + ... + (n-2) + (n-1) + n
     = (n/2)(1 + n)
     = (n^2 + n)/2
因此,该算法的第n项的时间复杂度为O(n^2)。
T(n)
=T(n-1)+n
=T(n-2)+(n-1)+n
=T(n-3)+(n-2)+(n-1)+n
...
=T(0)+1+2+...+(n-2)+(n-1)+n
=1+1+2+...+(n-2)+(n-1)+n
=1+(n+1)*n/2

但是:【时间复杂度】_第1张图片

你可能感兴趣的:(#,数据结构(初),数据结构,算法)