【Java】面试题50:第一个只出现一次的字符

题目:

在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出’b’。

第一思路:借助于数组来做。

开辟一个长度为26的数组,用来存放字符串中每个字符出现的次数。这样第一次扫描去统计这个字符串中字符出现的次数,第二次去统计第一个出现结果为1的次数,并输出对应的字符。

package jianZhiOffer;

import java.util.HashMap;
import java.util.Map;

/*
 * 面试题50:第一个只出现一次的字符
 * 题目一:字符串中第一个只出现一次的字符
 * 在字符串中找出第一次只出现一次的字符。如输入abccdeff,则输出b
 */
public class Demo50 {

	public static void main(String[] args) {
		System.out.println(findFirstNoRepeatChar1("abaccdef"));
		System.out.println(findFirstNoRepeatChar2("abaccdef"));
	}
	
	//使用数组来进行
	public static char findFirstNoRepeatChar1(String str) {
		if(str==null || str.trim().length()==0)  //去掉字符串两端多余的空格
			return '0';
		int[] counts = new int[26];
		str = str.toLowerCase(); //防止出现大小写混乱的情况
		int len = str.length();
		for(int i=0;i<len;i++)
			counts[str.charAt(i)-'a']++;
		
		for(int i=0;i<len;i++) {
			if(counts[str.charAt(i)-'a']==1)
				return str.charAt(i);
		}
		return '0';
	}
}

**小结:**上面开辟的一个数组,其实就是为了让a~z对应。故演化出来的第二种做法就是利用带有<k,v>键值对的形式来解决问题。

第二思路:借助于HashMap来做。

借助于HashMap天然的集合优势,<k,v>键值对的形式,k存储字符,v存储出现的次数。故借此来找到第一个只出现一次的字符。

代码实现:

	//使用HashMap来实现
	public static char findFirstNoRepeatChar2(String str) {
		if(str == null || str.trim().length()==0){
			return '0';
		}
		Map<Character, Integer> map = new HashMap<Character, Integer>();
		str = str.toLowerCase(); //防止出现大小写混乱
		int len = str.length();
		int count = 0;
		for(int i = 0; i < len; i++){
			if(map.containsKey(str.charAt(i))){
				count = map.get(str.charAt(i));
				map.put(str.charAt(i), ++count);
			}else{
				map.put(str.charAt(i), 1);
			}
		}
		for(int i = 0; i < len; i++){
			if(map.get(str.charAt(i)) == 1){
				return str.charAt(i);
			}
		}
		return '0';
	}

小结:条条大路通罗马

相关题目一:

定义一个函数,输入两个字符串,从第一个字符串中删除在第二个字符串中出现过的所有字符。例如从第一个字符串“We are students.”中删除在第二个字符串"aeiou"中出现过的字符串得到的结果是"W r Stdnts."。

思路:

我们可以创建一个用数组实现的简单哈希表来存储第二个字符串。这样我们从头到尾扫描第一个字符串的每一个字符时,用O(1)时间就能判断出该字符是不是在第二个字符中。如果第一个字符串的长度是n,那么总的时间复杂度是O(n)。

相关题目二:

定义一个函数,删除字符串中所有重复出现的字符。例如输入"google",删除重复的字符串之后的结果是"gole"。

思路:

我们可以创建一个用布尔型数组实现的简单的哈希表。数组中的元素的意义是其下表看作ASCII码对应的字母在字符串中是否已经出现。我们先把数组中所有的元素都设为false。以google为例,当扫描到第一个g时,g的ASCII码是103,那么我们把数组下标为103的元素设为true,就知道g在前面已经出现了。即我们用O(1)时间就能判断出每个字符是否在前面已经出现过。如果是字符串的长度是n,那么总的时间复杂度是O(n)。

相关题目三:

在英语中,如果两个单词中出现的字母相同,并且每个字母出现的次数也相同,那么这两个单词互为变位词(Anagram)。例如silent与listen、evil与live等互为变位词。完成一个函数,判断输入的两个字符串是不是互为变位词。

思路:

我们可以创建一个用数组实现的简单哈希表,用来统计字符串中每个字符出现的次数。当扫描到第一个字符串中的每个字符时,为哈希表对应的项的值增加1。接下来扫面第二个字符串,扫描到每个字符串时,为哈西边对应的项的值减去1。如果扫描完第二个字符串后,哈希表所有的值都是0,那么这两个字符串就互为变位词。

题目二:字符流中第一个只出现一次的字符

请实现一个函数,用来找出字符流中第一个出现的一次的字符。
例如,当从字符流中只读出前两个字符“go”时,第一个只出现一次的字符是“g”;当从该字符流中读出前6个,字符“google”时,第一个只出现一次字符是“l”。

用模拟哈希表的数组来实现:

public class Demo5001 {
	//数组存储每个字符出现的次数
	static char[] cn = new char[256];
	static StringBuffer sb = new StringBuffer();
	
	public static void Insert(char ch) {  //每次输入的字符
		cn[ch]++;
		sb.append(ch+" ");
	}
	
	//返回数据流中第一次只出现一次的字符
	public static char FirstAppearingOnce() {
		char[] t = sb.toString().toCharArray();  //sb是StringBuffer
		for(int i=0;i<t.length;i++) {
			if(cn[t[i]]==1)
				return t[i];
		}
		return '#';
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_38361153/article/details/88941710