找唯一不出现三次而出现1次的数子O(n)位运算算法

之前两次那个是异或运算处理。这次以为也是类似。可是没想出来。

高富帅想出来了算法,转为bitset,然后加起来 同样的话 要么0+0+0 要么1+1+1,最后剩下的 能够通过%3 算出0 或1。思想是这样,

事实上也是bit运算。仅仅只是不是异或这样的一次运算O(1)这样的,可是因为输入是int数组,-2^31~2^31-1 所以用32bit就能够表示了。

之前遇到,过几次错误,包含分配存储空间的问题,正如fawks说的。用全局数组,是在全局区域,比栈空间大非常多。所以能够申请大数组,可是leetcode向来

不给数据范围的,只是从int也能够知道了,可是leetcode是class的,public成员貌似也是栈。结果出错。顺便说一下leetcode非常多WA都说成TLE。。

。还有其它的类型指定错误。

后来发现有个负数的问题,负数取模符号位是异或(-7/-4=1.....-3, -7/4=-1....-3, 7/-4=-1.....3, 7/4=1....3  因此也能够归纳出,商的符号是除数被除数异或,余数符号是被除数符号),于是这样数组就变成负数了,为了便于处理。都辩证。可是最后符号位怎么判呢? 事实上都当成数组处理,3m个1,3n个1 另一个0/1,

加起来取模照样把代表符号位的0 1取出来。

可是从报错问题来看,另一个-2^31出错了,后来想想是的, 符号位变1,然后后面变为10000 1+31个0 结果那个1都装不下了,于是他的补码是10000000,所以要专门处理。

这里实现了比較底层的。实现了补码。

处理好逻辑后提交。最终过了T T

时间复杂度 O(32n)=O(n),空间复杂度O(1)

PS: 代码前面那些直接copy了圆神的代码:)

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <sstream>
#include <iomanip>
#define Min(a,b) (((a) < (b)) ?

(a) : (b))
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
using namespace std;
//#define MAXBITNUM 32
//#define MAXNUM 100000
//int bitnumvec[MAXNUM][MAXBITNUM];
int singleNumber(int A[], int n) {
	//vector<int*> vec;
	if(n==1) return A[0];
	const int MAXBITNUM=32;
    //int bitnumvec[MAXNUM][MAXBITNUM];

	int** bitnumvec=new int*[n];
	for(int i=0;i<n;i++)
		bitnumvec[i]=new int[MAXBITNUM]();

        for(int i=0;i<n;i++)
		{
			int offset=MAXBITNUM-1;
			if(A[i]==-pow(2.0,31))//-2^31
			{
				bitnumvec[i][0]=1;//, 10000000...000
			}
			else//others
			{
				if(A[i]<0&&A[i]>-pow(2.0,31))//negative
				{
					bitnumvec[i][0]=1;//1 means negative, 0 means positve
					A[i]=-A[i];
				}
				while(A[i]!=0)
				{
					bitnumvec[i][offset]=A[i]%2;
					//bitnum[offset]=A[i]%2;
					A[i]=A[i]/2;
					offset--;
				}
			}
			//reverse(vec.begin(),vec.end());
			//vec.push_back(bitnum);
		}
		//memset(bitnum,0,sizeof(int)*MAXBITNUM);
		int bitnum[MAXBITNUM];
		memset(bitnum,0,sizeof(int)*MAXBITNUM);
		int x=0;
		for(int i=0;i<MAXBITNUM;i++)
		{
			//if(i==MAXBITNUM-1)
			//	int y=1;
			for(int j=0;j<n;j++)
			{
				//if(bitnumvec[j][0]==0)
					bitnum[i]+=bitnumvec[j][i];
				//else if(bitnumvec[j][0]==1)
				//	bitnum[i]-=bitnumvec[j][i];
			}
			bitnum[i]=bitnum[i]%3;
			if(i>0)
				x+=bitnum[i]*pow(2.0,MAXBITNUM-1-i);
		}
		if(bitnum[0]==1 &&x !=0)
			x=-x;
		else if(bitnum[0]==1 && x==0)
			x=-pow(2.0,31);
		//for(int i=0;i<MAXBITNUM;i++)

		//int x;
		//for(int i=0;i<MAXBITNUM;i++)

		for(int i=0;i<n;i++)
			delete[] bitnumvec[i];
		delete[] bitnumvec;
		return x;
}
int main()
{
	//int x=-3%2;
	int a[]={-2,-2,-2147483648,-2};
	cout<<singleNumber(a,4)<<endl;
	return 0;
}
时间: 2024-10-24 11:34:42

找唯一不出现三次而出现1次的数子O(n)位运算算法的相关文章

找球号(三)

找球号(三) 时间限制:2000 ms  |  内存限制:3000 KB 难度:2 描述 xiaod现在正在某个球场负责网球的管理工作.为了方便管理,他把每个球都编了号,且每个编号的球的总个数都是偶数.有一天,xiaod发现少了一个球,你能帮他找出丢的那个球的球号吗? 输入 有多组测试数据.每组数据包括两行. 第一行是一个整数N(0<N<1000000),表示现在所剩的球数. 随后的一行是N个数,表示所剩的各个球的编号M(0<M<10^9). 输出 对于每组数据,输出弄丢的那个球的

