剑指offer:第一个只出现一次的字符

题意描述

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)

解题思路

一、思路一

  • 遍历字符串,使用HashMap记录每个字符出现的次数。

  • 再次遍历字符串,从map中查找每个字符出现的次数,返回第一个value == 1的索引。

    import java.util.*;
    public class Solution {
        public int FirstNotRepeatingChar(String str) {
              if(str == null || str.length() == 0) return -1;
           HashMap<Character,Integer> map = new HashMap<>();
            for(int i=0;i<str.length();i++){
                if (map.containsKey(str.charAt(i)))	//map中存在字符,value++
                    map.put(str.charAt(i), map.get(str.charAt(i)) + 1);
                else
                    map.put(str.charAt(i), 1);	//初次出现,将字符加入map
            }
            for(int i=0;i<str.length();i++){
                if(map.get(str.charAt(i)) == 1){ 
                    return i;	//返回索引
                }
            }
            return 0;
        }
    }

每次添加之前都要在map中查询字符是否存在,会消耗大量时间,能否进行优化呢?

因为字符串中只存在字母,所以可以使用一个char类型的数组,对应从A-z的每个字符,如果出现字符,直接对相应的索引+1。这样可以省去查询map的开销。

    public class Solution {
        public int FirstNotRepeatingChar(String str) {
            char[] chars = str.toCharArray();
            //使用一个‘z’+1大小的数组
            //65 - 90 表示 A - Z
            //97 - 122 表示 a - z
            char[] arr = new char['z' + 1];	
            for (char c : chars) {
                arr[c]++;	//每出现依次,对应的索引值+1
            }
            for (int i = 0; i < chars.length; i++) {
                if (arr[chars[i]] == 1) {	//查找第一个数组值为1的
                    return i;
                }
            }
            return -1;
        }
    }
posted @ 2020-05-06 22:53  灵图  阅读(123)  评论(0)    收藏  举报