Group Anagrams - Categorize Strings by Count - Leetcode 49

Group Anagrams - Categorize Strings by Count - Leetcode 49

NeetCode

3 года назад

423,440 Просмотров

Ссылки и html тэги не поддерживаются


Комментарии:

@HibiTeamQueso
@HibiTeamQueso - 13.12.2023 19:05

Dang, I almost got it myself but exceeded the time limit 🥲

Ответить
@dibehemoth401
@dibehemoth401 - 13.12.2023 02:46

What if we do not know about of what letters are our words. We can then use HashMaps for counting and as our keys, right?

Ответить
@sarvajnya_18
@sarvajnya_18 - 05.12.2023 19:36

O(m logn)
from collections import defaultdict, Counter
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
res = defaultdict(list)
for i in strs:
res[tuple(sorted(Counter(i).items()))].append(i)
return res.values()

Ответить
@aliquewilliams3080
@aliquewilliams3080 - 02.12.2023 00:35

There's no need to subtract the ascii value of each character from A's ascii value. Just use the characters ascii directly as the key in the hashmap, so change count = [0] * 256.

Ответить
@He_ze
@He_ze - 24.11.2023 01:41

I feel like this problem is easy to work out in your head than to actually implement... bruh
but after watching this video, the implementation is easier than it initially had it

Ответить
@user-pt7co4nn2h
@user-pt7co4nn2h - 21.11.2023 03:34

In c++ ,you can use an integer as keys. And use bits operation to represent the words contains what alphabet. No matter what sequence the alphabet comes in.

Ответить
@marioclavijo1283
@marioclavijo1283 - 02.11.2023 07:05

Great video!! just wondering, I see the point of the time complexity mn. However I keep wondering you will need a word of over 10^26 characters for mnlogn to become less efficient than (mn26)->mn. 10^26 is pretty much infinity already, I mean only for strings over 10^26 characters it would be better to do it this way. for instance, if n =10, nlogn =10 and n26=260, if n=10,000,000 nlogn = 70,000,000 and n26=260,000,000. I'm probably misunderstanding, could you please share some insight on this? Thank you!

Ответить
@calebemachado8929
@calebemachado8929 - 23.10.2023 03:55

Well, sorting the words and storing them as keys in the dict and the anagram in the values gave me better results both in runtime and memory. I'm not good with BigO yet, so I'm not sure what it is for mine solution:
Im a newbie with python too, so maybe there is a cleaner or shorter way to write what I did:
result = {}
for i, item in enumerate(strs):
anagram = ''.join(sorted(item))
if anagram in result:
anagram_list = result[anagram]
anagram_list.append(item)
result[anagram] = anagram_list
else:
data = []
data.append(item)
result[anagram] = data

resp = []
for item in result:
resp.append(result[item])

return resp

Ответить
@vaiterius
@vaiterius - 17.10.2023 06:55

Thank you! Never would have thought of making the keys the ASCII character count, that is pretty clever

Ответить
@josealvarezpulido
@josealvarezpulido - 15.10.2023 10:05

I was able to come up with a solution before looking it up :)
not optimal but I was glad I was able to solve it. Thanks in part to your videos.

def groupAnag(list):
result = {}
for item in list:
itemResult = []
for letter in item:
itemResult.append(letter)
itemResult.sort()
itemResult = ''.join(itemResult)
if itemResult in result:
result[itemResult].append(item)
else:
result[itemResult] = [item]
my_list = [i for i in result.values()]
return my_list

Ответить
@rahmansahinler1
@rahmansahinler1 - 30.09.2023 23:53

Maybe we can get rid of mapping strings with integer list and use sorted keys.
Something like below worked for me:

ans = defaultdict(list)
for str in strs:
sorted_str = sorted(str)
ans[tuple(sorted_str)].append(str)

return ans.values()

Ответить
@yrrep27
@yrrep27 - 28.09.2023 07:15

Set up a dictionary and output list.

Iterate thru the input strings.
For each input string, create a separate sorted string.

If the sorted string is a key in the dictionary,
append the input string to a list in the key's value

If the sorted string is not a key in the dictionary,
set up a new key value pair where the key is the sorted string,
and the value is a list holding just the input string.

Iterate thru the values of the the dictionary,
append them to the output list.

Return this output list.

Ответить
@AbhishekMishraiitkgp
@AbhishekMishraiitkgp - 18.09.2023 22:19

If you don't want to use defaultdict() from collections, you may do this:

def groupAnagrams(strs):
res = {}
for s in strs:
count = [0] * 26 # a .... z
for c in s:
count[ord(c) - ord("a")] += 1
key = tuple(count)
if key in res:
res[key].append(s)
else:
res[key] = [s]

return list(res.values())

