在一串字符

时间:2017-09-20 19:20:01

标签: java sorting data-structures treemap

我有一个字符串说“aaabbacccd”这里count [a] = 4 count [b] = 2 count [c] = 3且count [d] = 1。我必须找到第n个最大频率的角色。在上面的字符串中,具有第三高频率的字符是b(因为1 <2 <3 <4)并且计数[b] = 2

直接的解决方案是将字符Vs频率存储在地图中,并使用排序集合按值排序值,如下所示

public class MapUtil {
public static <K, V extends Comparable<? super V>> Map<K, V> 
    sortByValue(Map<K, V> map) {
    List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
    Collections.sort( list, new Comparator<Map.Entry<K, V>>() {
        public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
            return (o1.getValue()).compareTo( o2.getValue() );
        }
    });

    Map<K, V> result = new LinkedHashMap<K, V>();
    for (Map.Entry<K, V> entry : list) {
        result.put(entry.getKey(), entry.getValue());
    }
    return result;
}

}

我尝试使用树形图解决此问题,以根据计数按排序顺序维护字符。但是我最终得到的是违反相等性并与约束相比,因此我的地图以不一致的值结束。

因此,无法以最佳方式使用Tree-map或任何其他数据结构来解决此问题?

11 个答案:

答案 0 :(得分:1)

以下是流媒体解决方案:

import java.util.Collections;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


public class StackOverflow {

  private static class S46330187 {
    public static void main(String[] args) {
      //prints b
      System.out.println(kthMostFrequentChar("aaabbacccd",3));
      //prints b
      System.out.println(kthMostFrequentChar("aaabbacccbbbd",1));
      //prints e
      System.out.println(kthMostFrequentChar("aaabbbcccdddeee",5));

    }

    private static Character kthMostFrequentChar(final String string, final int kth) {
      Map<Integer, Long> counts = string.chars()
          .boxed()
          .collect(Collectors.groupingBy(
              Function.identity(),
              Collectors.counting()
          ));
      return counts.entrySet()
          .stream()
          .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
          .map(e->(char)e.getKey().intValue())
          .limit(kth)
          .reduce((l,r)->r)
          .orElseThrow(IllegalArgumentException::new);
    }

  }
}

答案 1 :(得分:1)

使用TreeMap不会有太大帮助,因为它是按键排序的,而不是按值排序。

这是我的简单算法:

  1. 收集有关字符出现在给定字符串中的次数的信息。
  2. 将其存储在角色和频率的地图中。
  3. 检索值(频率)并对其进行反向排序。
  4. 从此反向排序值中选择第3个值(因为您需要第三个最高频率)。
  5. 从地图中查找具有此频率的所有键(字符)并打印出来。
  6. 这是一个基于此算法的工作程序:

        String str = "aabbddddccc";
        Map<Character, Integer> map = new HashMap<>();
        while (!str.isEmpty()) {
            char ch = str.charAt(0);
            String[] arr = str.split(Character.toString(ch));
            map.put(ch, arr.length == 0 ? str.length() : arr.length - 1);
            str = String.join("", arr);         
        }
        System.out.println(map);
        List<Integer> values = new ArrayList<>(map.values().stream().sorted().collect(Collectors.toSet()));
        Collections.reverse(values);
        map.keySet().stream().filter(e -> map.get(e) == values.get(3)).forEach(System.out::println);
    

答案 2 :(得分:0)

维护两张地图。

  • 首先,在常规HashMap中将char映射到int(即char到frequency)。
  • 其次,在TreeMap中将int映射到List(即具有该频率的字符的频率)。

逐个读取所有输入字符并更新两个映射。完成输入后,请浏览TreeMap以获取列表。

从最高频率开始,

  • 如果该列表的 k 元素少于(等于 m ),则转到下一个并查找(k - m) 元素。
  • 另一方面,如果列表具有多个 k 元素,则返回列表中的第一个元素,因为 k th 发生率最高的元素。

答案 3 :(得分:0)

o(n)时间和恒定空间的解决方案。

假设它只包含字符。

伪代码(从手机上写,没有IDE)

1) create a data structure of
Frequency
 Char ch,
 int v
2) create an array (frqy) of 52 length and type Frequency
2.1 initialize each of the 52 object with character a-zA-Z

3) itterate over each character (ch) in the string
3.1) check if (int)ch <=122 and >= 96
  Then  increment the frequency of  the frqy array at index (int)ch - 96

3.3) check if (int)ch <=90 and >= 65
  Then  increment the frequency of  the frqy array at index (int)ch - 65+26

4 ) sort the array based on frequency  and now you have the answer

