字符串中的最后一个唯一字符
分析,类似的题目有 字符串中的第一个唯一字符
思路1: 如果字符的indexOf的值等于lastIndexOf相等,说明该字符出现一次
思路2:新建一个数组记录次数;
思路3:用HashMap 存储键值对,value等于1,说明仅仅出现一次。(应该使用LinkedHashMap,为什么,请往下看?)
故问题相当于原问题的类似的问题。
解法一:用到字符串中某字符的indexOf的值等于lastIndexOf
将字符串翻转,字符串长度为len, 如果字符的indexOf的值等于lastIndexOf相等,令为i;
则字符串中的最后一个唯一字符的索引为 len-1-i;
代码如下:
public class LastOnly {
public static void main(String[] args) {
String str="asdad";
StringBuffer s = new StringBuffer(str); //String转换为StringBuffer
String strTemp=s.reverse().toString();//StringBuffer翻转后转换为String
LastOnly lastOnly=new LastOnly();
System.out.println(lastOnly.findOnly(strTemp));
}
public int findOnly(String str){
int len=str.length();
for(int i=0;i<len;i++){
if(str.lastIndexOf(str.charAt(i))==str.indexOf(str.charAt(i))){
return len-i-1;
}
}
return -1;
}
}
需要注意的是,要用到StringBuffer类 的reverse方法,而且反转后的字符为StringBuffer 类,需要还原成String类。
String str="asdad";StringBuffer s = new StringBuffer(str); //String转换为
StringBufferString strTemp=s.reverse().toString();//StringBuffer翻转后转换为String
解法二、:若要求时间复杂度,那么空间换时间,用一个数组存放每个字符出现的次数
nums[s.charAt(i)]++;//nums[value]存储的是字符出现的次数,value 为字符s.charAt(i)
字符串长度为len,故遍历数组nums时候,只需要遍历前len个元素即可
为了得到最后一个唯一字符,可以逆序遍历
public class LastOnly {
public static void main(String[] args) {
String str="asdad12";
int index=firstUniqChar(str);
System.out.println(index);//打印索引
char ch=str.charAt(index);//索引对应在字符串中的字符
System.out.println(ch);
}
//得到字符串的索引
public static int firstUniqChar(String str) {
int[] nums = new int[256];//建一个比字符串大的数组,用来存储字符出现的次数
int index=-1;//初始化索引
// Arrays.fill(nums,0);//初始化数组nums为0,非必须,会自动初始化
for(int i=0;i<str.length();i++){
nums[s.charAt(i)]++;//nums[value]存储的是字符出现的次数,value 为字符s.charAt(i)
}
for(int j=str.length()-1;j>=0;j--){//从后往前遍历,只需要遍历nums数组的
if(nums[s.charAt(j)]==1){
index=j;
break;//找到一个就跳出循环
}
}
return index;
}
}
解法三、:若不要求时间复杂度,可以建一个数组flag标记字符是否重复出现,若重复出现,该索引位标记为1
public int firstUniqChar(String s) {//时间复杂度o(n^2)
char[] c = s.toCharArray();
int[] flag = new int[c.length];//数组flag标记字符是否重复出现
int index = -1;
for(int i = 0 ; i < c.length; i++){
for(int j = i+1; j < c.length; j++){
if(c[i] == c[j]){
flag[i] = 1;
flag[j] = 1;
}
}
}
for(int i = flag.length-1 ;i >=0 ; i--){
if(flag[i] == 0){//flag位为0,表示未重复出现
index = i;
return index;
}
}
return index;
}
注 :
解法二、三参考字符串中的第一个唯一字符
解法四、:若不要求时间复杂度,可以建一个数组flag标记字符是否重复出现,若重复出现,该索引位标记为1
利用LinkedHashMap<Character,Integer> ,用value记录出现的次数。
Linked内部含有一个private transient Entry header;来记录元素插入的顺序或者是元素被访问的顺序
private static int firstUniqChar(String str) {
LinkedHashMap<Character,Integer> map=new LinkedHashMap<>();
int count=1;
for(int i=0;i<str.length();i++){
char c=str.charAt(i);
if(map.containsKey(c)){
count++;
map.put(c,count);
}else {
map.put(c,1);
}
}
for(int j=str.length()-1;j>=0;j--){
if(map.get(str.charAt(j))==1){
return j;
}
}
return -1;
}
注意:
- HashMap里面存放的键值对是没有被记录插入顺序的,故使用LinkedHashMap;
- TreeMap中的元素默认按照keys的自然排序排列。(对Integer来说,其自然排序就是数字的升序;对String来说,其自然排序就是按照字母表排序)