• 面试40-一个数组,有2个数字出现奇数次,其余都是偶数次,求这两个数字O(n) O(1)


    #include<iostream>
    using namespace std;
    // 题目:数组中只有不多于两个数字出现次数是奇数次,其他都是偶数次,求出出现奇数次的数字(不含0的数组)
    
    //思想:
    /*
    (1)如果只有一个数字是奇数次,直接对数组进行按位异或运算,得到的结果就是该数
    (2)如果有俩个,可以先对数组异或,得到的结果(就是两个奇数次的数字异或的结果),必定至少包含一个1,可以根据这个1在的位置,把数组分为两个部分
         则两个奇数次的数字必定分别在两个部分,而相同的数次必定在同一组,则可以对两个部分分别求异或得到答案
    */
    int findNumsAppear(int arr[],int len,pair<int,int>& st);// 返回0表示没有,1表示一个,2表示2个,-1表示参数错误,没有考虑更多的情况
    int count1(int num);// 统计int在内存中1的个数
    int main()
    {
        pair<int,int>st;
        st.first=0x80000000;
        st.second=0x80000000;
        int arr[]={2,2,2,1,1,4,4,4,4,3,5,5,6,6,6,6,7,7,8,8,9,9,10,10,11,11};
        cout<<findNumsAppear(arr,sizeof(arr)/sizeof(int),st)<<endl;
        cout<<st.first<<"   "<<st.second<<endl;
        return 0;
    }
    int findNumsAppear(int arr[],int len,pair<int,int>& st)
    {
        if(arr==NULL||len<=0)
            return -1;
        int num=arr[0];
        int count=0;
        for(int i=1;i<len;i++)
            num^=arr[i];
        if(num==0)
            return 0;
        else  // 找到num 中第一个1,让其他位置1为0   此处参考count1的方法
        {
            while(num)
            {
                if((num&(num-1))==0)
                    break;
                else
                    num=num&(num-1);   // 最终会保留下最高位的一个1,用来划分数组
            }
        }
        int i=0;int j=len-1;
        int tmp;
        while(i<j)   // 循环最终结果为i==j 左半边数组的最后个元素下标
        {
            while(i<j&&(arr[j]&num)==0)
                j--;
            while(i<j&&(arr[i]&num)==num)
                i++;
            if(i<j)
            {
                tmp=arr[i];
                arr[i]=arr[j];
                arr[j]=tmp;
            }
        }
        int num1=arr[0];
        for(int k=1;k<=i;k++)
            num1^=arr[k];
    
        int num2=arr[len-1];
        for(int k=len-2;k>i;--k)
            num2^=arr[k];
        if(num1!=0)
            st.first=num1;
        if(num2!=0)
            st.second=num2;
        if(num1!=0&&num2!=0)
            return 2;
        else return 1;
    }
    int count1(int num) // 如果不许用位运算,直接 unsigned int n=(unsigned int)num; 用%  / 计算    -1内存全部为FFFFFFFF 转为最大的unsigned int
    {
        int count=0;
        while(num)
        {
            ++count;
            num=num&(num-1);
        }
        return count;
    }
  • 相关阅读:
    烂泥:KVM使用NAT联网并为VM配置iptables端口转发
    烂泥:CentOS6.5挂载windows共享文件夹
    烂泥:KVM、kickstart与FTP集成
    js-浅显基础-正则表达式集
    小程序-轮播图案例
    小程序-TabBar点击切换
    js-禁止微信内置浏览器调整字体大小
    小程序-分享到群或好友
    小程序-提交信息(姓名,电话)
    js-在url后面添加时间戳清除浏览器打开页面的缓存
  • 原文地址:https://www.cnblogs.com/fchy822/p/4798414.html
Copyright © 2020-2023  润新知