Ответить
@aisteelmemesforaliving
@aisteelmemesforaliving - 17.09.2023 20:55

Why is the sorted version run at a lower runtime on leetcode eventhough this solution is better in theory. Leetcode runtimes are pretty weird.

Ответить
@ANUJKUMAR-wc9dz
@ANUJKUMAR-wc9dz - 14.09.2023 17:00

why we are use '#' there and what is its importance ?

Ответить
@kirillzlobin7135
@kirillzlobin7135 - 10.09.2023 20:05

Amazing... How come you can get to these ideas. It is simple, but it is hard to get to these solutions without hints :)

Ответить
@ankulsinghrajput8452
@ankulsinghrajput8452 - 07.09.2023 22:05

JAVA code
I really should learn python:
28 lines vs 8 lines
public static List<List<String>> groupAnagrams(String[] strs) {
Map<List<Integer>, List<String>> hm = new HashMap();

for(String s: strs) {
int count[] = new int[26];
for(Character c: s.toCharArray()) {
count[c-97]++;
}
List<Integer> alphabet_count = new ArrayList<Integer>();
for(int i: count){
alphabet_count.add(i);
}
if(!hm.containsKey(alphabet_count)){
List<String> result_map_value = new ArrayList<String>();
result_map_value.add(s);
hm.put(alphabet_count, result_map_value);
}
else {
List<String> result_map = hm.get(alphabet_count);
result_map.add(s);
hm.put(alphabet_count, result_map);
}
}
List<List<String>> final_result_list = new ArrayList<List<String>>();
for (Map.Entry<List<Integer>, List<String>> entry : hm.entrySet()) {
final_result_list.add(entry.getValue());
}
return final_result_list;
}

Ответить
@tsunami8892
@tsunami8892 - 31.08.2023 09:18

var groupAnagrams = function (strs) {
const anagramsMap = new Map();

for (let str of strs) {
const charsCount = new Array(26).fill(0);

for (let char of str) {
charsCount[char.charCodeAt(0) - 97]++; // "a".charCodeAt(0) = 97 in the Unicode
}

const hash = charsCount.toString();

anagramsMap.set(hash, (anagramsMap.get(hash) || []).concat(str)); // much shorter than if statements
}

return Array.from(anagramsMap.values());
};

Ответить
@saladuit
@saladuit - 25.08.2023 12:11

I have a question for the M * n* log(n) solutions. I also came up with that, but one has to return the unsorted strings. So I am assuming that you also made a deep copy of strs to not fiddle with the order of characters?

Ответить
@RemotHuman
@RemotHuman - 19.08.2023 06:06

I didn't pay attention to the 26 characters part at first. And my python code ran out of execution time on leetcode 😢

Ответить
@koddezign8227
@koddezign8227 - 11.08.2023 12:56

My solution in typescript:
function groupAnagrams(strs: string[]): string[][] {
const sortedMap = new Map();
for (let i = 0; i < strs.length; i++) {
// Sort each item
const key = strs[i].split("").sort().join("");
// Add items as keys in the map. If one exists already concat it so it is in the right form [..., ...]
sortedMap.set(key, (sortedMap.get(key) || []).concat(strs[i]));
}
return Array.from(sortedMap.values());
};

Ответить
@ebrahimemad5100
@ebrahimemad5100 - 10.08.2023 16:05

aswome

Ответить
@CarsMeetsBikes
@CarsMeetsBikes - 08.08.2023 22:03

I've found an even faster solution that doesn't require ascii math:

def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
dict = defaultdict(list)
for str in strs:
sortedstr = ''.join(sorted(str))
if sortedstr in dict:
dict[sortedstr].append(str)
else:
dict[sortedstr] = [str]
return dict.values()

it's quite similar but essentially it sorts each str in strs. Then, if sortedstr is in dict, append to dict[sortedstr], otherwise append [str] to dict. return dict.values()

hope this helps someone

Ответить
@hassansuhaib9087
@hassansuhaib9087 - 08.08.2023 21:13

I went with a different approach where I just check whether sorted(string) is in the dict, if not then just store an array against that sorted string in the dict

Ответить
@anandkrishnan72
@anandkrishnan72 - 05.08.2023 01:25

How does this work because I thought you cannot key a dictionary with a list in python?

Ответить
@HelplessFangirl
@HelplessFangirl - 03.08.2023 05:09

If you're like me and doing this cause you couldn't figure it out on your own, I usually take notes on my code in the comments so I understand the logic when I come back to it and to solidify it in my head.

hope this helps!

Ответить
@imang3719
@imang3719 - 01.08.2023 08:55

Thank you @NeetCode for all the great videos! I just want to point out that the optimal approach is great for a large n but in case of this particular problem because n is limited to max of 100 (0 <= strs[i].length <= 100), log(n) would be 6.6 which makes m*n*log n faster than m*n*26

