文章目录
Leetcode 501.二叉搜索树中的众数
1.问题描述
2.解决方案
解法一:按普通二叉树的做法
总结:
这个思路很简单就是遍历一遍统计频率第二遍把最高的加入结果集,但是难的是代码的实现技巧
1.下面这两条语句可以直接写成一条,因为uMap即使没加入一个k-v,也可以直接uMap[k]++,所以优化版本在遍历的同时便统计了频率而不是先遍历再统计
if(uMap.find(item)==uMap.end()) uMap[item]=1;
else uMap[item]++;
2.就是对频率排序这个操作是个问题,下图说得很清楚了,这也算是个代码实现技巧了,因为一开始我统计完频率是不知道该怎么优雅的把众数统计出来的!
原始:
class Solution {
public:
vector<int> inorder;
void tran(TreeNode* root){
if(root== nullptr) return;
tran(root->left);
inorder.push_back(root->val);
tran(root->right);
}
bool static cmp(pair<int,int> a,pair<int,int> b){
//频率由高到低
return a.second>b.second;
}
vector<int> findMode(TreeNode* root) {
//1.想到了
tran(root);
unordered_map<int,int> uMap;
for (auto item: inorder) {
if(uMap.find(item)==uMap.end()) uMap[item]=1;
else uMap[item]++;
}
//2.这我就没想到了
vector<pair<int,int>> vec(uMap.begin(),uMap.end());
sort(vec.begin(),vec.end(),cmp);
vector<int> ans;
ans.push_back(vec[0].first);
for(int i=1;i<vec.size();i++){
if(vec[i].second==vec[0].second) ans.push_back(vec[i].first);
else break;
}
return ans;
}
};
优化:
class Solution1 {
public:
void tran(TreeNode* root,unordered_map<int,int>& uMap){
if(root== nullptr) return;
tran(root->left,uMap);
uMap[root->val]++;
tran(root->right,uMap);
}
bool static cmp(pair<int,int> a,pair<int,int> b){
//频率由高到低
return a.second>b.second;
}
vector<int> findMode(TreeNode* root) {
//1.想到了
unordered_map<int,int> uMap;
tran(root,uMap);
//2.这我就没想到了
vector<pair<int,int>> vec(uMap.begin(),uMap.end());
sort(vec.begin(),vec.end(),cmp);
vector<int> ans;
ans.push_back(vec[0].first);
for(int i=1;i<vec.size();i++){
if(vec[i].second==vec[0].second) ans.push_back(vec[i].first);
else break;
}
return ans;
}
};
Java:思路差不多,主要是用的集合框架完成的对value的排序
public class lc501 {
Map<Integer, Integer> map = new HashMap<>();
public void getFrequency(TreeNode root) {
if(root==null) return;
map.put(root.val, map.getOrDefault(root.val, 0)+1);
getFrequency(root.left);
getFrequency(root.right);
}
public int[] findMode(TreeNode root) {
//
if(root==null) return new int[0];
getFrequency(root);
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
ArrayList<Map.Entry<Integer, Integer>> list = new ArrayList<>(entries);
Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {
@Override
public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
//默认value升序
//return o1.getValue().compareTo(o2.getValue());
//按照value降序
return o2.getValue().compareTo(o1.getValue());
}
});
//
List<Integer> ans = new ArrayList<>();
ans.add(list.get(0).getKey());
for (int i = 1; i <= list.size()-1; i++) {
if(list.get(i).getValue()!=list.get(i-1).getValue()) break;
ans.add(list.get(i).getKey());
}
int[] array = ans.stream().mapToInt(Integer::intValue).toArray();
return array;
}
}
解法二:按二叉搜索树遍历一遍出结果的做法
总结:
思路呢这里已经说得很清楚了,我也就不多说,其实思路不是很难就是更新有更大的count就清空结果集再加入,然而其实难得是代码实现技巧
1.第一个技巧用pre记录递归遍历的前一个结点,在这篇博客第一次使用530. 二叉搜索树的最小绝对差,非常好用,初始化为nullptr然后每次对空不空做出判断就好!
2.这题目和530. 二叉搜索树的最小绝对差思路很像啊,就是我们不需要把中序序列求出来再作文章,我们直接在递归过程中进行一个前后元素比较!
3.既然是中序遍历那肯定大体框架不会变tran(cur->left)…中间节点处理…tran(cur->right)
4.再实现逻辑的时候有个大致的思路,我们声明了四个全局变量
int maxCount=0;
int count=0;
vector<int> ans;
TreeNode* pre= nullptr;
那么是不是我们再对情况使用if做一个分类之后就要想这种情况对这四个全局变量要作何处理,每一种情况都这么想就不会出错了!
5.代码实现小错误,我写代码不喜欢写else,一般都是两个if这也导致一种错误情况的出现,在if的expr判断的变量如果在第一个if被改变,那很有可能第二个if的判断就不是一开始的那个变量了,比如这段代码,所以在两个if作为完全集考虑的时候一定考虑第一个if是否对if的条件变量做出了改变如果有,及时处理,换成else或者如果在for里面加上continue等!
if(pre== nullptr){
count=1;
maxCount=1;
ans.push_back(cur->val);
pre=cur;
}
//if(pre!= nullptr){ //代码小错误
else{
6.至于一遍出结果这个思路还是很不错的,建议多看!
代码:
class Solution2 {
public:
int maxCount=0;
int count=0;
vector<int> ans;
TreeNode* pre= nullptr;
void tran(TreeNode* cur){
if(cur== nullptr) return;
tran(cur->left);
if(pre== nullptr){
count=1;
maxCount=1;
ans.push_back(cur->val);
pre=cur;
}
//if(pre!= nullptr){ //代码小错误
else{
if(pre->val==cur->val){
count++;
pre=cur;
}
if(pre->val!=cur->val){
count=1;
pre=cur;
}
if(count==maxCount){
ans.push_back(cur->val);
}
if(count>maxCount){
maxCount=count;
ans.clear();
ans.push_back(cur->val);
}
}
tran(cur->right);
}
vector<int> findMode(TreeNode* root) {
tran(root);
return ans;
}
};
解法三:迭代
老生常谈了,用迭代代替递归实现中序遍历,这边就不给出了暂时!
Leetcode 451.根据字符出现频率排序
1.问题描述
2.解决方案
简单的按照频率排序,然后从高到低依次写入结果集
class Solution {
public String frequencySort(String s) {
//统计频率
HashMap<Character, Integer> map = new HashMap<>();
for(char c : s.toCharArray()){
map.put(c, map.getOrDefault(c, 0) + 1);
}
//按照频率排序从高到低
List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet());
Collections.sort(list, (map1, map2) -> (map2.getValue() - map1.getValue()));
//从高到低构造结果集
StringBuilder sb = new StringBuilder();
for(var entry : list){
int fre = entry.getValue();
while(fre-->0){
sb.append(entry.getKey());
}
}
return sb.toString();
}
}