《剑指offer》 第50.1题 第一次只出现一次的字符。

第一个只出现一次的字符

https://www.nowcoder.com/practice/1c82e8cf713b4bbeb2a5b31cf5b0417c?tpId=13&tqId=11187&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

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


这个题目既然是找是否出现,并且由于每个字符需要返回第一次出现,因此需要记录次数,可以使用数组来完成出现次数的统计,而数组可以改进成TreeSet,因为实现了排序,或者是使用Map集合来统计次数。

写法1:

利用数组统计次数,这里可以建一个二维数组,但是,考虑到ASCII码中,字符对应某个数字,所以可以将字符对应的数字当做数组的角标,因此,可以只用一个一维数组即可。(也就是说,当你写一个arr[a],是会被认成arr[97],而Map不行)
注意:ASCII码一共是127个数,而小写z对应的是122,因此数组可以设置的最小角标数为122,所以最小必须创建一个123的数组,也可以128,这样所有的字符都能统计(PS:有人用256我是没想到为什么,大家知道的可以告诉我)。
  当然,也可以使用偏移量,毕竟A-Z对应的ASCII码为65-90,a-z对应的ASCII码值为97-122,用65到122这58个数也可以代替,所以使用偏移量需要做减法,然后创建大小58的数组即可。甚至可以用两次偏移,这样就只用大小52的数组了。但是为了少死一点脑细胞(我不想换算),我使用的是123个。不死脑细胞还占用空间较小的做法。
  字符对应的数字,将该数字作为索引,该索引处的元素用来统计出现的次数,遍历完后,再进行一次遍历,找到次数只为1的,并返回该数组中索引所表示的字符。就是这么个逻辑。

public class Solution {
    public int FirstNotRepeatingChar(String str) {
        if(str==null || str.length() == 0)
            return -1;
        int[] count = new int[123];
        //类似hash的方法来存储字符出现的次数
        for(int i=0; i < str.length();i++)
            count[str.charAt(i)]++;//进行统计
        //添加完字符后,再访问一遍数组,可以找到某个只出现一次的字符
        for(int i=0; i < str.length();i++){
            if(count[str.charAt(i)]==1)
                return i;
//这里不能遍历count数组,因为遍历count数组只能返回出现1次的字符,或者是某个字符出现的次数
//只有再拿着原字符串数组的角标遍历,才能将角标和出现次数对应上
        }
        return -1;
    }
}
//这个方法也可以改写成Set。只不过需要保证是有序的Set。

写法2:

使用Map集合来做,逻辑大致相同,只是添加的时候改动比较大。添加时,需要和Map的key比较,然后对Value进行维护。

import java.util.HashMap;
public class Solution {
    public int FirstNotRepeatingChar(String str) {
          if(str.length() == 0|| str == null){
            return -1;
        }
        HashMap<Character,Integer> map = new HashMap<>();
        for(int i = 0; i < str.length();i++){
//Map的逻辑是,如果Map不包含这个key,那就添加,注意添加的是字符,和出现的次数(添加时默认是1)
            if(!map.keySet().contains(str.charAt(i))){
                map.put(str.charAt(i),1);
            }else{//包含,则计数+1.map.get(str.charAt(i))就是拿到这个具体的次数即value
                map.put(str.charAt(i),map.get(str.charAt(i))+1);
            }
        }
        for(int i = 0; i < str.length();i++){//老规矩,只能对原字符串再次遍历
            if(map.get(str.charAt(i)) == 1){
                return i;
            }
        }
        return -1;//没找到就返回-1
    }
}
//keySet()  返回一个 SetMap视图中包含的键。

刷刷题

全部评论

相关推荐

真tmd的恶心,1.面试开始先说我讲简历讲得不好,要怎样讲怎样讲,先讲背景,再讲技术,然后再讲提升多少多少,一顿说教。2.接着讲项目,我先把背景讲完,开始讲重点,面试官立即打断说讲一下重点,无语。3.接着聊到了项目的对比学习的正样本采样,说我正样本采样是错的,我解释了十几分钟,还是说我错的,我在上一家实习用这个方法能work,并经过市场的检验,并且是顶会论文的复现,再怎么不对也不可能是错的。4.面试官,说都没说面试结束就退出会议,把面试者晾在会议里面,丝毫不尊重面试者难受的点:1.一开始是讲得不好是欣然接受的,毕竟是学习。2.我按照面试官的要求,先讲背景,再讲技术。当我讲完背景再讲技术的时候(甚至已经开始蹦出了几个技术名词),凭什么打断我说讲重点,是不能听出人家重点开始了?这也能理解,每个人都有犯错,我也没放心上。3.我自己做过的项目,我了解得肯定比他多,他这样贬低我做过的项目,说我的工作是错误的,作为一个技术人员,我是完全不能接受的,因此我就和他解释,但无论怎么解释都说我错。凭什么,作为面试官自己不了解相关技术,别人用这个方式work,凭什么还认为这个方法是错的,不接受面试者的解释。4.这个无可厚非,作为面试官,不打招呼就退出会议,把面试者晾着,本身就是有问题。综上所述,我现在不觉得第一第二点也是我的问题,面试官有很大的问题,就是专门恶心人的,总结面试官说教,不尊重面试者,打击面试者,不接受好的面试者,技术一般的守旧固执分子。有这种人部门有这种人怎么发展啊。最后去查了一下,岗位关闭了。也有可能是招到人了来恶心人的,但是也很cs
牛客20646354...:招黑奴啊,算法工程师一天200?
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务