数组题——壹

1.删除有序数组中的重复项

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
题目链接

解析:
给定两个指针,prev指针的位置表示当前位置的元素为不含重复元素数组的最后一个元素的位置
另外一个指针则遍历数组
由于数组是有序的,因此相同的元素都会靠在一起
因此,当两个元素不相等时,则将遍历指针的元素填入不含重复数组之内

由于prev指向的是不含重复元素数组的最后一个元素的位置
因此返回的时候,需要+1才是真实数组的大小

这种方法只需要遍历一遍数组,所以时间复杂度为O(N),空间复杂度为O(1)

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size()==0)//为空
        return 0;

        int prev=0;
        int next=1;

        while(next<nums.size())
        {
            if(nums[prev]!=nums[next])
            {
                nums[prev+1]=nums[next];
                prev++;
            }    
            next++;
        }
        return prev+1;

    }
};

2.只出现一次的数字2

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
题目链接

解析:
由于其他数字都出现了3次,因此我们只需要将每个比特位的1的个数统计起来再对3取余,即可知道单独出现的元素,在此位置的比特位是1还是0,再根据出现的位置将所有的值加起来即可

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret=0;
        
        for(int i=0;i<32;i++)
        {
            int bit=0;
            for(auto e:nums )
            {
                bit+=(e>>i)&1;//统计每个数字在该位置的1的个数
            }
            ret+=(bit%3)<<i;//每个位的1的个数对3取模,得到单独出现的数在该位置的值
        }
        return ret;
    }
};

3.只出现一次的数字 III

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
题目链接

解析:
1.将全部数都异或,得到出现一次的数的异或结果
2.在得到的结果中找到bit位为1的位置,记录下来
3.根据bit位为1的位置,将数组分为两组再进行异或即可得到最终结果

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
  
        int val=0;
        for(auto e:nums )
        {
            val^=e;//得到全部异或的值
        }
        if(val==0)
        return  nums;

        int count=0;
        while(1)//找到bit为1的位置
        {
            if((val>>count)&1==1)
            break;
            count++;
        }

        int num1=0;
        int num2=0;
        for(auto e:nums)//分为两组进行异或
        {
            if((e>>count)&1==1)
            num1^=e;
            else
            num2^=e;
        }

        vector<int> ret;      
        ret.push_back(num1);
        ret.push_back(num2);

        return ret;
    }
};

4.数组中出现次数超过一半的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
题目链接

解析:
给定一个变量prev标记当前的数字,给定一个count记录当前数字剩余个数
当遍历数组,元素和prev相等,计数器+1。如果不相等,计数器-1;
当计数器为零时,我们换下一个标记元素

由于是两两抵消的,如果数组元素个数是偶数,那么最后剩下的元素就是超过数组一办的元素。
如果我们的元素个数是奇数,那么最后剩下的元素很有可能就是最后单下的元素,因此最后还需要循环判断一次

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        if(numbers.size()==0)//没有数字
            return 0;
        
        int prev=numbers[0];
        int count=1;
        for(int i=1;i<numbers.size();i++)
        {
            if(count==0)
                prev=numbers[i];
            if(numbers[i]==prev)
                count++;
            else
            {
                count--;
                if(count==0)
                    prev=0;
            }
        }
        if(count==0)//不存在
            return prev;
       
        count=0;
        for(int i=0;i<numbers.size();i++)
        {
            if(prev==numbers[i])
                count++;
        }
        if(count>numbers.size()/2)
            return prev;
        return 0;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值