找球号(三)南阳acm528(异或&#39; ^ &#39;)

找球号(三) 时间限制:2000 ms  |  内存限制:10000 KB 难度:2 描述 xiaod现在正在某个球场负责网球的管理工作.为了方便管理,他把每个球都编了号,且每个编号的球的总个数都是偶数.有一天,xiaod发现少了一个球,你能帮他找出丢的那个球的球号吗? 输入 有多组测试数据.每组数据包括两行. 第一行是一个整数N(0<N<1000000),表示现在所剩的球数. 随后的一行是N个数,表示所剩的各个球的编号M(0<M<10^9). 输出 对于每组数据,输出弄丢的那个球

NYOJ528-找球号(三) 【位运算】

http://acm.nyist.net/JudgeOnline/problem.php?pid=528 找球号(三) 时间限制:2000 ms  |  内存限制:3000 KB 难度:2 描述 xiaod现在正在某个球场负责网球的管理工作.为了方便管理,他把每个球都编了号,且每个编号的球的总个数都是偶数.有一天,xiaod发现少了一个球,你能帮他找出丢的那个球的球号吗? 输入 有多组测试数据.每组数据包括两行.第一行是一个整数N(0<N<1000000),表示现在所剩的球数.随后的一行是N个

bestcoder #71 1003 找位运算&amp;的最大生成树

Clarke and MST Accepts: 33 Submissions: 92 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 克拉克是一名人格分裂患者.某一天克拉克变成了一名图论研究者. 他学习了最小生成树的几个算法,于是突发奇想,想做一个位运算and的最大生成树. 一棵生成树是由n-1n−1条边组成的,且nn个点两两可达.一棵生成树的大小等于所有在生成树上的边的权

nyist oj 138 找球号(二)(hash 表+位运算)

找球号(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 在某一国度里流行着一种游戏.游戏规则为:现有一堆球中,每个球上都有一个整数编号i(0<=i<=100000000),编号可重复,还有一个空箱子,现在有两种动作:一种是"ADD",表示向空箱子里放m(0<m<=100)个球,另一种是"QUERY",表示说出M(0<M<=100)个随机整数ki(0<=ki<=100000100),分

位运算 找出给定的数中其他数都是两个,有两个是一个的数

题目大意: 给定你n个数, 其中有n-2个数都是两两成对的,有两个是单独出现的,如n = 8, 2 3 2 5 3 6 4 6, 这时候4和5是单独的两个,所以答案就是4,5,其中n的范围是1e6. 思路: 之前做过找一个单独的数的题,那个题是用一个比较巧妙的方法来做的,不过这个也是一类经典问题,用到了强大的位运算,有了那个题的基础再来做这个题就简单了.(附:找一个的题目链接). 刚开始我是用了O(nlogn)的时间复杂度来做的,先排序,然后用类似找一个的方法找出第二个.我觉得对于1e6的数据量

JavaSE学习(三):按位运算—数据结构(顺序、分支、循环)

  第一节 按位运算 1.1按位运算符&  | 1.1.1按位运算符可作算术运算 做算术运算先将十进制转为二进制数,再按位计算,按位与全部为1,才为1,只要有0则为0:按位或只要有1则为1,全部为0才为0.最后按位输出再转为十进制. 7&3 = 3  -----  0111 & 0011 == 0011  3 7|3 = 7  -----  0111 & 0011 == 0011  7 1.1.2按位运算符可作逻辑运算 按位与&和按位或| 做逻辑功能时,与逻辑与&a

一个序列,除了一个数出现两次,其他数都出现一次,找出来重复的这个数-位运算应用(异或运算)

一个序列,除了一个数出现两次,其他数都出现一次,找出来重复的这个数-位运算应用 面试的题目 贴一下代码: 1 //位运算应用 2 #include<bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 const int maxn=1e5+10; 6 7 int n; 8 int a[maxn]; 9 10 void found(){ 11 int xors=0; 12 for(int i=0;i<n;i++){

使用天平3次,从12个乒乓球找唯一1个轻重未知的废品

前些天在知乎看到一个问如何鉴定程序员水平的问题,其中一个答主建议用智力题考验程序员解决问题的能力(我们在此不讨论答主的观点),然后就留了这么一个问题供大家思考.当时思考了一阵,没头绪(我真不是答主认为的优秀程序员╯□╰)就此放下了.恰好今天在看<控制论与科学方法论>这本书时,看到这本书对此题目的解答,但文中只给了第一步的推倒,然后就同理了……然后我就纠结了N久,才把这个同理给想明白.下面把书中的解法和自己想明白的分享给大家. 书中是使用控制能力来分析的(控制能力 = 原可能性空间大小 / 施加