zoukankan      html  css  js  c++  java
  • 【LeetCode-数组】移除元素

    题目描述

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

    给定 nums = [0,1,2,2,3,0,4,2], val = 2,
    函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    注意这五个元素可为任意顺序。
    你不需要考虑数组中超出新长度后面的元素。
    

    题目链接:https://leetcode-cn.com/problems/remove-element/

    思路1

    遍历数组,当遇到要移除的元素时,将该元素后面的元素整体前移一位,模拟移除该元素,并将数组长度减一。遍历结束时,返回当前的数组长度即可。代码如下:

    class Solution {
    public:
        int removeElement(vector<int>& nums, int val) {
            int length = nums.size();   //当前数组的长度
            int i=0;
            while(i<length){
                if(nums[i]==val){
                    for(int j=i; j<length-1; j++)
                        nums[j]=nums[j+1];
                    length--;
                }
                else i++;
            }
            return length;
        }
    };
    
    • 时间复杂度:O(n^2)
      时间复杂度最好为O(n)(该情况下不需要移除元素,遍历一遍即可),最差为O(n^2)(对应移除数组中所有元素的情况)。
    • 空间复杂度:O(1)
      申请额外内存不随输入规模的增大而增大。

    思路2

    使用两个指针i和j,其中i为慢指针,j为快指针。i,j都从数组头开始,j先出发,如果nums[j]!=val,则nums[i]=nums[j]并将i++,j遍历结束时,i就是此时的数组长度。代码如下:

    class Solution {
    public:
        int removeElement(vector<int>& nums, int val) {
            int i=0;
            for(int j=0; j<nums.size(); j++){
                if(nums[j]!=val){
                    nums[i] = nums[j];
                    i++;
                }
            }
            return i;
        }
    };
    
    • 时间复杂度:O(n)
      j遍历一遍数组就行,所以为O(n).
    • 空间复杂度:O(1)

    思路3

    思路2其实很好了,时间复杂度和空间复杂度都在大多数情况下都是最优的。但如果要删除的元素数量较少,例如输入为[1,2,3,4,5],删除1,那么数组还是有很多不必要的移动操作。解决这一问题的办法类似于思路1:记录当前数组的长度length并遍历数组,如果当前元素nums[i]==val,则交换当前元素与最后一个元素,也就是swap(nums[i], nums[length-1]),并将length--。只有nums[i]!=val时,才判断下一个元素(i++),因为如果nums[i]==val,通过swap(nums[i], nums[length-1]),nums[length-1]也可能是要删除的元素(例如[2,1,2],删除2)。代码如下:

    class Solution {
    public:
        int removeElement(vector<int>& nums, int val) {
            int i=0;
            int length = nums.size();   //当前数组的长度
            while(i<length){
                if(nums[i]==val){
                    swap(nums[i], nums[length-1]);
                    length--;
                } else {
                    i++;
                }
            }
            return length;
        }
    };
    

    -时间复杂度:O(n)
    i最多移动n步,所以时间复杂度为O(n)。这种情况下赋值的次数等于要删除元素的数量。
    -空间复杂度:O(1)

    总结

    当遇到删除数组中重复的元素时,可以使用一快一慢两个指针来解决。

  • 相关阅读:
    大型架构.net平台篇(中间层均衡负载WCF)
    大型高性能ASP.NET系统架构设计
    百万级访问量网站的技术准备工作
    容器管理的分布式事务
    SQL Server 2005实现负载均衡
    nginx负载均衡 tomcat集群 memcache共享session
    JTA实现跨数据库操作
    [AX]AX2012 Table的AOSAuthorization 属性
    [AX]AX2012 Form上的ReferenceGroup control
    [AX]AX2012 Form开发概览
  • 原文地址:https://www.cnblogs.com/flix/p/12646287.html
Copyright © 2011-2022 走看看