day每日一练,数组中数字出现的次数

1.0 数组中数字出现的次数

数组中数字出现的次数
在这里插入图片描述
整体思路如下:举例 1 2 3 1 2 3 4 5
1.整体异或,最终的结果一定是不同数据的异或----结果一定不为0
2.异或结果一定有比特位是1,该位置意味着?不同的两个数据,该位置的比特位是不同的
3.假设是第n个位的比特位为1,根据遍历数组检测每一个数字的第n个位,根据是否为1,将其分为A、B两组
4.相同的数据,一定是在同一组,不同的数据,一定在不同组
5.从而将数组中两个不同的数分在了两组,转化为(一个整型数组除一个数字之外,其他数字都出现了两次,找出这一个只出现一次的数字)

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
    //1.整体异或
    int result = nums[0];
    for(int i=1;i<nums.size();i++)
    {
        result ^= nums[i];
    }
    //2.找比特位,从低到高
    int size = nums.size();

    int flag=1;
    int i=0;
    while(size > 0){
        if((flag<<i) & result)  //从最低位开始,依次去找比特位
        {
            flag <<= i;
            break;
        }
        i++;
        size--;
    }
    int a=0;
    int b=0;
    //3分组
    for(int i=0;i<nums.size();i++)
    {
        if((nums[i]&flag) == 0){
            a ^= nums[i];

        }
        else{
            b ^= nums[i];
        }
    } 
    return  {a,b};
    }
    
};

2.0 轮转数组

在这里插入图片描述
思路如下:
在这里插入图片描述
注意一种例外:旋转的次数(k)>= 数组的大小(numsSize)
k == nSize时,不旋转,就是想要的结果
k=10,nSize=7。旋转三次即为想要的结果
总结 : k= k%numSize

void Reserse(int* nums,int left,int right)
{
    while(left < right)
    {
        int tmp = nums[left];
        nums[left] = nums[right];
        nums[right] = tmp;

        ++left;
        --right;
    }
}
void rotate(int* nums, int numsSize, int k){
    if(k >= numsSize)
        k %= numsSize;
    //前n-k个数逆置,注意边界控制
    Reserse(nums,0,numsSize-k-1);
    //后k个逆置,注意边界控制
    Reserse(nums,numsSize-k,numsSize-1);
    //整体逆置
    Reserse(nums,0,numsSize-1);

}

3.0 合并有序数组

在这里插入图片描述

第一种情况:在这里插入图片描述
第二种情况:
在这里插入图片描述

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    int end1 = m-1, end2 =n-1;
    int end = m+n-1;

    while(end1 >= 0 && end2 >= 0)
    {
        if(nums1[end1] > nums2[end2])
        {
            nums1[end--] = nums1[end1--];
        }
        else
        {
            nums1[end--] = nums2[end2--];
        }
    }
    //判断哪一个先结束
    //nums1先结束,不用考,数据本身就在那里
    //处理num2还没有结束
    while(end2 >= 0)
    {
        nums1[end--] = nums2[end2--];
    }

}

4.0 删除数组中的重复项

在这里插入图片描述
在这里插入图片描述
双指针的一个变形
在这里插入图片描述

第二种情况:
在这里插入图片描述

int removeDuplicates(int* nums, int numsSize){
   if(numsSize == 0)
        return 0;
   
    int i =0,j =1;
    int dst = 0;
    while(j < numsSize)
    {
        if(nums[i] == nums[j])
        {
            ++j;
        }
        else
        {
            nums[dst] = nums[i];
            ++ dst;
            i = j;
            ++j;
        }
    }

    nums[dst] = nums[i];
    ++dst;

    return dst;  //返回的则是数组的大小
}

在这里插入图片描述

5.0 移除元素

在这里插入图片描述

int removeElement(int* nums, int numsSize, int val){
  int src =0, dst =0;
  while(src <numsSize)
  {
      if(nums[src] != val)
      {
          nums[dst] = nums[src];
          src++;
          dst++;
      }
      else
      {
          src++;
      }
  }
  return dst;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值