题记:
给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。
示例 1:
输入: s = “leetcode”
输出: 0
示例 2:
输入: s = “loveleetcode”
输出: 2
示例 3:
输入: s = “aabb”
输出: -1
提示:
1 <= s.length <= 105
s 只包含小写字母
题目来源:
作者:LeetCode
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xn5z8r/
来源:力扣(LeetCode)
自己想出的方法:
一:利用集合处理
class Solution {
/**
* @param String $s
* @return Integer
*/
function firstUniqChar($s) {
//先拆分为数组
$s_arr = str_split($s);
//过滤掉重复项
$s_union_arr = array_unique($s_arr);
//重复的键值对
$repeat_arr = array_diff_key($s_arr,$s_union_arr);
//对重复的键值对去重
$no_repeat_arr = array_unique($repeat_arr);
//去掉重复项后的唯一字符键值对
$unionque_arr = array_diff($s_union_arr,$no_repeat_arr);
if(empty($unionque_arr)){
return -1;
}
//返回数组中当前单元的键名
$key_current = key($unionque_arr);
return $key_current;
}
}
$s = "loveleetcode";
$solution = new Solution();
$result = $solution->firstUniqChar($s);
print_r($result);
/**
输出结果为:2
*/
二:暴力双循环(效率最低)
class Solution {
/**
* @param String $s
* @return Integer
*/
function firstUniqChar($s) {
//暴力循环(效率低),出现超时现象
//先拆分为数组
$s_arr = str_split($s);
$length = count($s_arr);
$map = []; //重复元素数组初始化
for($i = 0; $i < $length; $i++){
for($j = $i + 1; $j < $length; $j++){
if($s_arr[$i] == $s_arr[$j]){
$map[$s_arr[$i]] = $s_arr[$i];
}
}
}
//原数组与重复元素数组取差集
$unique_array = array_diff($s_arr,$map);
if(!empty($unique_array)){
return key($unique_array);
}else{
return -1;
}
}
}
$s = "loveleetcode";
$solution = new Solution();
$result = $solution->firstUniqChar($s);
print_r($result);
/**
输出结果为:2
*/
官方解题方法:
一:两次遍历
第一遍先统计每个字符出现的次数,第二遍再次从前往后遍历字符串s中的每个字符,如果某个字符出现一次直接返回,原来比较简单,看下代码
public int firstUniqChar(String s) {
int count[] = new int[26];
char[] chars = s.toCharArray();
//先统计每个字符出现的次数
for (int i = 0; i < s.length(); i++)
count[chars[i] - 'a']++;
//然后在遍历字符串s中的字符,如果出现次数是1就直接返回
for (int i = 0; i < s.length(); i++)
if (count[chars[i] - 'a'] == 1)
return i;
return -1;
}
转换为PHP代码为:
function firstUniqChar($s) {
//拆分为数组
$s_arr = str_split($s);
$str_count = [];
//先统计各个字符出现的次数,字符为键,值为次数
foreach($s_arr as $key => $value){
if(!isset($str_count[$value])){
$str_count[$value] = 1;
}else{
$str_count[$value]++;
}
}
if(!empty($str_count)){
//在数组中搜索给定的值(1),如果成功则返回首个相应的键名
$key_char = array_search(1,$str_count);
if($key_char){
//再去原数组里搜索首次出现不重复的值,返回首个键名
$value_char = array_search($key_char,$s_arr);
return $value_char;
}
return -1;
}
return -1;
}
二:使用HashMap解决
public int firstUniqChar(String s) {
Map<Character, Integer> map = new HashMap();
char[] chars = s.toCharArray();
//先统计每个字符的数量
for (char ch : chars) {
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
//然后在遍历字符串s中的字符,如果出现次数是1就直接返回
for (int i = 0; i < s.length(); i++) {
if (map.get(chars[i]) == 1) {
return i;
}
}
return -1;
}
三:使用Java的api
一个从前查找,一个从后查找,如果下标相等,说明只出现了一次
public int firstUniqChar(String s) {
for (int i = 0; i < s.length(); i++)
if (s.indexOf(s.charAt(i)) == s.lastIndexOf(s.charAt(i)))
return i;
return -1;
}
官方推荐答案:
class Solution {
/**
* @param String $s
* @return Integer
*/
function firstUniqChar($s) {
$char = count_chars($s,1); //count_chars — 返回字符串所用字符的信息
$indexarr = [];
foreach($char as $k => $v){ //k为字符字节值,v为次数
if($v == 1){
$chr = chr($k); //chr — 从数字生成单字节字符串
$index = strpos($s,$chr); //strpos() - 查找字符串首次出现的位置
$indexarr[] = $index;
}
}
if(count($indexarr) > 0) return min($indexarr); //min — 找出最小值
return -1;
}
}
$s = "loveleetcode";
$solution = new Solution();
$result = $solution->firstUniqChar($s);
print_r($result);
/**
输出结果为:2
*/
官方解题来源:
作者:数据结构和算法
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xn5z8r/?discussion=6TyKA7
来源:力扣(LeetCode)
其他方法(PHP):
function firstUniqChar($s) {
$chr = null;
for($i = 0; $i < strlen($s); $i++){
//substr_count — 计算字串出现的次数
//substr — 返回字符串的子串
if(substr_count($s, substr($s, $i, 1)) == 1){
return $i;
//return substr($s, $i, 1);
}
}
return -1;
}