I have this code below to count the frequency of a string in an ArrayList
public static int count (ArrayList<String> c, String str){
int num = 0;
num = Collections.frequency(c, str);
return num;
}
What I have to do now is to improve this so that the function takes in ArrayList<ArrayList<String>> and can loop through the set of Arraylists and Count the occurrences of the String. Any ideas would be great.
You need to use two nested for loops, looping through each list with the first one and looping through each element of the current list with the second, i.e.:
int count = 0;
for (ArrayList<String> list : lists) {
for (String string : list) {
if (list.equals("something")) count++;
}
}
To compute the frequency you'll also need to count the total number of elements in all the lists, but I'll leave that to you as it should be straightforward now.
Dude, you described the algorithm, it won't get simpler than that. Just code the thing.
Keep in mind that Collections::frequency is misnamed (IMHO), it should be count.
In java 8 use the stream
public void findOccurenceInLists(ArrayList<ArrayList<String>> lists, String myStr) throws Exception {
int occurence = 0;
lists.stream().forEach((list) -> {
occurence += list.stream().filter((str) -> str.equals(myStr)).count();
});
System.out.println(occurence + " occurence found");
}
Related
I am taking a course to prepare for coding interviews and how it works is I try a problem then the solution is presented.
Question:
Given a string, find the length of the longest substring, which has all distinct characters.
Example:
Input: String="aabccbb"
Output: 3
Explanation: The longest substring with distinct characters is "abc".
I was wondering if there is any reason to use a HashMap and not an ArrayList on this problem? I will show both solutions and I was wondering if mine is wrong for any reason or if it is inefficient?
My solution works and the output matches (3,2,3). That's why I am wondering if I am doing anything wrong because their solution seems so much more complex than needed?
My Solution:
import java.util.*;
class NoRepeatSubstring {
public static int findLength(String str) {
// TODO: Write your code here
List<Character> charList = new ArrayList<Character>();
int maxLength = 0;
for(int windowEnd = 0; windowEnd < str.length(); windowEnd++) {
while(charList.contains(str.charAt(windowEnd))) {
charList.remove(0);
}
charList.add(str.charAt(windowEnd));
if(charList.size() > maxLength) {
maxLength = charList.size();
}
}
return maxLength;
}
public static void main(String[] args) {
System.out.println("Length of the longest substring: " + NoRepeatSubstring.findLength("aabccbb"));
System.out.println("Length of the longest substring: " + NoRepeatSubstring.findLength("abbbb"));
System.out.println("Length of the longest substring: " + NoRepeatSubstring.findLength("abccde"));
}
}
Their Solution:
import java.util.*;
class NoRepeatSubstring {
public static int findLength(String str) {
int windowStart = 0, maxLength = 0;
Map<Character, Integer> charIndexMap = new HashMap<>();
// try to extend the range [windowStart, windowEnd]
for (int windowEnd = 0; windowEnd < str.length(); windowEnd++) {
char rightChar = str.charAt(windowEnd);
// if the map already contains the 'rightChar', shrink the window from the beginning so that
// we have only one occurrence of 'rightChar'
if (charIndexMap.containsKey(rightChar)) {
// this is tricky; in the current window, we will not have any 'rightChar' after its previous index
// and if 'windowStart' is already ahead of the last index of 'rightChar', we'll keep 'windowStart'
windowStart = Math.max(windowStart, charIndexMap.get(rightChar) + 1);
}
charIndexMap.put(rightChar, windowEnd); // insert the 'rightChar' into the map
maxLength = Math.max(maxLength, windowEnd - windowStart + 1); // remember the maximum length so far
}
return maxLength;
}
public static void main(String[] args) {
System.out.println("Length of the longest substring: " + NoRepeatSubstring.findLength("aabccbb"));
System.out.println("Length of the longest substring: " + NoRepeatSubstring.findLength("abbbb"));
System.out.println("Length of the longest substring: " + NoRepeatSubstring.findLength("abccde"));
}
}
charList.contains(str.charAt(windowEnd)) is O(n) while charIndexMap.containsKey(rightChar) is (usually) O(1).
charList.contains goes through the whole list to check if the character is in the list.
charIndexMap.containsKey hashes the character/key, which is constant in time.
(It would be even faster to use an array of booleans with a fixed size of 2^8 (=the number of possible characters) and use the character as index into the array. That would be guaranteed to be O(1) and would also be faster with small strings since no time is wasted on computing hashes.)
ArrayList's contains method is O(N) but of HashMap is mostly O(1). Infact you dont even need to use a HashMap here , even HashSet will do.
So I basically have an array that looks like this:
BG6001;1193;M;63;B+
BG6001;1124;M;41;C
BG6001;1121;F;FA;FA
BG6001;1143;M;26;FA
BG6001;1157;F;74;A
And what I've been trying to do is to count how many times the letter "M" appears in it, and add it into a counter
Any ideas?
What I have tried so far:
for (int i=0; i<name.length(); i++) {
if (name.charAt(i)=='M' ) counter++;
}
System.out.println("the string contains " + count + " times the letter M")
You should probably use a foreach loop. Try implementing something like this:
int counter=0;
String[][] array = something;
for(String[] subArray : array)
for(String string : subArray)
if(string.toLowerCase().equals("m"))
counter++;
//Counter has the value of the amount of 'm's in the array
#mike fischer please check the below code whoich gives you the count of "M" in an Array.
public class Arraycount {
public static void main(String args[]){
String[] a=new String[5];
a[0]="BG6001;1193;M;63;B+";
a[1]="BG6001;1124;M;41;C";
a[2]="BG6001;1121;F;FA;FA";
a[3]="BG6001;1143;M;26;FA";
a[4]="BG6001;1157;F;74;A";
int count=0;
for(int i=0;i<=a.length-1;i++){
for(int j=0;j<=a[i].length()-1;j++){
char c=a[i].charAt(j);
if(c=='M'){
count++;
}
}
}
System.out.println("Number of M present in an array is "+count);
}
}
My answer is very similar to 7H3_H4CK3R's answer with some variation. Specifically, if a particular letter (in this case, "M") could appear anywhere in the string, you can do the following (and I apologize for using C# rather than Java syntax here, I'm not sitting in front of a Java compiler, but hopefully the differences won't be too difficult to follow):
private static int Count(string[][] data, char letterToFind)
{
int count = 0;
// Loop over each array
foreach (string[] array in data)
{
// Each array is a collection of strings
foreach (string str in array)
{
// Loop through the characters in each string
for (int i = 0; i < str.Length; i++)
{
if (str[i] == letterToFind)
{
count++;
}
}
}
}
return count;
}
Alternatively, if you're looking for something where the entire string is "M" 7H3_H4CK3R's answer should do the trick.
I have two arraylists and the second one is a subset of the first.
I want to know the initial and final position in the first arraylist of elements in the subset (in my example the position in arrayList of: uno, due, tre)
How to modify this code?
import java.util.ArrayList;
public class ConfrontaArrayList {
public static void main(String[] args)
{
ArrayList<String> arrayList = new ArrayList<String>();
ArrayList<String> subSetArrayList = new ArrayList<String>();
arrayList.add("inizio");
arrayList.add("stringa");
arrayList.add("uno");
arrayList.add("due");
arrayList.add("tre");
arrayList.add("fine");
arrayList.add("stringa");
subSetArrayList.add("uno");
subSetArrayList.add("due");
subSetArrayList.add("tre");
System.out.print("Elementi di arrayList: ");
for (String stringa : arrayList) System.out.print(stringa + " ");
System.out.print("\nElementi di subSetArrayList: ");
for (String stringa : subSetArrayList) System.out.print(stringa + " ");
}
}
java.util.Collections.indexOfSubList() method will return the index of the sub list:
int startIdx = Collections.indexOfSubList(arrayList, subSetArrayList);
if (-1 != startIdx)
{
int endIdx = startIdx + subSetArrayList.size() - 1;
}
If you can't do the whole problem break it down into smaller steps that you can do:
How do you tell if two elements match?
Given 1, how do you tell if two equal-length lists match?
Given 2, how do you tell if a list matches at a given index in a longer list?
Given 3, how can you answer your problem?
The simplest answer is of course to iterate over the arraylist and do a String.equals() to find the index.
Use the indexOf method of ArrayList.
for(String item : subSetArrayList)
{
int index = arrayList.indexOf(item);
}
On 2nd thought, if SubsetArrayList items are in same sequence and in contigous order. you can do as following:
int startIndex = arrayList.indexOf(subSetArrayList.get(0));
int endIndex = startIndex + subSetArrayList.size() - 1;
I want to create a Java method, which accepts an inputArray = Object[n][], where n can be any integer, and outputs a list of possible n-size combinations between all values of the n subarrays. Below is an example:
Input Array: (where Object=String and n=3)
String[] subarrayA = {"A0","A1","A2"};
String[] subarrayB = {"B0","B1"};
String[] subarrayC = {"C0","C1","C2","C3"};
String[3][] inputArray = {subarrayA, subarrayB, subarrayC};
Desired Output:
{A0,B0,C0},{A0,B0,C1},{A0,B0,C2},{A0,B0,C3},
{A0,B1,C0},{A0,B1,C1},{A0,B1,C2},{A0,B1,C3},
{A1,B0,C0},{A1,B0,C1},{A0,B0,C2},{A1,B0,C3},
{A1,B1,C0},{A1,B1,C1},{A1,B1,C2},{A1,B1,C3},
{A2,B0,C0},{A2,B0,C1},{A2,B0,C2},{A2,B0,C3},
{A2,B1,C0},{A2,B1,C1},{A2,B1,C2},{A2,B1,C3}
Obviously, I cannot have a fixed nested-loop inside my method since I do not know n in advance. So, I am guessing the only way to solve it would be through a recursive method? Any recommendations?
P.S: I am aware of the simple combination-related posts on the website.
This should solve your problem.
public static void permute(String array[][], int index, ArrayList<String> output){
if(index == array.length){
System.out.println(output.toString());
}
else{
for(int i=0 ; i<array[index].length ; i++){
output.add(array[index][i]);
permute(array,index+1,output);
output.remove(output.size() - 1);
}
}
}
In a recent interview I was asked to write the below program.
Find out the character whose frequency is minimum in the given String ?
So I tried by iterating through the string by using charAt and storing the character as key in a HashMap and the number of occurences as its value.
Now Again I have to iterate on the Map to find the lowest element.
Is there a more efficient way to do it as obviously the above one is too intensive i guess.
Update and Another Solution
After some thought process and answers I think the best time that this can be is O(n).
In the first iteration we will have to iterate through the String character by character and then store their frequency in an Array at the specific position(character is an int) and same time have two temporary variables which maintain the least count and the corresponding character.So when I go to the next character and store its frequency in arr[char] = arr[char]+1;At the same time I will check if the temp varible has a value greater than this value,if yes then the temp varible will be this value and also the char will be this one.In this way i suppose we dont need a second iteration to find the smallest and also no sorting is required I guess
.... Wat say ? Or any more solutions
I'd use an array rather than a hash map. If we're limited to ascii, that's just 256 entries; if we're using Unicode, 64k. Either way not an impossible size. Besides that, I don't see how you could improve on your approach. I'm trying to think of some clever trick to make it more efficient but I can't come up with any.
Seems to me the answer is almost always going to be a whole list of characters: all of those that are used zero times.
Update
This is probably clost to the most efficient it could be in Java. For convenience, I'm assuming we're using plain Ascii.
public List<Character> rarest(String s)
{
int[] freq=new int[256];
for (int p=s.length()-1;p>=0;--p)
{
char c=s.charAt(p);
if (c>255)
throw new UnexpectedDataException("Wasn't expecting that");
++freq[c];
}
int min=Integer.MAX_VALUE;
for (int x=freq.length-1;x>=0;--x)
{
// I'm assuming we don't want chars with frequency of zero
if (freq[x]>0 && min>freq[x])
min=freq[x];
}
List<Character> rares=new ArrayList<Character>();
for (int x=freq.length-1;x>=0;--x)
{
if (freq[x]==min)
rares.add((char)x);
}
return rares;
}
Any effort to keep the list sorted by frequency as you go is going to be way more inefficient, because it will have to re-sort every time you examine one character.
Any attempt to sort the list of frequencies at all is going to be more inefficient, as sorting the whole list is clearly going to be slower than just picking the smallest value.
Sorting the string and then counting is going to be slower because the sort will be more expensive than the count.
Technically, it would be faster to create a simple array at the end rather than an ArrayList, but the ArrayList makes slightly more readable code.
There may be a way to do it faster, but I suspect this is close to the optimum solution. I'd certainly be interested to see if someone has a better idea.
I think your approach is in theory the most efficient (O(n)). However in practice it needs quite a lot of memory, and is probably very slow.
It is possibly more efficient (at least it uses less memory) to convert the string to a char array, sort the array, and then calculate the frequencies using a simple loop. However, in theory it is less efficient (O(n log n)) because of sorting (unless you use a more efficient sort algorithm).
Test case:
import java.util.Arrays;
public class Test {
public static void main(String... args) throws Exception {
// System.out.println(getLowFrequencyChar("x"));
// System.out.println(getLowFrequencyChar("bab"));
// System.out.println(getLowFrequencyChar("babaa"));
for (int i = 0; i < 5; i++) {
long start = System.currentTimeMillis();
for (int j = 0; j < 1000000; j++) {
getLowFrequencyChar("long start = System.currentTimeMillis();");
}
System.out.println(System.currentTimeMillis() - start);
}
}
private static char getLowFrequencyChar(String string) {
int len = string.length();
if (len == 0) {
return 0;
} else if (len == 1) {
return string.charAt(0);
}
char[] chars = string.toCharArray();
Arrays.sort(chars);
int low = Integer.MAX_VALUE, f = 1;
char last = chars[0], x = 0;
for (int i = 1; i < len; i++) {
char c = chars[i];
if (c != last) {
if (f < low) {
if (f == 1) {
return last;
}
low = f;
x = last;
}
last = c;
f = 1;
} else {
f++;
}
}
if (f < low) {
x = last;
}
return (char) x;
}
}
The process of finding frequency of characters in a String is very easy.
For answer see my code.
import java.io.*;
public class frequency_of_char
{
public static void main(String args[])throws IOException
{
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
int ci,i,j,k,l;l=0;
String str,str1;
char c,ch;
System.out.println("Enter your String");
str=in.readLine();
i=str.length();
for(c='A';c<='z';c++)
{
k=0;
for(j=0;j<i;j++)
{
ch=str.charAt(j);
if(ch==c)
k++;
}
if(k>0)
System.out.println("The character "+c+" has occured for "+k+" times");
}
}
}
I'd do it the following way as it involves the fewest lines of code:
character you wish to want to know frequency of: "_"
String "this_is_a_test"
String testStr = "this_is_a_test";
String[] parts = testStr.split("_"); //note you need to use regular expressions here
int freq = parts.length -1;
You may find weird things happen if the string starts or ends with the character in question, but I'll leave it to you to test for that.
Having to iterate through the HashMap is not necessarily bad. That will only be O(h) where h is the HashMap's length--the number of unique characters--which in this case will always be less than or equal to n. For the example "aaabbc", h = 3 for the three unique characters. But, since h is strictly less than the number of possible characters: 255, it is constant. So, your big-oh will be O(n+h) which is actually O(n) since h is constant. I don't know of any algorithm that could get a better big-oh, you could try to have a bunch of java specific optimizations, but that said here is a simple algorithm I wrote that finds the char with the lowest frequency. It returns "c" from the input "aaabbc".
import java.util.HashMap;
import java.util.Map;
public class StackOverflowQuestion {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("" + findLowestFrequency("aaabbc"));
}
public static char findLowestFrequency(String input) {
Map<Character, Integer> map = new HashMap<Character, Integer>();
for (char c : input.toCharArray())
if (map.containsKey(c))
map.put(c, map.get(c) + 1);
else
map.put(c, 0);
char rarest = map.keySet().iterator().next();
for (char c : map.keySet())
if (map.get(c) < map.get(rarest))
rarest = c;
return rarest;
}
}