《剑指offer》——第一个只出现一次的字符位置

60 篇文章 3 订阅

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

T:

题目描述
在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符的位置。若为空串,返回-1。位置索引从0开始.

这道题目,和以下问题的解决思路类似:

问题:

给定一个字符串,该字符串都是由阿拉伯数字0~9组成,该字符串可能很长(几万,甚至更长),问如何更快的找出所有只出现过一次的数字?

解法相同,而设定场景不同,这就是需要融会贯通的地方。

  • 比较笨的一种解法,那就是用一个两层循环来做,看看当前位置的元素是否在后面也出现过。该解法的时间复杂度为 O ( n 2 ) O(n^2) O(n2),当 n n n很大的时候,那是相当的不能忍啊。。。

  • 还一种相对容易一些的方法,就是先遍历一遍,统计各个元素出现的次数,再在统计数据中找出数值为1的元素。

那么问题的关键就是在这个统计结构的设计了,如何设计?也许用一个二维数组,那么,如果元素不是阿拉伯数字,而是字母怎么办?这是相对麻烦的一种,幸好java都已经做了封装,我们可以用hashMap,或者hashSet来解决。

如果用c语言来实现,又该怎么破?没有封装好的哈希来调用,只能寻求其他方法。如果是阿拉伯数字,那么统计结构就可以设计成为一个长度为10的一维整型数组,字符串中出现的阿拉伯数字就可用来代表其在整型数组中的下标,问题迎刃而解,省时省力省空间。如果不是阿拉伯数字,而是字母,那就设定一个长度为26的整型一维数组。

先给出一个hashMap版本的:

code:

	import java.util.HashMap;
	
	/**
	 * T: 第一个只出现一次的字符位置
	 * 
	 * 题目描述 
	 * 在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符的位置。
	 * 若为空串,返回-1。位置索引从0开始.
	 * 
	 * date: 2015.11.17  21:16
	 * @author SSS
	 *
	 */
	public class Solution {
	    
	    /**
		 * 设立一个hashMap,将每个字母出现的次数进行统计。
		 * 若要找出第一个,就要对string从头开始再次遍历一遍,
		 * 找到其在hashMap中的value值为1,则返回其下标
		 * @param str
		 * @return
		 */
	    public int FirstNotRepeatingChar(String str) {
			
	        int index = -1;
			if (str == null || str == "") {
				return index;
			}
	        
	        HashMap<Character, Integer> statisticsMap = new HashMap<Character, Integer>();
	        
	        // 第一次遍历,统计每个字符出现的个数
	        for (int i = 0; i < str.length(); i++) {
				Character tempChar = str.charAt(i);
				if (statisticsMap.get(tempChar) == null) {
					statisticsMap.put(tempChar, 1);
				} else {
					int tempCount = statisticsMap.get(tempChar) + 1;
					statisticsMap.remove(tempChar);
					statisticsMap.put(tempChar, tempCount);
				}
			}
	        
	        // 第二次遍历,找出第一个只出现一次的字符的下标位置
	        for (int i = 0; i < str.length(); i++) {
				Character tempChar1 = str.charAt(i);
				if (statisticsMap.get(tempChar1) == 1) {
					index = i;
					break;
				}
			}
	        
			return index;
	    }
	}

再来第二种用数组统计的方式:

code:

	import java.util.HashMap;
	
	/**
	 * T: 第一个只出现一次的字符位置
	 * 
	 * 题目描述 
	 * 在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符的位置。
	 * 若为空串,返回-1。位置索引从0开始.
	 * 
	 * date: 2015.11.17  21:16
	 * @author SSS
	 *
	 */
	public class Solution {
	    
	    /**
		 * 另一种方式,用数组进行统计
		 * @param str
		 * @return
		 */
	    public int FirstNotRepeatingChar(String str) {
			int index = -1;
			if (str == null || str == "") {
				return index;
			}
			
			// 创建一个数组进行统计
			int []countArr = new int[26];
			// 初始化
			for (int i = 0; i < countArr.length; i++) {
				countArr[i] = 0;
			}
			
			// 本题目比较坑的地方,都是大写或者都是小写,先进行判断
			char tempChar = 'a';
			if (str.charAt(0) < tempChar) {
				tempChar = 'A';
			}
			// 进行统计
			for (int i = 0; i < str.length(); i++) {
				int tempIndex = str.charAt(i) - tempChar;
				int nums = countArr[tempIndex];
				countArr[tempIndex] = nums + 1;
			}
			
			// 在原字符串中找出该字符第一次出现的地方,记录其下标,中断for循环
			for (int i = 0; i < str.length(); i++) {
				if (countArr[str.charAt(i) - tempChar] == 1) {
					index = i;
					break;
				}
			}
			
			return index;
	    }
	}

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值