May LeetCoding Challenge22 之 比较器comparator、map按Value排成逆序、桶排序
本题需要统计字符个数,并按逆序排序,共有三种解法:
1.用数组存储排序,先将字符串转为字符数组,调用Arrays.sort方法对字符数组排序,将相同的字符存储在一个字符串中,将所有字符串存入list中,按照每个字符串长度由大到小进行排序,新建一个StringBuilder,将排好序的字符串依次添加到StringBuilder中,最后转成String输出。
2.HashMap存储排序,用HashMap统计字符及出现次数,存入count中,对count的value值进行排序,然后依次添加字符到StringBuilder中,最后转成String输出。
3.桶排序,用HashMap统计字符及出现次数,存入count中,遍历count得到最大的value,用ArrayList建立value个空桶,将字符放入桶中,桶的顺序是字符出现的频次,从后向前遍历每个桶中的字符,添加到StringBuilder中,最后转成String输出。
语法补充:
1.Comparator比较器复写方法
Collections.sort(list, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getId() - o2.getId(); } };
list.sort(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getId() - o2.getId(); } });
Collections.sort(list, (a, b) -> b.getId()-a.getId());
2.将map按Value大小逆序排序,需要利用map.entrySet()并存入list中[(Character1,Integer1), (Character2,Integer2)]
//首先将count放入list List<Map.Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(count.entrySet());//[(Character1,Integer1), (Character2,Integer2)] //用list对Comparator复写,实现按map的Value逆序排序 list.sort(new Comparator<Map.Entry<Character, Integer>>(){ @Override public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer>o2){ return o2.getValue()-o1.getValue(); } });
3.遍历map对象
Map<Integer, Integer> map = new HashMap<Integer, Integer>(); for (Map.Entry<Integer, Integer> entry : map.entrySet()) { System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); } //遍历map中的键 for (Integer key : map.keySet()) { System.out.println("Key = " + key); } //遍历map中的值 for (Integer value : map.values()) { System.out.println("Value = " + value); }
4.Python的Counter, 和 mostcommon 和 .join 和 sort的熟练使用
# Sort the strings by length from *longest* to shortest. charStrings.sort(key=lambda string : len(string), reverse=True)
def frequencySort(self, s: str) -> str:
# Count up the occurances.
counts = collections.Counter(s)
# Build up the string builder.
string_builder = []
for letter, freq in counts.most_common():
# letter * freq makes freq copies of letter.
# e.g. "a" * 4 -> "aaaa"
string_builder.append(letter * freq)
return "".join(string_builder)
JAVA
class Solution { public String frequencySort(String s) { if(s == null || s.isEmpty()) return s; StringBuilder res = new StringBuilder(); //将字符串转成字符数组并排序 char[] chars = s.toCharArray(); Arrays.sort(chars); //将字符相同的存入一个字符串,并将所有字符串存入list List<String> charStrings = new LinkedList<>(); StringBuilder temp = new StringBuilder(); temp.append(chars[0]); for(int i = 1; i < chars.length; i++){ if(chars[i] != chars[i-1]){ charStrings.add(temp.toString()); temp = new StringBuilder(); } temp.append(chars[i]); } charStrings.add(temp.toString()); //对list 按照字符串长度从大到小排序 Collections.sort(charStrings, (a, b) -> b.length()-a.length()); //将排序后的字符串依次存入结果 for(String str : charStrings){ res.append(str); } return res.toString(); } }
class Solution { public String frequencySort(String s) { StringBuilder res = new StringBuilder(); Map<Character, Integer> count = new HashMap<>(); for(char c: s.toCharArray()){ count.put(c, count.getOrDefault(c, 0)+1); } //首先将count放入list List<Map.Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(count.entrySet());//[(Character1,Integer1), (Character2,Integer2)] //用list对Comparator复写,实现按map的Value逆序排序 list.sort(new Comparator<Map.Entry<Character, Integer>>(){ @Override public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer>o2){ return o2.getValue()-o1.getValue(); } }); for (Map.Entry<Character, Integer> map : list){ for(int i = 0; i < map.getValue(); i++){ res.append(map.getKey()); } } return res.toString(); } }
class Solution { public String frequencySort(String s) { if(s == null || s.isEmpty()) return s; StringBuilder res = new StringBuilder(); Map<Character, Integer> count = new HashMap<>(); for(char c: s.toCharArray()){ count.put(c, count.getOrDefault(c, 0)+1); } int maxFrequency = 0; for(Map.Entry<Character, Integer> entry: count.entrySet()){ maxFrequency = Math.max(maxFrequency, entry.getValue()); } System.out.println(maxFrequency); //申请一排桶,桶的顺序代表桶内字符出现的次数 List<List<Character>> buckets = new ArrayList<>(); //bug 这里写成LinkedList会超时,因为单个字符出现次数多的时候,需要访问的桶也增多。 //ArrayList访问速度快,LinkedList增加删除速度快 //构建空桶 for(int i = 0; i <= maxFrequency; i++){ buckets.add(new LinkedList<Character>()); } //根据字符出现的次数放入对应的桶内 for(Character key: count.keySet()){ int freq = count.get(key); buckets.get(freq).add(key); //!!!桶排序最重要的一步 } for(int i =buckets.size()-1; i >= 1; i--){ for(Character c: buckets.get(i)){//一个桶内可能有多个字符 for(int j = 0; j < i; j++){ res.append(c); } } } return res.toString(); } }
Python3
class Solution: def frequencySort(self, s: str) -> str: if not s: return s # Convert s to a list. s = list(s) # Sort the characters in s. s.sort() # Make a list of strings, one for each unique char. charStrings = [] temp = [s[0]] for c in s[1:]: # If the last character on string builder is different... if temp[-1] != c: charStrings.append("".join(temp)) temp = [] temp.append(c) charStrings.append("".join(temp)) # Sort the strings by length from *longest* to shortest. charStrings.sort(key=lambda string : len(string), reverse=True) # Convert to a single string to return. # Converting a list of strings to a string is often done # using this rather strange looking python idiom. return "".join(charStrings)
def frequencySort(self, s: str) -> str: # Count up the occurances. counts = collections.Counter(s) # Build up the string builder. string_builder = [] for letter, freq in counts.most_common(): # letter * freq makes freq copies of letter. # e.g. "a" * 4 -> "aaaa" string_builder.append(letter * freq) return "".join(string_builder)
def frequencySort(self, s: str) -> str: if not s: return s # Determine the frequency of each character. counts = collections.Counter(s) max_freq = max(counts.values()) # Bucket sort the characters by frequency. buckets = [[] for _ in range(max_freq + 1)] for c, i in counts.items(): buckets[i].append(c) # Build up the string. string_builder = [] for i in range(len(buckets) - 1, 0, -1): for c in buckets[i]: string_builder.append(c * i) return "".join(string_builder)