Home > leetcode > First Unique Character in a String (Ruby)

First Unique Character in a String (Ruby)


Today we solve a very popular 'kata' on Leetcode #387 First Unique Character in a String

Difficulty level: Easy

Related Topics: Hash Table, String

Disclaimer: You might have different results in Runtime and Memory Usage, it's okay 🤣 it how it works.


Description:

Given a string, find the first non-repeating character in it and return its index. If it doesn't exist, return -1.

Examples:

s = "leetcode"
return 0.

s = "loveleetcode"
return 2.

Note:

 You may assume the string contains only lowercase English letters.

And your playground looks like this:

def first_uniq_char(s)
end

Solution 1

We know that we can get an empty string. Let's first check it, then start to search for unique characters.

If string has no length, that means it's empty and we return -1

    if(!s.empty?) then

    ...

    else
        return -1
    end

Then we declare an empty hash

hash_table = {}

And count how many times a character appears.

If we have a character in the dictionary we increase its value by one, if not the value will be equal to one.

s.split("").each do |char|
    if hash_table.has_key?(char) then
    hash_table[char] = hash_table[char] + 1
    else
    hash_table[char] = 1
    end
end

Then we go thru the dictionary and return the first character which has value 1

s.split("").each_with_index do |char, i|
    if hash_table[char] == 1 then
        return i
    end
end

Full solution

def first_uniq_char(s)
  if(!s.empty?) then
    hash_table = {}

    s.split("").each do |char|
      if hash_table.has_key?(char) then
        hash_table[char] = hash_table[char] + 1
      else
        hash_table[char] = 1
      end
    end

    s.split("").each_with_index do |char, i|
        if hash_table[char] == 1 then
            return i
        end
    end

    return -1

  else
    return -1
  end
end

Let's submit it and see the result.

Runtime: 1060 ms, faster than 5.49% of Ruby online submissions for First Unique Character in a String.
Memory Usage: 15.9 MB, less than 10.00% of Ruby online submissions for First Unique Character in a String.

I don't really like this result 🥵 let's improve it!


Solution 1.1

We split string two times, let's move it a variable

slided_string = s.split("")

Full solution

def first_uniq_char(s)
  if(!s.empty?) then
    hash_table = {}
    slided_string = s.split("")

    slided_string.each do |char|
      if hash_table.has_key?(char) then
        hash_table[char] = hash_table[char] + 1
      else
        hash_table[char] = 1
      end
    end

    slided_string.each_with_index do |char, i|
        if hash_table[char] == 1 then
            return i
        end
    end

    return -1

  else
    return -1
  end

end

Let's submit it and see the result.

Runtime: 612 ms, faster than 8.79% of Ruby online submissions for First Unique Character in a String.
Memory Usage: 14.4 MB, less than 10.00% of Ruby online submissions for First Unique Character in a String.

This is better but still pretty bad.


Solution 1.2

I don't like that we have 3 returns and I guess we can remove empty string checking.

def first_uniq_char(s)

    hash_table = {}
    slided_string = s.split("")

    slided_string.each do |char|
      if hash_table.has_key?(char) then
        hash_table[char] = hash_table[char] + 1
      else
        hash_table[char] = 1
      end
    end

    slided_string.each_with_index do |char, i|
        if hash_table[char] == 1 then
            return i
        end
    end

    return -1

end

Let's submit it and see the result.

Runtime: 476 ms, faster than 21.98% of Ruby online submissions for First Unique Character in a String.
Memory Usage: 14.4 MB, less than 10.00% of Ruby online submissions for First Unique Character in a String.

So far this is my best result.

© 2021, Andrew Losseff