第一个只出现一次的字符

这个题目可以看做是一类题型。就是从一个数组中找出不重复的第一个或是全部的数,或是在一个字符串当中找。另外还可以做成大数据的情况,例如,给你一亿或是几亿个数,32位的int类型,让你找出所有的不重复的数。

基本思路有几个,第一个推荐的方法是位图BitMap,哈希表Hashtable。第二个方法是异或法,此方法在剑指offer中有介绍。下面详细来分析如何解决此类问题。

HashTable法

对于查找第一个只出现一次的字符,我们可以用一个数据容器来存放每一个字符出现的次数,在这个容器中,可以根据字符来查找它出现的次数,也就是说把字符映射成一个数字。

我们可以定义一个哈希表,他的键值(Key)是字符,而值(Value)是该字符出现的次数。同时需要扫描字符数组两次。第一次用于统计所有字符出现的次数。第二遍时,可以输出第一个只出现一次的字符,也可以设置输出所有只出现一次的字符。

下面关键一步是定义Hashtable。因为是字符,所以只有256种情况,不考虑中文字符。那么我们就建一个256大小的数组,用字符的ASCII码值作为下标,即该字符的ASCII码值就是其在数组中的位置。好的,代码如下:

char FindNotRepeatedChar(char *string)
{
	if (string == NULL)
		return '\0';
	const int Tablesize = 256;
	unsigned int HashTable[Tablesize] = {0};

	char* pHash = string;
	while ((*pHash) != '\0')
	{
		HashTable[*pHash]++;
		pHash++;
	}

	pHash = string;
	while (*pHash != '\0')
	{
		if (HashTable[*pHash] == 1)
<span style="white-space:pre">		</span>{<span style="white-space:pre">	</span>
			return *pHash;
<span style="white-space:pre">			</span>break;<span style="white-space:pre">	</span>
<span style="white-space:pre">		</span>}
		pHash++;
	}
	return '\0';
}


好下面来讨论下大数据量时,用BitMap来压缩统计。

BitMap

代码参考:

# include<stdio.h>    
# include<string.h>    
  
const int N = 26;    
int bit_map[N];    
  
void findNoRepeat(char *src)    
{    
    int pos;    
    char *str = src;    
    int i ,len = strlen(src);    
  
    //统计    
    for(i = 0 ; i < len ;i ++)    
        bit_map[str[i]-'a'] ++;    
  
    //从字符串开始遍历 其bit_map==1 那么就是结果    
    for(i = 0 ; i < len ; i ++)    
    {    
        if(bit_map[str[i]-'a'] == 1)    
        {    
            printf("%c",str[i]);    
            return ;    
        }    
    }    
}    
  
int main()    
{       
    char *src = "abaccdeff";    
    findNoRepeat(src);    
    printf("\n");    
    return 0;    
}  


题目可以是: 在2.5亿个整数中找出不重复的整数,内存不足以容纳这2.5亿个整数。

    方案1:采用2-Bitmap(每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义)进行,共需内存2^32*2bit=1GB内存,还可以接受。然后扫描这2.5亿个整数,查看Bitmap中相对应位,如果是00变01,01变10,10保持不变。扫描遍历完事后,查看bitmap,把对应位是01的整数输出即可。

    方案2:也可采用上题类似的方法,进行划分小文件的方法。然后在小文件中找出不重复的整数,并排序。然后再进行归并,注意去除重复的元素。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值