答案 4 :(得分:0)

  1. 我们将使用地图计算频率,然后将计数和字符存储在成对列表中。
  2. 以自定义方式对列表进行排序(基于字符数)(使用比较器或lambda)
  3. 从列表中检索第K个值。

    import java.util.*;
    import java.lang.*;
    import java.io.*;
    class Main{
        static class Pair{
        char first;
        int second;
        Pair(char first,int second){
            this.first=first;
            this.second=second;
        }
    }
    public static void main(String[] args) {
        TreeMap<Character,Integer> m = new TreeMap<>();    
        String s;
        int k;
        for(int i=0;i<s.length();i++){
            char ch = s.charAt(i);
            int x=0;
            if(m.containsKey(ch))
                x=m.get(ch);
            m.put(ch,x+1);
        }
        ArrayList<Pair> list = new ArrayList<Pair>();
        for(Map.Entry<Character,Integer> i : m.entrySet()){
            w.println(i.getKey() +" : "+i.getValue());
            list.add(new Pair(i.getKey(),i.getValue()));
        }
        Collections.sort(list, (a,b)->{if(a.second>=b.second) return -1; else return 1;});
        System.out.println(list.get(k-1).first);
    }
    
    }
    
  4. 为确保您拥有第k个Frequent元素,您可以使用hashSet计算唯一频率的数量,以及是否可以获得第k个频率。

  5. 实时运行代码示例: https://ideone.com/p34SDC

答案 5 :(得分:0)

以下是不使用Java 8的简单解决方案

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
class TestClass {
public static void main(String args[]) throws Exception {
    // ma("aaabbacccd",3);
    // ma("aaabbacccbbbd",4);
    ma("aabbcd", 1);
}

private static void ma(String s, int k) {
    TreeMap<Character, Integer> map = new TreeMap<>();
    for (int i = 0; i < s.length(); i++) {
        if (map.containsKey(s.charAt(i))) {
            map.put(s.charAt(i), map.get(s.charAt(i)) + 1);
        } else {
            map.put(s.charAt(i), 1);
        }
    }
    System.out.println(map.toString());
    Set<Entry<Character, Integer>> set = map.entrySet();
    List<Entry<Character, Integer>> list = new ArrayList<>(set);
    Collections.sort(list, new Comparator<Map.Entry<Character, Integer>>() {
        public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
            return o2.getValue().compareTo(o1.getValue());
        }
    });
    Set<Integer> ls = new LinkedHashSet<>();
    System.out.println("after sorting by value-----");
    for (Entry<Character, Integer> e : list) {
        System.out.println("key: " + e.getKey() + " value: " + e.getValue());
        ls.add(e.getValue());
    }
    System.out.println("removed duplicate from value array --------" + ls.toString());
    System.out.println(new ArrayList<>(ls).get(k - 1));
    for (Entry<Character, Integer> e1 : list) {
        if (e1.getValue().equals(new ArrayList<>(ls).get(k - 1))) {
            System.out.println(e1.getKey());
            break;
        }
    }
}

答案 6 :(得分:0)

这在联机测试期间非常方便,因为这是使用两个地图的非常简单的解决方案。     我们首先创建一个字符频率哈希表。使用此方法,我们可以创建频率字符树图,     仅当值较小时才将元素插入树形图(这是为了处理存在     多个字符具有相同的频率)。树状图制作完成后(已经     按频率递增的顺序排序),我们只打印与第k个最高频率相对应的字符。

import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception{
    String s="1112229999955555777777777";
    HashMap<Character,Integer> hm= new HashMap<Character,Integer>();
    for(int i=0;i<s.length();i++){
        char cur=s.charAt(i);
        if(!hm.containsKey(cur)){
            hm.put(cur,0);
        }
        hm.put(cur,hm.get(cur)+1);
    }
    TreeMap<Integer,Character> tm= new TreeMap<Integer,Character>();

    for(Map.Entry<Character,Integer> entry:hm.entrySet()){
        int x=entry.getValue();
        char cur=entry.getKey();
        if(!tm.containsKey(x)){
            tm.put(x,cur);
        }
        else{
            if(cur<tm.get(x))
                tm.put(x,cur);
        }

    }

    int k=2; // print the kth most frequent character. If there are multiple, print the one with lesser value
    int tar=tm.size()-k;
    if(tar<0) System.out.println("-1");
    else{
    int d=0;
    for(Map.Entry<Integer,Character> entry: tm.entrySet()){

        int x=entry.getKey();
        char cur=entry.getValue();
        //System.out.println(cur+" "+x);
        if(d++==tar)  {
            System.out.println("ans- "+cur);
            break; // we have found the requried character, so break
        }
    }

    }

}
}