Ответить
@deotexh
@deotexh - 21.07.2023 18:55

My brain is fuming, I'm not made for developping...

Ответить
@StoriesByDrew
@StoriesByDrew - 06.07.2023 05:57

I originally tried to solve this by creating a hash using the char codes of each char in a string and using the hash as the key to group the values. I had a ton of collisions as my hashing function was crappy. Was wondering if you'd revisit this and solve with hashing?

Ответить
@Dhanushh
@Dhanushh - 28.06.2023 18:39

No way, the code is this concise and clear in Python. That's it. I am divorcing Java for leetcode. Switching to python.

Ответить
@indhumathi5846
@indhumathi5846 - 25.06.2023 14:20

understood

Ответить
@TheRongster
@TheRongster - 22.06.2023 09:19

i dunno if anyone will see this but is accessing the hash map with keys of an array really constant time and gonna work lol?

Ответить
@razewithodin
@razewithodin - 20.06.2023 07:19

I'm confused. What about for a test case like ["ab","c"]. ab and c both = 3 so they would just go in same list even though they are not anagrams?

Ответить
@lgami
@lgami - 17.06.2023 11:20

First of all, thanks for your work.

I coded first and second solutions in python3, solution 1 (using sorted strings) seems to perform better in speed use and in memory use on leetcode test cases.

Ответить
@ikakika1745
@ikakika1745 - 16.06.2023 23:24

would it be better to use a hashmap to count the letters and use that as the key instead of reusing an array with 26 spots for each letter in the alphabet? I feel like that is wasting a lot of memory and using a hashmap would slightly improve on that

Ответить
@elitea6070
@elitea6070 - 11.06.2023 12:01

Oh my god I feel so stupid. Every leetcode question I am mind boggled and I come here for answers after hours of trying JUST FOR THE ANSWERS TO BE VERY SIMPLE. MY INTERVIEW IS TODAY AND I WILL NOT MAKE IT. I will never be a good programmer. Like every question I do I never think of the correct answer even if its very basic. I feel like im wasting my time. Im so scared that I wont make it as a successful programmer no matter how hard I try. This question was the last straw for me and im losing my mind rn.

Ответить
@astik2002
@astik2002 - 02.06.2023 09:20

How the length of the count array is 26??

Ответить
@mounirkanane8083
@mounirkanane8083 - 29.05.2023 01:46

Does anyone know the space complexity?

Ответить
@TadesseDev
@TadesseDev - 27.05.2023 17:14

Nice explanation @NeetCode. Mind me but I have something to discuss, I'm not a master at this, just a thought I'm having. Considering we have 100 characters in a substring n, it will take us 100 characters to check the character and save it in the hash instead of just 26, wouldn't it be better to sort it with "log-n". I believe this might make the worst memory usage, since instead of counting, this time we will be saving the whole string.

Ответить
@sweetphilly2
@sweetphilly2 - 13.05.2023 21:29

yeah I would've never thought of the ASCII value stuff. Twas thinking about going with Counter and using the result as a key if possible

Ответить
@ParryHotter73
@ParryHotter73 - 10.05.2023 20:43

nah its not worth it, O(m*nlogn) might perform better

Ответить
@anuragmodi02
@anuragmodi02 - 06.05.2023 21:01

I wonder how storing array as a key will work in C# or java, since even if 2 array sequence are same, dictionary.ContainsKey(array) will be always false since we are doing new int[25] on each iteration.

Ответить
@mostafamekawy5425
@mostafamekawy5425 - 21.04.2023 23:27

Wouldn't this algorithm fail if encountered two words with same sum but different characters ? such as "eat" & "bas" I know "bas" isn't a word but still they would match.

Ответить
@RohithMusic
@RohithMusic - 13.04.2023 04:44

You automatically assumed that sorting the alphabets of each string is O(nlog(n)). This only applies for a comparison based sort. However, you can sort using counting sort which will end up taking O(26) + O(n) time (or O(n)) plus O(n) additional space. If we serialize the output of counting sort as character followed by count, instead of constructing the whole sorted string, we will end up with exactly the same key as you got. A hashmap can then be used as usual to finish the problem.

Ответить
@JohnIdlewood
@JohnIdlewood - 07.04.2023 20:04

The downside of this approach is that you're using a hashmap. What's bad here is that we don't know how the hash of the key is calculated and we don't consider if there're hash collisions and therefore we can't guarantee that our operations with hashmap will be O(1). Because the hashmap is used inside a for loop, the overall complexity will be O(m*n^2)

Ответить
@MichaelShingo
@MichaelShingo - 05.04.2023 11:23

what a smart solution

Ответить