题目:
在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。 例如: 数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,其他数字都出现2次,找出5。
法一:
位操作符计算法
^ 按位异或符号,对应的二进制数运算,相同位为0,不同位为1!
举个例子:-5 ^ 13= -10
#include<stdio.h>
int main()
{
int a = -5;
//1000 0000 0000 0000 0000 0000 0000 0101 原码
//1111 1111 1111 1111 1111 1111 1111 1010 反码
//1111 1111 1111 1111 1111 1111 1111 1011 补码
int b = 13;
//0000 0000 0000 0000 0000 0000 0000 1101 正数原码就是补码
int c = a ^ b;
//1111 1111 1111 1111 1111 1111 1111 0110 相同为0 不同为1
//1000 0000 0000 0000 0000 0000 0000 1010 补码 -(2+8)=-10
printf("%d", c);
return 0;
}
那么我们可以推出一个特性:a^a=0 a^0=a
由此可以解题如下:
思路:遍历数组,当0与数组元素异或时,result变成该元素,在遇到不同数时,先存下得数如
result=1^2, 当遇到相同数时,result=1^2^1=1^1^2=0^2=2。所以直到遇到最后一个数没有相同数配对时,即返回这个数,没有单独出现的数,就返回0。
#include <stdio.h>
int Number(int nums[], int size)
{
int result = 0;
for (int i = 0; i < size; i++)
{
result ^= nums[i];
}
return result;
}
int main() {
int nums[] = {1, 2, 3, 4, 5, 1, 2, 3, 4};
int size = sizeof(nums) / sizeof(nums[0]);
printf("%d\n", Number(nums, size));
return 0;
}
法二:
数学求和法:
思路:result = (sumAll - sumPair)
,其中 sumAll
是数组所有数字的和,sumPair
是所有成对出现的数字的和。
#include <stdio.h>
int main()
{
int nums[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4 };
int size = sizeof(nums) / sizeof(nums[0]);
// 计算所有数字的和
long long sumAll = 0;
for (int i = 0; i < size; i++)
{
sumAll += nums[i];
}
// 计算所有成对出现的数字的和
long long sumPair = 0;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (i != j && nums[i] == nums[j])
{
sumPair += nums[i];
}
}
}
// 计算只出现一次的数字
int Number = (int)(sumAll - sumPair);
printf("%d\n", Number);
return 0;
}
法三:
哈希表(源于网络):
#include <stdio.h>
#include <stdlib.h>
// 定义哈希表的节点
typedef struct {
int key;
int value;
} HashNode;
// 定义哈希表
typedef struct {
HashNode* nodes;
int size;
} HashTable;
// 创建哈希表
HashTable* createHashTable(int size) {
HashTable* table = (HashTable*)malloc(sizeof(HashTable));
table->size = size;
table->nodes = (HashNode*)malloc(sizeof(HashNode) * size);
for (int i = 0; i < size; i++) {
table->nodes[i].key = 0;
table->nodes[i].value = 0;
}
return table;
}
// 计算哈希值
int hashCode(int key, int size) {
return abs(key) % size;
}
// 插入元素到哈希表
void insert(HashTable* table, int key) {
int hash = hashCode(key, table->size);
while (table->nodes[hash].key != 0 && table->nodes[hash].key != key) {
hash = (hash + 1) % table->size;
}
if (table->nodes[hash].key == 0) {
table->nodes[hash].key = key;
}
table->nodes[hash].value++;
}
// 查找哈希表中计数为1的元素
int findSingle(HashTable* table) {
for (int i = 0; i < table->size; i++) {
if (table->nodes[i].key != 0 && table->nodes[i].value == 1) {
return table->nodes[i].key;
}
}
return -1; // 没有找到
}
int main() {
int nums[] = {1, 2, 3, 4, 5, 1, 2, 3, 4};
int size = sizeof(nums) / sizeof(nums[0]);
int tableSize = 1000; // 哈希表的初始大小
HashTable* table = createHashTable(tableSize);
for (int i = 0; i < size; i++) {
insert(table, nums[i]);
}
int singleNumber = findSingle(table);
printf("The single number is: %d\n", singleNumber);
free(table->nodes);
free(table);
return 0;
}
你还有什么别的写法吗?欢迎在评论区留言讨论!