答案 7 :(得分:0)

static String getNthlargestFrequency(String str, int K) {
    char[] charArr = str.toCharArray();     
    String result = "-1"; //if nth frequency doesn't exist
    Map<Character, Integer> map = new HashMap<Character, Integer>();
    for (char value : charArr) {
        if (map.containsKey(value)) {
            map.put(value, map.get(value) + 1);
        } else {
            map.put(value, 1);
        }
    }
    // sort map on value basis [desc]
    System.out.println("Original map" + map);
    Map sorted = map.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
            .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (e1, e2) -> e2, LinkedHashMap::new));
    //get character with nth maximum frequency
    Optional<Entry<Integer, Character>> entry = sorted.entrySet().stream().skip(K - 1).findFirst();
    if (entry.isPresent()) {
        result = ""+entry.get().getValue();
    }
    return result;
}

注意:

如果有多个具有相同第n个频率的字符,则将返回最后一个字符。

答案 8 :(得分:0)

String str = scanner.next();
int k = scanner.nextInt();
HashMap <Character, Integer> hash = new HashMap();
int len = str.length();
Set <Integer> set = new TreeSet < > ();
for (int i = 0; i < len; i++) {
  Integer count = hash.get(str.charAt(i));
  if (count == null) {
    count = 0;
  }
  hash.put(str.charAt(i), count + 1);
} //iterate the entire map
for (Map.Entry < Character, Integer > h: hash.entrySet()) {
  set.add(h.getValue());
}
int length = set.size();
if (k > length) {
  System.out.println("-1");
} else {
  System.out.println(set);
  Iterator < Integer > it = set.iterator();
  int j = 0;
  Integer integer = null;
  while (it.hasNext() && j <= length - k) {
    integer = it.next();
    j++;
  }
  int x = integer;
  for (Map.Entry < Character, Integer > h: hash.entrySet()) {
    if (h.getValue() == integer) {
      System.out.println(h.getKey());
      break;
    }
  }
}

答案 9 :(得分:0)

使用自定义类使用HashMap和Priority Queue解决。

import java.util.Comparator;
import java.util.HashMap;
import java.util.PriorityQueue;

public class kth_largest_in_a_string {

    static class myclass {
        int count;
        char ch;

        myclass(int count, char ch) {
            this.count = count;
            this.ch = ch;
        }
    }

    public static Character helper(String input, int k) {
        HashMap<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < input.length(); i++) {
            if (!map.containsKey(input.charAt(i))) {
                map.put(input.charAt(i), 1);
            } else {
                map.put(input.charAt(i), map.get(input.charAt(i)) + 1);
            }
        }
        PriorityQueue<myclass> pq = new PriorityQueue<>(input.length(), new Comparator<myclass>() {
            public int compare(myclass a, myclass b) {
                return b.count - a.count;
            }
        });
        for (HashMap.Entry<Character, Integer> entry : map.entrySet()) {
            pq.add(new myclass(entry.getValue(), entry.getKey()));
        }
        for (int i = 0; i < k - 1; i++)
            pq.remove();
        myclass ans = pq.remove();
        return ans.ch;
    }

    public static void main(String[] args) {
        System.out.println(helper("aaabbacccd", 3));
    }
}

答案 10 :(得分:0)

public class MyStringDemo {

    public static void main(String[] args) {
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.print("Enter Test Case Numbers: ");
            int T = Integer.parseInt(scanner.nextLine());
            int testCases[] = new int[T];
            
            for (int i=0 ; i < testCases.length; i++) {
                System.out.print("Enter String: ");
                String str = scanner.nextLine();
                System.out.print("Enter Kth String Number: ");
                int K = Integer.parseInt(scanner.nextLine());
                String result = getKthFrequency(str, K);
                System.out.println(result);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    static String getKthFrequency(String str, int K) {
        HashMap<Character, Integer> hp = new HashMap<Character, Integer>();
        char chs[] = str.toCharArray();
        
        for (char c : chs) {
            if (hp.containsKey(c)) {
                hp.put(c, hp.get(c) + 1);
            } else {
                hp.put(c, 1);
            }
        }
        char ch = 'z';
        boolean flag = false;
        for (Map.Entry<Character, Integer> val : hp.entrySet()) {
            if (K == val.getValue()) {
                if (ch > val.getKey()) {
                    ch = val.getKey();
                    flag = true;
                }
                return ch + "";
            }
            flag = false;
        }
        return flag == true ? ch + "" : "-1";
    }
}