在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
要根据出现的先后顺序,就没办法将字符值转换为数组下标,那样就是按字符值大小排序了,为解决这一问题,方法如下:
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; }
