single number

本文详细阐述了三种解决特定算法问题的方法:单个元素查找、数组中唯一元素识别及重复次数为一次的数字识别。通过引入高效算法和技巧,如异或运算、位操作等,实现了O(n)的时间复杂度,展示了在不同场景下的应用和优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有先排序在求的,O(nlogn)

1.

// Single Number.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

int singleNumber(int A[], int n) 
{
	if(A == NULL || n == 2)
		return -1;
	else if (n == 1)
		return A[0];
	int num = A[0];
	for(int i = 1; i < n; ++ i)
	{
		num ^= A[i];
	}
	return num;
}

//=====================================================
void Test(char* testName, int* A, int len, int expected)
{
	if(testName != NULL)
        printf("%s begins: \n", testName);
	
	for(int i = 0; i < len;++ i)
	{
		cout<<A[i];
	}
	cout<<endl;

	int result = singleNumber(A, len);
	cout<<"result: "<<result<<endl;
	if(result == -1 && expected == -1)
		cout<<"Passed!"<<endl;
	else
		cout<<"Failed!"<<endl;
	
}


void Test1()
{
	int A[1] = {1};
	Test("Test1", A, 1, 1);
}

int _tmain(int argc, _TCHAR* argv[])
{
	Test1();
	return 0;
}

2

// Single Number.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
//一个数组中数成对出现,除了两个数,找出这两个数,O(N)
unsigned int FindFirstBitIs1(int number)
{
	int indexBit = 0;
	//完全不知道应该用sizeof计算位数
	while((number & 1) == 0 && indexBit < 8 * sizeof(int))
	{
		number = number >> 1;
		++ indexBit;
	}
	return indexBit;
}

bool IsBit1(int num, unsigned int indexOf1)
{
	//直接右移多少位可,不用循环右移
	num = num >> indexOf1;

	return num & 1;
}

void singleNumber(int A[], int len, int* num1, int* num2) 
{
	if(A == NULL || len <=2 && A[0] == A[1])
	{
		*num1 = -1;
		*num2 = -1;
		return;
	}
	else if (len == 2 && A[0] != A[1])
	{
		*num1 = A[0];
		*num2 = A[1];
		return;
	}

	int resultExclusiveOR = 0;
	//1. 异或
	for(int i = 0; i < len; ++ i)
		resultExclusiveOR ^= A[i];
	//用unsigned int
	//2.异或结果最右边的1的位置,不同的数一定某位是1
	unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
	//3.以1的位置将数组进行分割,一半是1一半是0
	*num1 = *num2 =0;
	for(int i = 0; i < len; ++ i)
	{
		if(IsBit1(A[i], indexOf1))
			*num1 ^= A[i];
		else
			*num2 ^= A[i];
	}


}

//=====================================================
void Test(char* testName, int* A, int len, int expected1, int expected2)
{
	if(testName != NULL)
        printf("%s begins: \n", testName);
	
	for(int i = 0; i < len;++ i)
	{
		cout<<A[i];
	}
	cout<<endl;
	int result1;
	int result2;
	//都忘了用&,使用已有的变量,将值进行返还,传递地址即可
	singleNumber(A, len, &result1,&result2);
	//可是不对应
	if((result1 == expected1 && result2 == expected2 )||(expected2 == result1 && expected1 == result2))
		cout<<"Passed!"<<endl;
	else
		cout<<"Failed!"<<endl;
	cout<<"result1: "<<result1<<"\n"<<"result2: "<<result2<<endl;
	
}


void Test1()
{
	int A[2] = {1,2};
	Test("Test1", A, sizeof(A)/sizeof(int), 1,2);
}

int _tmain(int argc, _TCHAR* argv[])
{
	Test1();
	return 0;
}
3.
// Single NumberII.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

//数组中的数都出现3次除了1个数,时间复杂度O(N),空间复杂度O(1)情况下找到这个数

int singleNumber(int A[], int len)
{
	if(len <= 0)
		return len;

	int result = 0;

	for(int i = 0;i < 32; ++ i)
	{
		//index 左移表示 1的位置
		int count = 0, index = 1 << i ;

		for(int j = 0; j < len; ++ j)
		{
			//&结果是bool
			if(A[j] & index)
				++ count;
		}
//		cout<<count<<endl;
		int count3 = count % 3;
		if(count3)
			result |= index;//result |= count3<<i;不知道为什么后者比前者节约16ms
	}
	return result;
}
//==============================================================================================
void Test(string testName, int* A, int len, int expected)
{
	
	if(testName.size() > 0)
	{
		cout<<testName<<" begins: "<<endl;
	}


	for(int i = 0; i < len; ++ i)
	{
		cout<<A[i];
	}
	cout<<endl;

	int result = singleNumber(A, len);
	if(result == expected)
		cout<<"Passed!"<<endl;
	else
		cout<<"Failed"<<endl;

	cout<<"result: "<<result<<endl;
}

void Test1()
{
	int A[4] = {10,10,11,10};
	Test("Test1", A, 4, 3);
}


int _tmain(int argc, _TCHAR* argv[])
{
	Test1();
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值