数组经典三大题

1.原地删除所有x

  给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-element

1.1思想

  遍历(i)数组元素,如果找到所删除的值,则标记(j)此处位置,继续向后遍历(i),直至没有找到所删除的值;如果没有找到删除的值,则把当前位置元素赋值给标记处位置,然后继续向后遍历(i,j),直至遍历所有元素

1.2画图

原地删除所有x

1.3代码

int removeElement(int* nums, int numsSize, int val){
    //双游标i,j
    int i = 0;
    int j = 0;
    
    //循环numsSize次
    while(i < numsSize)
    {
        //如果游标i等于所删除的元素,i就往后移动一位
        if(nums[i] == val)
            i++;
            
        //如果游标i不等于所删除的元素,游标i指向的元素
        //就会把游标j指向的元素覆盖掉,然后i与j都向后移动一位
        else
            nums[j++] = nums[i++];
    }

    //返回数组长度(因为j此时已经指向最后一个元素的后一个位置)
    return j;
}

1.4复杂度

时间复杂度:O(n)
空间复杂度:O(1)

2.原地删除重复项(有序数组)

  给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array

2.1思想

  遍历(i)数组,若果找到重复值,则标记(j)该重复值第一次出现的位置,继续遍历(i)直到不再出现重复值的位置,则将该位置赋值到标记(j)的下一个位置(j+1),继续遍历直至删除所有重复值。

2.2画图

原地删除重复项

2.3代码

int removeDuplicates(int* nums, int numsSize){
    //双游标
    int i = 0;
    int j = 0;
    
    //循环numsSize次
    while(i < numsSize)
    {
        //如果游标i所指向的内容等于游标j所指向的内容,i就往后移一位
        if(nums[i] == nums[j])
            i++;

        //如果游标i所指向的内容不等于游标j所指向的内容
        //先让j往后移一位,再把游标i所指向的内容赋值给游标j所指向的内容
        //i再往后移一位
        else
            nums[++j] = nums[i++];
    }

    //返回数组长度(因为j此时指向最后一个元素)
    return j + 1;
}

2.4复杂度

时间复杂度:O(n)
空间复杂度:O(1)

3.合并有序数组

  给你两个按非递减顺序排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/merge-sorted-array

3.1思想

  从有效元素末尾比较两个数组的大小,数组元素较大的赋值到新数组,以此循环直至两个数组合并完成。

3.2画图

合并有序数组

3.3代码

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    int i1 = m -1;     //指向数组nums1有效元素最后一个位置
    int i2 = n - 1;    //指向数组nums2最后一个位置
    int j = m + n -1;  //指向数组nums1的最后一个位置

    //如果i1与i2同时不为空就进入循环,比较两个数组的元素,并合并
    while(i1 >= 0 && i2 >= 0)
    {
        //如果此时数组nums1的元素大于数组nums2的元素
        //将数组nusm1当前元素赋值到j所标记的位置,并且游标i1与游标j向左移动一位
        if(nums1[i1] > nums2[i2])
            nums1[j--] = nums1[i1--];

        //如果此时数组nums1的元素小于数组nums2的元素
        //将数组nusm2当前元素赋值到j所标记的位置,并且游标i2与游标j向左移动一位
        else
            nums1[j--] = nums2[i2--];
    }

    //如果nums2还有剩余的元素未合并,则直接将他们赋值到nums1当中游标j所指向的位置
    //并且游标i2与游标j向左移动一位
    while(i2 >= 0)
        nums1[j--] = nums2[i2--];
}

3.4复杂度

时间复杂度:O(n)
空间复杂度:O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值