Given a string, find the first non-repeating character in it and return it‘s index. If it doesn‘t exist, return -1.
Examples:
s = "leetcode" return 0. s = "loveleetcode", return 2.
Note: You may assume the string contain only lowercase letters.
1 public class Solution { 2 public int FirstUniqChar(string s) { 3 var dict = new Dictionary<char, IList<int>>(); 4
// Map 5 for (int i = 0; i < s.Length; i++) 6 { 7 if (!dict.ContainsKey(s[i])) 8 { 9 dict[s[i]] = new List<int>(); 10 } 11 12 dict[s[i]].Add(i); 13 } 14
// Reduce 15 bool found = false; 16 var result = Int32.MaxValue; 17 foreach (var pair in dict) 18 { 19 if (pair.Value.Count == 1 && pair.Value[0] < result) 20 { 21 found = true; 22 result = pair.Value[0]; 23 } 24 } 25 26 return found ? result : -1; 27 } 28 } 29 30 // traverse the string twice, if the string is super long, performance wouldn‘t be very good 31 public class Solution1 { 32 public int FirstUniqChar(string s) { 33 var dict = new Dictionary<char, int>(); 34 35 foreach (var c in s) 36 { 37 if (!dict.ContainsKey(c)) 38 { 39 dict[c] = 1; 40 } 41 else 42 { 43 dict[c]++; 44 } 45 } 46 47 for (int i = 0; i < s.Length; i++) 48 { 49 if (dict[s[i]] == 1) 50 { 51 return i; 52 } 53 } 54 55 return -1; 56 } 57 }
Follow up: what if the string is exetremly long and you have to process it with multi machines?
Answer: I think this is a typical Map-Reduce problem where you can split the string to multi batches, the Map function will be similar as my solution 1, one difference is we should pass the start index of each patch in the original string to the Map function, then the Reduce function will aggregate the Map results and generate the final result.