剑指offer java版 test34— 找出第一个只出现一次的字符(hash初尝试)

  1. 前言:

java里new一个新数组,eg:int[] a=new int[30],初始值是默认全为0的。

这题用了hash思想,原来也不一定用到hash这个关键字

hashmap的底层是散列表,数据的存储与插入顺序无关,比如依次put的是q,w,e字符,遍历的时候可能是e,w,q顺序的。而linkedhashmap底层有一个双链表来维护其存储顺序,遍历的时候是按照插入顺序来遍历的

  1. 题目:

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

  1. 思路:

3.1 一直用数组比较多,所以这次还是用数组做出来了,但是答案也不如大佬们用hash表来做的,先说一下自己的思路,毕竟能做出来也是开心的:两个数组,一个从来存储单次出现的字符,一个用来存储多次(大于1次)的字符。把各字符依次与这两个数组比较。

3.2 hash思想的思路:(两种,一种用到hash来存储数据,一种用数组来存储)(**完全可以直接建个256长度的数组,因为acsii码总共就256个,这样就不用下标-65了。**参考test54也行)
用hash和ASCII码来解决,也是学到了,建个数组,下标0-58,值均为0,依次代表a-z,A-Z(A-Z得ASCII值是65-90,a-z得ASCII值是97-122.122-65+1=58,中间断档,有几个用不,无所谓)。然后我遍历字符串,比如输入A,我们就求得它的ascii—65,为0,这样数组下标为0的地方的值就+1。即,建个数组,数组的下表代表各字母,值代表出现的次数,就形成了键值对。

3.3 用hashmap来存储键值对信息,键即字母,值即次数。存储完了后,找值为1的,但是只能通过str遍历来找,不能自己遍历hashmap来找第一个值为1的,然后输出下标。因为hashmap不一定按顺序存储的。Linkedhashmap是按顺序存储的,所以选择不同的map,有不同的遍历方法。

  1. 代码:
    我的:
package cn.test34;

import java.util.ArrayList;
import java.util.List;

public class test {
    public static void main(String[] args){
    String str="abcdefgbbcddeas";
    Solution solution=new Solution();
    System.out.println(solution.FirstNotRepeatingChar(str));
    }
}


class Solution {
    public int FirstNotRepeatingChar(String str) {
        if(str.length()==0) return -1;//字符串为空,返回-1;

        List<Character> repeat=new ArrayList<Character>();//记录已经出现了2次及以上的字符
        List<Character> simple=new ArrayList<Character>();//记录只出现了一次的字符

        for(int i=0;i<str.length();i++){
            Character a=str.charAt(i);//记录当前字符

            //如果repeat里包含字符a,则结束循环,如果repeat里没有,且simple里有,则说明这个字符第二次出现,从
            //simple里删除它,并加入到repeat里。如果repeat和simple里都没有,则加入simple里。
            if(repeat.contains(a)){
                continue;
            }else if(simple.contains(a)){
                simple.remove(a);
                repeat.add(a);

            }else{
                simple.add(a);
            }
        }

        //返回simple数组第一个字符在str里的位置
        if(simple.size()==0) return -1;
        else return (str.indexOf(simple.get(0)));



    }
}

大佬们用hash的代码,自己也学者写了下,得熟悉用hash,最近做题发现用得也多,也很实用。

class Solution1 {
    public int FirstNotRepeatingChar(String str) {
        //因为区分大小写,A-Z得ASCII值是65-90,a-z得ASCII值是97-122.122-65+1=58
        //数组从前到后(除去中间几个)依次代表A-Z,a-z的值
        int[] words=new int[58];
        //循环遍历
        for(int i=0;i<str.length();i++){
            words[(int)str.charAt(i)-65]+=1;
        }

        //看各字母,谁的计数为1
        for(int i=0;i<str.length();i++){
            if(words[(int)str.charAt(i)-65]==1) return i;
        }
        return -1;

    }
}

用到hash结构的代码:

class Solution2 {
    public int FirstNotRepeatingChar(String str) {
        Map<Character,Integer> map =new HashMap<Character,Integer>();
        for(int i=0;i<str.length();i++){
            if(map.containsKey(str.charAt(i))){
                int time=map.get(str.charAt(i));//看看当前字符的值,即次数
                map.put(str.charAt(i),++time);//新的值会覆盖旧的值

            }else{
                map.put(str.charAt(i),1);
            }
        }

        for(int i=0;i<str.length();i++){
            if(map.get(str.charAt(i))==1){
                return i;
            }
        }
        return -1;

        //再查找

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值