剑指offer-例题第一次只出现一次的字符

    科技2025-12-24  18

    题目描述:

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

    我的解法:

    import java.util.*; public class Solution { public int FirstNotRepeatingChar(String str) { if(str==null||str.length()==0) return -1; ArrayList<ListNode> result=new ArrayList<ListNode>(); for(int i=0;i<str.length();i++) { int j; for(j=0;j<result.size();j++) { if(result.get(j).ch==str.charAt(i)) { result.get(j).num++; break;//这里是个坑,一定要break } } if(j==result.size()) { ListNode k=new ListNode(str.charAt(i),1,i); result.add(k); } } for(int i=0;i<result.size();i++) { if(result.get(i).num==1) return result.get(i).index; } return -1; } } class ListNode{ char ch; int num; int index; public ListNode(char ch,int num,int index){ this.ch=ch; this.num=num; this.index=index; } }

    要根据出现的先后顺序,就没办法将字符值转换为数组下标,那样就是按字符值大小排序了,为解决这一问题,方法如下:

    public class Solution { public int FirstNotRepeatingChar(String str) { if(str==null||str.length()==0) return -1; int[] result=new int[100]; int[] index=new int[100]; for(int i=0;i<str.length();i++) { if(result[str.charAt(i)-'A']==0) index[str.charAt(i)-'A']=i; result[str.charAt(i)-'A']++; } for(int i=0;i<str.length();i++) { if(result[str.charAt(i)-'A']==1)//这里是个坑,这样才能保证是按出现顺序排列的而不是按字符大小顺序排列的 return index[str.charAt(i)-'A']; } return -1; } }

    我的解法存在的问题:

    1、时间复杂度为O(n*n)    还有提升的空间

    2、为保证按出现顺序而不是按字符大小顺序,第二次应该在str上遍历而不是result上,而且这样还可以直接得到位置值

    3、字符转换为数组下标,直接使用result[char]   相当于改变了数组中下标为  char对应ASCII值   的元素值

         这样也不需要在每次判断时都遍历一遍数组,节省时间

    4、题目中只涉及到字母,一个字节就已足够,有种情况,因此数组大小设为256,如果任意字符出现的话,char是2字节的数据类型

    5、可以直接得到位置值,不需要通过另一个数组存储第一次出现的位置

    正确解法:

    时间复杂度:O(n)

    空间复杂度:O(1)

    public class Solution { public int FirstNotRepeatingChar(String str) { if(str==null||str.length()==0) return -1; int[] result=new int[256]; for(int i=0;i<str.length();i++) { result[str.charAt(i)]++; } for(int i=0;i<str.length();i++) { if(result[str.charAt(i)]==1) return i; } return -1; } }

    每个字符根据其ASCII码值作为数组下标

     

    相关题目:(哈希表的应用)

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

    时间复杂度:O(n)

    空间复杂度:O(1)

    public String FirstNotRepeatingChar(String str1,String str2) { if(str1==null||str1.length()==0) return str1; if(str2==null||str2.length()==0) return str1; int[] num=new int[65536]; for(int i=0;i<str2.length();i++) num[str2.charAt(i)]++; StringBuilder s=new StringBuilder(str1); for(int i=0;i<s.length();i++) { if(num[s.charAt(i)]!=0) { s.deleteCharAt(i); i--;//这是一个坑 } } return s.toString(); }

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

    时间复杂度:O(n)

    空间复杂度:O(1)

    public String FirstNotRepeatingChar(String str1) { if(str1==null|str1.length()==0) return str1; StringBuilder s=new StringBuilder(); int result[]=new int[65536]; for(int i=0;i<str1.length();i++) { if(result[str1.charAt(i)]==0) { result[str1.charAt(i)]++; s.append(str1.charAt(i)); } } return s.toString(); }

    下面是错误解法 :

    s发生变化不利于此问题解决

    public String FirstNotRepeatingChar(String str1) { if(str1==null|str1.length()==0) return str1; StringBuilder s=new StringBuilder(str1); int result[][]=new int[65536][2]; for(int i=0;i<str1.length();i++) { if(result[str1.charAt(i)][0]==0) { result[str1.charAt(i)][1]=i; } result[str1.charAt(i)][0]++; } //这是一个坑,以下要全部在s上进行 for(int i=0;i<s.length();i++) { if(result[s.charAt(i)][0]>1) { if(i!=result[s.charAt(i)][1]) { s.deleteCharAt(i); i--;//这是一个坑,删除了长度发生变化,i也要跟着变化 但是i都已经发生变化了就不能判断它是否是第一次出现了 } } } return s.toString(); }

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

    时间复杂度:O(n)

    空间复杂度:O(1)

    public static boolean FirstNotRepeatingChar(String str1,String str2) { int[] s1=new int[65537]; int[] s2=new int[65537]; for(int i=0;i<str1.length();i++) s1[str1.charAt(i)]++; for(int i=0;i<str2.length();i++) s2[str2.charAt(i)]++; for(int i=0;i<str1.length();i++) { if(s1[str1.charAt(i)]!=s2[str1.charAt(i)]) return false; } for(int i=0;i<str2.length();i++) { if(s2[str2.charAt(i)]!=s1[str2.charAt(i)]) return false; } return true; }

     

    Processed: 0.021, SQL: 9