【LeetCode】顺序表练习 3 道题

第一题:移除元素

题目描述:

给你一个数组nums和一个值val,你需要 原地 移除所有数值等于val的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用O(1)额外空间并 原地 修改输入数组
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

  • 0 <= nums.length <= 100
  • 0 <= nums[i] <= 50
  • 0 <= val <= 100
//题目框架
int removeElement(int* nums, int numsSize, int val){
    
    
}

方法一:

可以使用覆盖删除的方式来解决这道题。
遍历所给数组,如果遇到val,就去寻找数组后面不是val的值进行交换,直到数组遍历完。
参考代码如下:

//时间复杂度:O(n^2)
//空间复杂度:O(1)
int removeElement(int* nums, int numsSize, int val)
{
    
    
    int i = 0;
    for(i = 0; i < numsSize; ++i)
    {
    
    
        if(nums[i] != val)
        {
    
    
            ;
        }
        else//nums[i]==val
        {
    
    
            for(int j = i + 1; j < numsSize; ++j)
            {
    
    
            	//num[j]!=val,才能和val交换
            	//num[j]==val,就跳过
                if(nums[j] != val)
                {
    
    
                    int tmp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = tmp;
                    break;
                }
            }
        }
    }

	//遍历数组,求移除元素后数组的长度
    for(i = 0; i < numsSize; ++i)
    {
    
    
        if(nums[i] == val)
        {
    
    
            break;
        }
    }
    return i;
}

方法二:

可以使用前后指针的方式来解决这道题。
定义两个指针变量frontback,当back遇到的值不是val,就把他赋值给front位置;back遇到的值是val,`back``就跳过,继续寻找,直到遍历数组完成。
参考代码如下:

//时间复杂度:O(n)
//空间复杂度:O(1)
int removeElement(int* nums, int numsSize, int val)
{
    
    
    int* front = nums;
    int* back = nums;

    while(back < nums + numsSize)
    {
    
    
        if(*back != val)
        {
    
    
            *front = *back;
            ++front;
            ++back;
        }
        else
        {
    
    
            ++back;
        }
    }

    return front - nums;
}

第二题:删除有序数组中的重复项

题目描述:

给你一个升序排列的数组nums,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

  • 1 <= nums.length <= 3 * 10^4
  • -10^4 <= nums[i] <= 10^4
  • nums 已按 升序 排列
//题目框架
int removeDuplicates(int* nums, int numsSize){
    
    
}

方法一:

这道题可以使用前后指针的方式来解决。
定义两个指针变量frontbackbackfront后一个位置(back=front+1),当back遇到的值和front相等的话,back就跳过;back遇到的值和front不等的话,就赋值给front的下一个位置。
参考代码如下:

//时间复杂度:O(n)
//空间复杂度:O(1)
int removeDuplicates(int* nums, int numsSize)
{
    
    
    if(numsSize<2)
    {
    
    
        return numsSize;
    }

    int* front = nums;
    int* back = nums + 1;

    while (back < nums + numsSize)
    {
    
    
        if (*back == *front)
        {
    
    
            ++back;
        }
        else
        {
    
    
            ++front;
            *front = *back;
            ++back;
        }
    }

    return front - nums + 1;
}

第三题:合并两个有序数组

题目描述:

给你两个按 非递减顺序 排列的整数数组nums1nums2,另有两个整数mn,分别表示nums1nums2中的元素数目。
请你 合并nums2nums1中,使合并后的数组同样按 非递减顺序 排列。

  • nums1.length == m + n
  • nums2.length == n
  • 0 <= m, n <= 200
  • 1 <= m + n <= 200
  • -10^9 <= nums1[i], nums2[j] <= 10^9
//题目框架
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    
    
}

方法一:

额外开辟一个m+n大小的数组,通过nums1nums2两个数组元素的比较进行归并,最后将归并后的数据顺序拷贝回num1数组。
参考代码如下:

//时间复杂度:O(m+n)
//空间复杂度:O(m+n)
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
    
    
    int* arr = (int*)malloc((m + n) * sizeof(int));

    int* end1 = nums1 + m;
    int* end2 = nums2 + n;
    int* ptr = arr;
    while (nums1 < end1 && nums2 < end2)
    {
    
    
        if (*nums1 < *nums2)
        {
    
    
            *ptr = *nums1;
            ++nums1;
            ++ptr;
        }
        else
        {
    
    
            *ptr = *nums2;
            ++nums2;
            ++ptr;
        }
    }
    if (nums1 == end1)
    {
    
    
        while(nums2 < end2)
        {
    
    
            *ptr = *nums2;
            ++ptr;
            ++nums2;
        }
    }
    else
    {
    
    
        while (nums1 < end1)
        {
    
    
            *ptr = *nums1;
            ++ptr;
            ++nums1;
        }
    }

	//将数据拷贝回nums1数组
    nums1 = end1 - m;
    for(int i = 0; i < m + n; ++i)
    {
    
    
        nums1[i] = arr[i];
    }
}

方法二:

这种方法是从nums1和nums2的尾部开始比较大小进行归并的,将较大值直接归并到nums1数组的尾部位置。
参考代码如下:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
    
    
    int* dest = nums1 + m + n - 1;
    int* src1 = nums1 + m - 1;
    int* src2 = nums2 + n - 1;

    while (src1 >= nums1 && src2 >= nums2)
    {
    
    
        if (*src1 > *src2)
        {
    
    
            *dest = *src1;
            --dest;
            --src1;
        }
        else
        {
    
    
            *dest = *src2;
            --dest;
            --src2;
        }
    }

	//nums2没有归完需要继续归
	//因为归并的目标数组就是nums1,所以nums1没有归完也不需要继续循环归并了
    while(src2 >= nums2)
    {
    
    
        *dest = *src2;
        --dest;
        --src2;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_62172209/article/details/129762469
今日推荐