so basically i have C:/180301.txt file in which i have 1 1 2 2 3 4 5 numbers\bytes and output(49) is correct i think. my qustion is how to print out all elements which coming repetiteve times, now i have only one its 49
private static ArrayList<Integer> list1 = new ArrayList<>();
private static ArrayList<Integer> list2 = new ArrayList<>();
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
FileInputStream fileReader = new FileInputStream(br.readLine());
while (fileReader .available() > 0)
{
list1.add(fileReader .read());
}
int element = 0;
int count = 0;
for (int i = 0; i < list1.size(); i++)
{
if (same_element(list1.get(i)))
{
for (int j = 0; i < list1.size(); i++)
{
if (list1.get(i).equals(list1.get(j)))
{
count++;
element = list1.get(j);
list2.add(list1.get(i));
}
}
}
}
if (count > 1)
System.out.println(element);
fileReader.close();
}
private static boolean same_element(int list_i) {
for (Integer aList2 : list2) if (list_i == aList2) return false;
return true;
}
}
In same_element you have to switched true and false. 49 is prtinted because you never increase j. So the inner loop is buggy, too. But it should be deleted anyway because same_element now should do that job. The third problem is that you add the recent value only to the list of already seen value if it's already in there. That can't ever happen. So with some slight reworks your code might look like this:
List<Integer> fromFile = new ArrayList<>();
InputStream fileReader = new ByteArrayInputStream("71123456".getBytes("utf-8"), 0, 8);
while (fileReader.available() > 0)
{
fromFile.add(fileReader.read());
}
int element = 0;
int count = 0;
List<Integer> seen = new ArrayList<>();
for (int i = 0; i < fromFile.size(); i++)
{
Integer recent = fromFile.get(i);
if (seen.contains(recent))
{
count++;
element = recent;
}
seen.add(recent);
}
if (count > 1) System.out.println(element);
fileReader.close();
This prints the last duplicate, but still not the byte with most occurences. Today we write it like this:
Map<Byte, Integer> counters = new HashMap<>();
Path path = FileSystems.getDefault().getPath(args[0]);
// build a map with byte value as a key refering to a counter in the value
for (Byte b: Files.readAllBytes(path)) {
Integer old = counters.get(b);
counters.put(b, (old == null ? 1 : old + 1));
}
// create a comparator that orders Map.Entry objects by their value. I.E. the
// occurences of the respective byte. The order is ascending.
Comparator<Entry<Byte, Integer>> byVal = Comparator.comparingInt(e -> e.getValue());
// create a stream of Map.Entry objects. The stream is a new concept of Java8.
// That's somehow like a collection, but more powerful. While the collection
// stores data he stream has a focus on manipulating
counters.entrySet().stream()
// Use the comaparator in reversed form. That means the number of
// occurences is now descending
.sorted(byVal.reversed())
// only use the first Map.Entry. I.E. the one with most occurences
// a similar functionality is by filter.
// .filter(e -> e.getValue() > 1) would use all duplicates
.limit(1)
// print out the results. Of course the argument for println can be
// concatenated from several parts like:
// e.getKey() + "\tcount: " + e.getValue()
.forEach(e -> System.out.println(e.getKey()));
Java 8 helps a lot for problems like this. Tying to write the same with former versions take quite a bit more code.
Related
What is the easiest way to get the most duplicated value in a list and sorted in descending order...
for example:
List<String> list = new ArrayList<>(List.of("Renault","BMW","Renault","Renault","Toyota","Rexon","BMW","Opel","Rexon","Rexon"));
`
"renault" & "rexon" are most duplicated and if sorted in descending order alphabetically I would like to get the rexon.
I think one of the most readable and elegant way would be to use the Streams API
strings.stream()
.collect(Collectors.groupingBy(x -> x, Collectors.counting()))
.entrySet().stream()
.max(Comparator.comparingLong((ToLongFunction<Map.Entry<String, Long>>) Map.Entry::getValue).thenComparing(Map.Entry::getKey))
.map(Map.Entry::getKey)
.ifPresent(System.out::println);
Create a map of names with their corresponding number of occurrences.
Get names and sort them in descending order.
Print the first name that has the highest number of occurrences.
class Scratch {
public static void main(String[] args) {
List<String> list = List.of("Renault","BMW","Renault","Renault","Toyota","Rexon","BMW","Opel","Rexon","Rexon");
Map<String, Integer> duplicates = new HashMap<>();
// 1. Create a map of names with their corresponding
// number of occurrences.
for (String s: list) {
duplicates.merge(s, 1, Integer::sum);
}
// 2. Get names and sort them in descending order.
List<String> newList = new ArrayList<String>(duplicates.keySet());
newList.sort(Collections.reverseOrder());
// 3. Print the first name that has the highest number of
// occurrences.
Integer max = Collections.max(duplicates.values());
newList.stream().filter(name -> duplicates.get(name).equals(max))
.findFirst()
.ifPresent(System.out::println);
}
}
After some time this is what I came with (I only tested it with your example and it worked):
public class Duplicated {
public static String MostDuplicated(String[] a) {
int dup = 0;
int position = -1;
int maxDup = 0;
for(int i = 0; i < a.length; i++) { //for every position
for(int j = 0; j < a.length; j++){ //compare it to all
if(a[i].equals(a[j])) { dup++; } // and count how many time is duplicated
}
if (dup > maxDup) { maxDup = dup; position = i;}
//if the number of duplications
//is greater than the maximum you have got so far, save this position.
else if (dup == maxDup) {
if( a[i].compareTo(a[position]) > 0 ){ position = i; }
//if its the same, keep the position of the alphabetical last
// (if u want the alphabetical first, just change the "<" to ">")
}
}
return a[position]; //return the position you saved
}
}
You are asking to sort the list and then find the most common item.
I would suggest that the easiest way to sort the list is using the sort method that is built into list.
I would then suggest finding the most common by looping with the for..each construct, keeping track of the current and longest streaks.
I like Yassin Hajaj's answer with streams but I find this way easier to write and easier to read. Your mileage may vary, as this is subjective. :)
import java.util.*;
public class SortingAndMostCommonDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("Renault","BMW","Renault","Renault","Toyota","Rexon","BMW","Opel","Rexon","Rexon"));
list.sort(Comparator.reverseOrder());
System.out.println(list);
System.out.println("The most common is " + mostCommon(list) + ".");
}
private static String mostCommon(List<String> list) {
String mostCommon = null;
int longestStreak = 0;
String previous = null;
int currentStreak = 0;
for (String s : list) {
currentStreak = 1 + (s.equals(previous) ? currentStreak : 0);
if (currentStreak > longestStreak) {
mostCommon = s;
longestStreak = currentStreak;
}
previous = s;
}
return mostCommon;
}
}
The fast algorithm takes advantage of the fact that the list is sorted and finds the list with the most duplicates in O(n), with n being the size of the list. Since the list is sorted the duplicates will be together in consecutive positions:
private static String getMostDuplicates(List<String> list) {
if(!list.isEmpty()) {
list.sort(Comparator.reverseOrder());
String prev = list.get(0);
String found_max = prev;
int max_dup = 1;
int curr_max_dup = 0;
for (String s : list) {
if (!s.equals(prev)) {
if (curr_max_dup > max_dup) {
max_dup = curr_max_dup;
found_max = prev;
}
curr_max_dup = 0;
}
curr_max_dup++;
prev = s;
}
return found_max;
}
return "";
}
Explanation:
We iterate through the list and keep track of the maximum of duplicates found so far and the previous element. If the current element is the same as the previous one we increment the number of duplicates found so far. Otherwise, we check if the number of duplicates is the bigger than the previous maximum of duplicates found. If it is we update accordingly
A complete running example:
public class Duplicates {
private static String getMostDuplicates(List<String> list) {
if(!list.isEmpty()) {
list.sort(Comparator.reverseOrder());
String prev = list.get(0);
String found_max = prev;
int max_dup = 1;
int curr_max_dup = 0;
for (String s : list) {
if (!s.equals(prev)) {
if (curr_max_dup > max_dup) {
max_dup = curr_max_dup;
found_max = prev;
}
curr_max_dup = 0;
}
curr_max_dup++;
prev = s;
}
return found_max;
}
return "";
}
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("Renault","BMW","Renault","Renault","Toyota","Rexon","BMW","Opel","Rexon","Rexon"));
String duplicates = getMostDuplicates(list);
System.out.println("----- Test 1 -----");
System.out.println(duplicates);
list = new ArrayList<>(List.of("Renault","BMW"));
duplicates = getMostDuplicates(list);
System.out.println("----- Test 2 -----");
System.out.println(duplicates);
list = new ArrayList<>(List.of("Renault"));
duplicates = getMostDuplicates(list);
System.out.println("----- Test 3 -----");
System.out.println(duplicates);
}
}
Output:
----- Test 1 -----
Rexon
----- Test 2 -----
Renault
----- Test 3 -----
Renault
Actually, I found a solution which works:
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("Renault", "BMW", "BMW", "Renault", "Renault", "Toyota",
"Rexon", "BMW", "Opel", "Rexon", "Rexon"));
Map<String, Integer> soldProducts = new HashMap<>();
for (String s : list) {
soldProducts.put(s, soldProducts.getOrDefault(s, 0) + 1);
}
LinkedHashMap<String, Integer> sortedMap = soldProducts.entrySet()
.stream()
.sorted(VALUE_COMPARATOR.thenComparing(KEY_COMPARATOR_REVERSED))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new));
String result = "";
for (Map.Entry<String, Integer> s : sortedMap.entrySet()) {
result = s.getKey();
}
System.out.println(result);
}
static final Comparator<Map.Entry<String, Integer>> KEY_COMPARATOR_REVERSED =
Map.Entry.comparingByKey(Comparator.naturalOrder());
static final Comparator<Map.Entry<String, Integer>> VALUE_COMPARATOR =
Map.Entry.comparingByValue();
I am facing a task which is generating 900000 random words and then print out the most frequent one. So here is my algorithm:
1. move all number into a collection rather than printhing out them
2. for (900000...){move the frequency of Collection[i] to another collection B}
** 90W*90W is too much for a computer(lack of efficiency)
3. find the biggest number in that collection and the index.
4. then B[index] is output.
But the thing is that my computer cannot handle the second step. So I searched on this website and find some answer about find the frequency of word in a bunch of words and I viewed the answer code, but I haven't find a way to apply them into huge amount of words.
Now I show my code here:
/** Funny Words Generator
* Tony
*/
import java.util.*;
public class WordsGenerator {
//data field (can be accessed in whole class):
private static int xC; // define a xCurrent so we can access it all over the class
private static int n;
private static String[] consonants = {"b","c","d","f","g","h","j","k","l","m","n","p","r","s","t","v","w","x","z"};
private static String[] vowels = {"a", "e", "i", "o", "u"};
private static String funnyWords = "";
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int times = 900000; // words number
xC = sc.nextInt(); // seeds (only input)
/* Funny word list */
ArrayList<String> wordsList = new ArrayList<String>();
ArrayList<Integer> frequencies = new ArrayList<Integer>();
int maxFreq;
for (int i = 0; i < times; i++) {
n = 6; // each words are 6 characters long
funnyWords = ""; // reset the funnyWords each new time
for (int d = 0; d < n; d ++) {
int letterNum = randomGenerator(); /* random generator will generate numbers based on current x */
int letterIndex = 0; /* letterNum % 19 or % 5 based on condition */
if ((d + 1) % 2 == 0) {
letterIndex = letterNum % 5;
funnyWords += vowels[letterIndex];
}
else if ((d + 1) % 2 != 0) {
letterIndex = letterNum % 19;
funnyWords += consonants[letterIndex];
}
}
wordsList.add(funnyWords);
}
/* put all frequencies of each words into an array called frequencies */
for (int i = 0; i < 900000; i++) {
frequencies.add(Collections.frequency(wordsList, wordsList.get(i)));
}
maxFreq = Collections.max(frequencies);
int index = frequencies.indexOf(maxFreq); // get the index of the most frequent word
System.out.print(wordsList.get(index));
sc.close();
}
/** randomGenerator
* param: N(generate times), seeds
* return: update the xC and return it */
private static int randomGenerator() {
int a = 445;
int c = 700001;
int m = 2097152;
xC = (a * xC + c) % m; // update
return xC; // return
}
}
So I have realized that maybe there is a way skip the second step somehow. Anyone can give me a hint? Just a hint not code so I can try it myself will be great! Thx!
Modified:
I see lots of your answer code contains "words.stream()", I googled it and I couldn't find it. Could you guys please tell me where I can find this kind of knowledge? this stream method is in which class? Thank you!
You can do it using Java Lambdas (requires JDK 8). Also notice that you can have words with equal frequency in your word list.
public class Main {
public static void main(String[] args) {
List<String> words = new ArrayList<>();
words.add("World");
words.add("Hello");
words.add("World");
words.add("Hello");
// Imagine we have 90000 words in word list
Set<Map.Entry<String, Integer>> set = words.stream()
// Here we create map of unique words and calculates their frequency
.collect(Collectors.toMap(word -> word, word -> 1, Integer::sum)).entrySet();
// Find the max frequency
int max = Collections
.max(set, (a, b) -> Integer.compare(a.getValue(), b.getValue())).getValue();
// We can have words with the same frequency like in my words list. Let's get them all
List<String> list = set.stream()
.filter(entry -> entry.getValue() == max)
.map(Map.Entry::getKey).collect(Collectors.toList());
System.out.println(list); // [Hello, World]
}
}
This can basically be broken down into two steps:
Compute the word frequencies, as a Map<String, Long>. There are several options for this, see this question for examples.
Computing the maximum entry of this map, where "maximum" refers to the entry with the highest value.
So if you're really up to it, you can write this very compactly:
private static <T> T maxCountElement(List<? extends T> list)
{
return Collections.max(list.stream().collect(Collectors.groupingBy(
Function.identity(), Collectors.counting())).entrySet(),
(e0, e1) -> Long.compare(e0.getValue(), e1.getValue())).getKey();
}
Edited in response to the comment:
The compact representation may not be the most readable. Breaking it down makes the code a bit elaborate, but may make clearer what is happening there:
private static <T> T maxCountElement(List<? extends T> list)
{
// A collector that receives the input elements, and converts them
// into a map. The key of the map is the input element. The value
// of the map is the number of occurrences of the element
Collector<T, ?, Map<T, Long>> collector =
Collectors.groupingBy(Function.identity(), Collectors.counting());
// Create the map and obtain its set of entries
Map<T, Long> map = list.stream().collect(collector);
Set<Entry<T, Long>> entrySet = map.entrySet();
// A comparator that compares two map entries based on their value
Comparator<Entry<T, Long>> comparator =
(e0, e1) -> Long.compare(e0.getValue(), e1.getValue());
// Compute the maximum element of the set of entries. That is,
// the entry with the largest value (which is the entry for the
// element with the maximum number of occurrences)
Entry<T, Long> entryWithMaxValue =
Collections.max(entrySet, comparator);
return entryWithMaxValue.getKey();
}
HashMap is one of the fastest data structures, just loop through each words, use it as key to the HashMap, inside the loop, make the counter the value of the hashMap.
HashMap<string, Integer> hashMapVariable = new HashMap<>();
...
//inside the loop of words
if (hashMapVariable.containsKey(word){
hashMapVariable.put(key, hashMapVariable.get(key) + 1);
} else {
hashMapVariable.put(word, 1);
}
...
for each key(word) just increment the value as associated with the key. although you have to check if the key exits ( in java its hashMapVariable.containsKey("key") ). if its exits then just increament else add it to the HashMap. by doing this you are not restoring the whole data you are only making every key just one and the number of times it occurs as value to the key.
At the end of the loop the most frequent word will have the highest counter/value.
you can use a HashMap and the key store word and the value is correspond times
pseudocode as below:
String demo(){
int maxFrequency = 0;
String maxFrequencyStr = "";
String strs[] ;
Map<String,Integer> map = new HashMap<String,Integer>();
for(int i = 0; i < 900000;i++){//for
if(map.containsKey(strs[i])){
int times = map.get(strs[i]);
map.put(strs[i], times+1);
if(maxFrequency<times+1){
maxFrequency = times + 1;
maxFrequencyStr = strs[i];
}
}
else{
map.put(strs[i], 1);
if(maxFrequency<1){
maxFrequency = 1;
maxFrequencyStr = strs[i];
}
}
}//for
return maxFrequencyStr;
}
I am currently solving this problem on Hackerrank, and below is the code that I have written so far.
When I ran it, there are a couple of errors: the output is totally wrong even though the input and the process are correct, and when the input is 1, it does not add it into my hashmap. I believe that both errors exist because of using HashMap. For example, if the input is
3(testcases) ==> 12, 5, 7. It will print out Prime, Prime, Not prime instead of the correct output like Not prime, Prime, Prime.
For more information, I commented out the lines,saying "output purposes". You can see, it added to the hashmap in correct order, but when it prints, it messed up.
So, I am just curious if someone can please explain why printing is wrong, and fix for the part when the input is 1.
import java.io.*;
import java.util.*;
public class Solution1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] myarray = new int[n]; // read number of testcases
for(int i=0;i<n;i++){ // add input to my int array
myarray[i]=sc.nextInt();
}
HashMap<Integer, String> newmap = new HashMap <>(); // create empty hashmap
int temp;
int value;
for(int i=0;i<n;i++){ // loop based on num of testcases
temp =myarray[i];
boolean isprime = true;
if(temp ==1){ // hardcode for input 1
isprime = false;
continue;
}
for(int j=2;j<=temp/2;j++){ // checking whether the input is prime or not
value = temp%j;
if(value==0){
isprime = false;
continue;
}
}
if(isprime==true){
//System.out.println("temp(Prime): "+temp); //output purpose
newmap.put(temp,"Prime");
}
else{
//System.out.println("temp(Not prime): "+temp); //output purpose
newmap.put(temp,"Not prime");
}
}
Set set = newmap.entrySet();
Iterator iterator = set.iterator();
//printing out values of the each element in hashmap(newmap)
while(iterator.hasNext()) {
Map.Entry mentry = (Map.Entry)iterator.next();
System.out.println(mentry.getValue());
}
}
}
The problem in your code is that your myarray is not sorted and and when you are inserting into newmap , it's not getting inserted in the desired order.
I recommend you to sort the array and used ordered map like LinkedHashMap or linked list.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] myarray = new int[n]; // read number of testcases
Arrays.sort(myarray);
for (int i = 0; i < n; i++) { // add input to my int array
myarray[i] = sc.nextInt();
}
HashMap<Integer, String> newmap = new LinkedHashMap<Integer, String>(); // create
// empty
// hashmap
int temp;
int value;
for (int i = 0; i < n; i++) { // loop based on num of testcases
temp = myarray[i];
boolean isprime = true;
if (temp == 1) { // hardcode for input 1
isprime = false;
break;
}
for (int j = 2; j <= temp / 2; j++) { // checking whether the input
// is prime or not
value = temp % j;
if (value == 0) {
isprime = false;
break;
}
}
if (isprime == true) {
// System.out.println("temp(Prime): "+temp); //output purpose
newmap.put(temp, "Prime");
} else {
// System.out.println("temp(Not prime): "+temp); //output
// purpose
newmap.put(temp, "Not prime");
}
}
Set set = newmap.entrySet();
Iterator iterator = set.iterator();
// printing out values of the each element in hashmap(newmap)
while (iterator.hasNext()) {
Map.Entry mentry = (Map.Entry) iterator.next();
System.out.println(mentry.getValue());
}
}
}
#Jim Lewis and #Michael Markidis have already provided the right answers for how to fix the bugs in this code.
I think to satisfy the requirements of the coding exercise you're doing, you'll need to output the results in the same order as the input numbers, so you'll want to collect the results into something with an order, rather than the (unordered) HashMap. Here's some slightly cleaned up code that uses an ArrayList instead (though frankly you should be able to just print out the results as you go):
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] inputs = new int[n]; // read number of testcases
for (int i = 0; i < n; i++) { // add input to my int array
inputs[i] = sc.nextInt();
}
List<String> results = new ArrayList<>();
for (int number : inputs) {
boolean isprime = true;
if (number == 1) { // hardcode for input 1
isprime = false;
} else {
for (int j = 2; j <= number / 2; j++) { // checking whether the input is prime or not
if (number % j == 0) {
isprime = false;
continue;
}
}
}
results.add(isprime ? "Prime" : "Not prime");
}
for (String result : results) {
System.out.println(result);
}
}
}
A HashMap doesn't have predictable order. However, you can print out the keys associated with each value like this:
for (Iterator<Integer> iter = newmap.keySet().iterator(); iter.hasNext(); )
{
int key = iter.next();
System.out.println(key + "=" + newmap.get(key));
}
This will output:
5=Prime
7=Prime
12=Not prime
EDIT: As suggested by MeBigFatGuy and smarx, an entrySet() iterator is better while used with an enhanced loop.
Example:
for (Map.Entry mentry : newmap.entrySet())
{
System.out.format("%s = %s\n", mentry.getKey(), mentry.getValue());
}
You are assuming that the Iterator over the entrySet of your Hashmap will return the entries in the same order you added them. A plain old HashMap guarantees nothing of the sort (no pun intended). Try using a LinkedHashMap instead.
While checking for 1 , update in map before continue;
Inside Inner for loop ,
Use break instead of continue
Some tweaks
- If your array doesn't have duplicates then dont waste memory in
hashmaps. Loop on array.
coding exercises has large input to be read , use bufferedreader instead for faster throughput
use generics properly
I am trying to make a script that will take a set of Words (custom class), organize them alphabetically into an array by their text value (this part works). From here I was going to count how many terms ahead of it are the same as it, and that will be the frequency for all those similar terms. Then it continues to do this till each element in the array has been assigned a frequency. From here it re sorts the elements back into their original position provided a pre stored variable that holds their original element order. Here is the code:
public void setFrequencies() {
List<Word> dupeWordList;
dupeWordList = new ArrayList<>(wordList);
dupeWordList.removeAll(Collections.singleton(null));
Collections.sort(dupeWordList, (Word one, Word other) -> one.getValue().compareTo(other.getValue()));
int count;
int currElement;
for(currElement = 0; currElement < dupeWordList.size(); currElement++) {
count = 1;
Word tempWord = dupeWordList.get(currElement);
tempWord.setFrequency(count);
if(currElement+1 <= dupeWordList.size() - 1) {
Word nextWord = dupeWordList.get(currElement+1);
while(tempWord.getValue().equals(nextWord.getValue())) {
count++;
currElement++;
tempWord.setFrequency(count);
for(int e = 0; e < count - 1; e++) {
Word middleWord = new Word();
if(currElement-count+2+e < dupeWordList.size() - 1) {
middleWord = dupeWordList.get(currElement-count+2+e);
}
middleWord.setFrequency(count);
}
if(currElement+1 <= dupeWordList.size() - 1) {
nextWord = dupeWordList.get(currElement+1);
} else {
break;
}
}
break;
}
}
List<Word> reSortedList = new ArrayList<>(wordList);
Word fillWord = new Word();
fillWord.setFrequency(0);
fillWord.setValue(null);
Collections.fill(reSortedList, fillWord);
for(int i = 0; i < dupeWordList.size(); i++) {
Word word = dupeWordList.get(i);
int wordOrder = word.getOrigOrder();
reSortedList.set(wordOrder, word);
}
System.out.println(Arrays.toString(DebugFreq(reSortedList)));
setWordList(reSortedList);
}
public int[] DebugFreq(List<Word> rSL) {
int[] results = new int[rSL.size()];
for(int i=0; i < results.length; i++) {
results[i] = rSL.get(i).getFrequency();
}
return results;
}
As you can see I set up a little debug method at the bottom. When I run this method is shows that every word was given a frequency of 1. I cant see the issue in my code, nor does it get any errors. Keep in mind I have had it display the sorted dupeWordList and it does correctly alphabetize and their are consecutive duplicate elements in it so this should not be happening.
So If I understand you correctly.. below code would be your solution.
Okay You have a list which is having a strings (terms or words) which are sorted in alphabetical Order.
// Okay the below list is already sorted in alphabetical order.
List<String> dupeWordList = new ArrayList<>(wordList);
To count the Frequency of words in your list, Map<String, Integer> might help you as below.
//Take a Map with Integer as value and String as key.
Map<String,Integer> result = new HashMap<String,Integer> ();
//Iterate your List
for(String s : dupeWordList)
{
if(map.containskey(s))
{
map.put(s,map.get(s)+1);
// Please consider casting here.
}else
{
map.put(s,1);
}
}
Okay now we have a map which is having the frequency of your words or terms as value in your map.
Hope it helps.
This was my online interview question, and I already submitted the answer. However, the compilation was terminated due to time so I just submitted. Could I get feedback from you? Thanks in advance.
Problem:
Given N numbers , [N<=10^5] we need to count the total pairs of numbers that have a difference of K
Input Format:
1st line contains N & K (integers).
2nd line contains N numbers of the set. All the N numbers are assured to be distinct.
Output Format:
One integer saying the no of pairs of numbers that have a diff K.
Sample Input #00:
5 2
1 5 3 4 2
Sample Output #00:
3
My code:
import java.io.*
import java.util.*;
public class DiffNumbers {
public static void main(String[] args) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line1 = in.readLine();
String line2 = in.readLine();
int n = Integer.parseInt(line1.split(" ")[0]);
int diff = Integer.parseInt(line1.split(" ")[1]);
Hashtable table = new Hashtable();
int[] arr = new int[n];
for(in i=0; i<n; i++) {
arr[i] = Integer.parseInt(line2.split(" ")[i]);
table.put(Integer.parseInt(line2.split(" ")[i]));
}
int count = 0;
for(in i=0; i<n; i++) {
if(table.containsKey(arr[i]+diff) {
count++;
}
}
system.out.println(count);
}
}
Using HashMap/Table needs extra space. If you want to avoid it you can do it this way
1) Sort the array
2) initialize outputCount as 0
3) Let there be two pointers. "first" start with 0 and "Other" pointer start with 1.
4)
while(arr[other]-arr[first] <requiredDifference)
other ++;
if(arr[other]-arr[first] == requiredDifference)
outputCount++;
else // no match for arr[first]
first++;
5)
return outputCount;
explanation :-
When difference is more than requiredDifference you stop moving ahead "other" poiner. So there is no match for arr[first]. So move ahead first counter. Now do the same logic for new arr[first]. This time you will continue checking from current position of "other" as array is sorted; lower number will not have required match.
public static void main(String[] args) throws Exception{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line1 = in.readLine();
String line2 = in.readLine();
int diff = Integer.parseInt(line1.split(" ")[1]);
Map<Integer, Object> nMap = new HashMap<Integer, Object>();
Map<Integer, Boolean> uMap = new HashMap<Integer, Boolean>();
Map<Integer, Boolean> lMap = new HashMap<Integer, Boolean>();
String[] numbers = line2.split(" ");
//init maps
for(String number : numbers){
Integer intValue = Integer.valueOf(number);
nMap.put(intValue, new Object()); //original set, N
uMap.put(intValue + diff, false); //upper-bound map
lMap.put(intValue - diff, false); //lower-bound map
}
int count = 0;
for(Integer nKey : nMap.keySet()){
//Do if the lower-bound of n exists in N and if n hasn't used as an upper-bound?
if(nMap.get(nKey - diff) != null && !uMap.get(nKey)){
count++;
//Mark the lower-bound as used.
lMap.put(nKey - diff, true);
}
//Do if the upper-bound of n exists in N and if n hasn't used as an lower-bound?
if(nMap.get(nKey + diff) != null && !lMap.get(nKey)){
count++;
//Mark the upper-bound as used.
uMap.put(nKey + diff, true);
}
}
System.out.println(count);
}
There's not much reason to store the integers in both an array and a hashtable. We can modify your code to do the all of the work in a single for loop.
for(int i=0; i<n; i++) {
int j = Integer.parseInt(line2.split(" ")[i]) //probably not how I would go about this
table.put(j);
if(table.containsKey(j+diff)) {
count++;
}
if(table.containsKey(j-diff)) {
count++;
}
}