Given a problem that determines the output of the word, length of each word, and the number of times the word repeats, I have the following code capable to determine the word and length of each word below:
String sentence;
String charSentence;
String[] wordOutput;
private void analyzeWords(String s) {
String[] words = sentence.split(" ");
wordOutput = new String[words.length];
int[] repeats = new int[words.length];
// Increment a single repeat
for (int i = 0; i < words.length; i++) {
repeats[i] = 1;
// Increment when repeated.
for (int j = i + 1; j < words.length - 1; j++) {
if (words[i].equalsIgnoreCase(words[j])) {
repeats[i]++;
}
}
wordOutput[i] = words[i] + "\t" + words[i].length() + "\t" + repeats[i];
}
When I run the program, I get the following output:
Equal 5 2
Equal 5 1 <- This is a duplicate word and should not be here when it repeats.
Does anyone know where my problem is? Is it something relating that deals with my repeats array?
The first problem is that in the inner for loop you are looping from i+1 to length-1. You need to loop till length. Second you will need to determine if there are any occurrences of the word in the String, and if so use a continue statement. You can do:
outer:
for (int i = 0; i < words.length; i++) {
repeats[i] = 1;
for(int index = i-1; index >= 0; index--) {
if(words[i].equals(words[index])) {
continue outer;
}
}
...
}
However the problem with this is that there will be null values at the end of the list, as you specify an Array with the same length as the number of words. To solve this you can do:
wordOutput = Arrays.stream(wordOutput).filter(e-> e!= null).toArray(String[]::new);
Which will filter out the null values
Output:
(With the input String: "This is a String is a with a lot lot of this repeats repeats")
This 4 2
is 2 2
a 1 3
String 6 1
with 4 1
lot 3 2
of 2 1
this 4 1
repeats 7 2
Instead of incrementing count at all index store the count only in last occurence of word, in other case, have the count value of 0. at the end traverse the count array, if its greater than zero, print the value and its count
private void analyzeWords(String s) {
String[] words = sentence.split(" ");
wordOutput = new String[words.length];
int[] repeats = new int[words.length];
for (int i = 0; i < words.length; i++) {
int count =1;
int index = i;
for (int j = i + 1; j < words.length - 1; j++) {
if (words[i].equalsIgnoreCase(words[j])) {
count++;
index = j;
}
}
if(repeats[index]==0){
repeats[index]=count; // update repeat array only for last occurence of word
wordOutput[i] = words[i] + "\t" + words[i].length() + "\t" + repeats[index];
}
}
First, as GBlodgett mention you should check all left words for repeats, your current solution skips last word. Update second loop termination condition to j < words.length.
Second, if you want to print duplicates only once you need a condition in your solution. One of the example:
boolean[] duplicates = new boolean[words.length];
// Increment a single repeat
for (int i = 0; i < words.length; i++) {
repeats[i] = 1;
// Check for duplicates,
// If the word was not marked as duplicate
if (!duplicates[i]) {
// Increment when repeated.
for (int j = i + 1; j < words.length; j++) {
if (words[i].equalsIgnoreCase(words[j])) {
repeats[i]++;
duplicates[j] = true;
}
}
wordOutput[i] = words[i] + "\t" + words[i].length() + "\t" + repeats[i];
}
}
There is a Java 8+ solution, for example:
Map<String, Long> m = Arrays.stream(s.split(" ")).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Map will have pairs of word and it occurrences.
Related
I have string in java "naveen" i want output as "eennav". Please help me out in this. The idea is that the characters are to be ordered in order of frequency, and, where frequencies are the same, alphabetically.
Thanks
I have tried to find duplicates in the string , but am not able to get the required output .
String str="naveen";
int count =0;
char[] charr=str.toCharArray();
for(int i=0;i<charr.length;i++) {
//System.out.println(s[i]);
for(int j=i+1;j<charr.length;j++) {
if(charr[i]==(charr[j])) {
System.out.println(charr[i]);
}
Assuming the question is asking us to take a string containing only lower case letters and organize them by frequency of letters (high to low) and within that by alphabetical order, we can do it as below.
The strategy is first to make a pass through the characters of the input string and count the number of occurrences of each. Then we look through the counts for letters and find the largest. Working from the largest down to 1, we run through the alphabet for characters that occur that many times, and append that many of them to the result string.
There is a little bit of work involved here to convert back and forth from 'a' to 0 and 0 to 'a' and so on to 25 and 'z'.
This approach could be extended, but since the question didn't specify, I chose to make simplifying assumptions. I also did not work on optimizing, just getting it to work.
public class MyClass {
public static void main(String args[]) {
String str = "naveen"; //this string may change, but it is assumed to be all lower case letters by this implementation
int[] counts = new int[26]; //frequency count of letters a to z
for (int i = 0; i < 26; i++) {
counts[i] = 0; // intially 0 of any letter
}
char[] charr = str.toCharArray();
for (int i = 0; i < charr.length; i++) {
counts[(int)(charr[i]) - (int)('a')]++; // increment corresponding spot in counts array, spot 0 for 'a' through 25 for 'z'
}
int maxCount = counts[0]; // now find the most occurrences of any letter
for (int i = 1; i < counts.length; i++) {
if (counts[i] > maxCount) {
maxCount = counts[i];
}
}
String result = ""; // string to return
for (int j = maxCount; j > 0; j--) { // work down from most frequently occuring, within that alphabetically
for (int i = 0; i < 26; i++) {
if (counts[i] == j) {
//System.out.println("there are "+j+" of the letter "+(char)((int)('a'+i)));
for (int k = 0; k < j; k++) {
result = result + (char)((int)('a' + i));
}
};
}
}
System.out.println(result);
}
}
OK, i know this question was asked many times here, but i still don't get it, how to find the first repeated character in a string ?
I did something which was close, but it gave me all repeated characters instead of only the first one.
Here's what i did :
private static void stringChar(){
String s = "sababa";
int count = 0;
char c[] = s.toCharArray();
System.out.println("Duplicate characters are :");
for(int i = 0; i < s.length(); i++){
for(int j = i + 1; j < s.length(); j++){
if(c[i] == c[j]) {
System.out.println(c[j]);
count++;
break;
}
}
}
}
One quick and dirty (yet effective) approach which comes to mind is to maintain a map whose keys are the characters. In this case, we don't even need a formal map, because we can use an integer array which maps to the underlying ASCII values of the characters.
The basic idea here is to walk down the string, and check the array if we have seen it before. If so, then print that character and exit.
int[] nums = new int[128]; // assuming only basic ASCII characters
String str = "stuff";
for (int i=0; i < str.length(); ++i) {
int index = str.charAt(i);
if (nums[index] != 0) {
System.out.println("The first repeated character is: " + str.charAt(i));
break;
}
++nums[index];
}
Demo
You need to break the outer loop if you have already found the repeating character.
boolean found = false;
for(int i = 0; i < s.length(); i++){
for(int j = i + 1; j < s.length(); j++){
if(c[i] == c[j]) {
System.out.println(c[j]);
found = true;
break;
}
}
if (found) {
break;
}
}
If you want the count of it
int count = 0;
char repeatingChar = '0'; //dummy to overcome compiler warning
for(int i = 0; i < s.length(); i++){
for(int j = i + 1; j < s.length(); j++){
if(c[i] == c[j]) {
repeatingChar = c[j];
count++;
}
}
if (count > 0) {
System.out.println("Repeating char is " + repeatingChar + ". Occurred " + count + " times");
break;
}
}
The first repeated char is one you have seen before as you iterate the chars in the string. You can keep track of the first time you see a char with a Boolean array. The array is indexed with the char value. Java automatically "widens" char to int. So, for each char, check if it's been seen before and if not, mark that it has been seen.
String s = "sababa";
boolean[] seenChars = new boolean[Character.MAX_VALUE + 1]; // initialized to all false.
for (char c : s.toCharArray()) {
if (Character.isSurrogate(c)) throw new IllegalArgumentException("No first char seen before seeing a surrogate. This algorithm doesn't work for codepoints needing surrogates in UTF-16.");
if (seenChars[c]) {
System.out.println("First repeated char is: " + c);
break;
}
seenChars[c] = true;
}
You might notice that I've been saying char instead of character. Character is not a well-defined term. Java's text datatypes use the UTF-16 encoding of the Unicode character set. Some Unicode codepoints require two UTF-16 code units (char), which are sometimes called surrogate pairs. Since they are not all unique as individual chars, the algorithm doesn't work if they are present. For example, try String s = "sab🚲aba"; (You can also write it as "sab\uD83D\uDEB2aba".) The answer would be "a", again. But now try String s = "sab🚲🚶aba"; (You can also write it as "sab\uD83D\uDEB2\uD83D\uDEB6aba".) The answer should still be "a" but the algorithm would say "\uD83D" (which of course can't be displayed because it is only part of a codepoint).
Short and Simple >
void findFirstDupChar() {
String s = "google";
Integer dupIndex = s.length() - 1;
boolean isDuplicateExists = false;
Map<Character, Integer> map = new LinkedHashMap<>();
char[] words = s.toCharArray();
for (int i = 0; i < words.length; i++) {
Integer index = map.put(words[i], i);
if (index != null) {
if (index < dupIndex) {
dupIndex = index;
isDuplicateExists = true;
}
}
}
System.out.println(isDuplicateExists ? words[dupIndex] + ", index=" + dupIndex : "No duplicateds found");
}
This will print output as following >
g, index=0
I'm having trouble writing a method that takes a string and counts the number of times the first character (or really any character) appears. The code I've written is below, but for some reason keeps returning half the correct count when I run it. Any help would be appreciated, thanks.
public static void countOccurrences(String string1) {
int counter = 0;
char toCheck = string1.charAt(0);
char compareChar;
for (int i = 0; i < string1.length(); i++) {
compareChar = string1.charAt(i);
if (toCheck == compareChar) {
counter++;
}
i++;
}
System.out.println(toCheck + " appears " + counter + " times in string1.");
}
You're incrementing i twice in each iteration, so you are skipping half the characters:
for (int i = 0; i < string1.length(); i++) { // i is incremented here
compareChar = string1.charAt(i);
if (toCheck == compareChar){
counter++ ;
}
i++ ; // i is incremented again here - remove this line
}
i++ in for loop is incrementing the i value by 1, no need to increment inside th eloop
check Working of For loop here
public static void countOccurrences(String string1) {
int counter = 0;
char toCheck = string1.charAt(0);
char compareChar;
for (int i = 0; i < string1.length(); i++) {
compareChar = string1.charAt(i);
if (toCheck == compareChar){
counter++ ;
}
}
System.out.println(toCheck + " appears " + counter + " times in string1.");
}
Your immediate problem is that i++; happens twice per iteration.
An alternative approach is to use
s.length() - s.replace("x", "").length()
which gives you the number of times "x" appears in s. Arguably it's not the most efficient way, but it's clear.
Hi so I am supposed to count the number of unique elements after an array sort excluding duplicates but i'm getting the wrong output.
In in = new In(args[0]);
int[] whitelist = in.readAllInts();
Arrays.sort(whitelist);
int count = 0;
for (int i = 0; i < whitelist.length; i++) {
if (whitelist[i] == whitelist[count]) {
count++;
}
}
while (!StdIn.isEmpty()) {
int key = StdIn.readInt();
rank(key, whitelist);
}
System.out.println(count);
}
}
expected output: java InstrumentedBinarySearch tinyW.txt < tinyT.txt
65
got: 16
Did i count the number of duplicates or something?
int flag = 0;
int count = 0;
for (int i = 0; i < whitelist.length; i++) //Element to be checked for
{
for (int j=0; j< whitelist.length ; j++) //Loop that goes through the whole array
{
if (whitelist[i] == whitelist[j]) //checks if there are duplicates
{
flag++; // count
}
}
if( flag==1) //There should be only 1 instance of the element in the array and that is the element itself
{
System.out.println(whitelist[i]); //displays unique element
count++; // Keeps count
}
}
This algorithm counts how many different unique numbers there are in the array. A number appearing more than once will only count for 1. I am assuming this is what you mean, as opposed to "numbers which appear exactly once".
There is a more trivial way to do it, as proposed in another answer, but it requires a nested for-loop and therefore executes in quadratic complexity. My algorithm below attempts to solve the problem in linear time proportional to the array size.
int uniquesFound = 0;
// Assume that array is sorted, so duplicates would be next to another.
// If we find duplicates, such as 12223, we will only count its last instance (i.e. the last '2')
for (int i = 0; i < whitelist.length; i++) {
// If we are at the last element, we know we can count it
if (i != whitelist.length - 1) {
if (whitelist[i] != whitelist[i+1]) {
uniquesFound++;
}
else {
// Nothing! If they are the same, move to the next step element
}
} else {
uniquesFound++;
}
}
For instance, given the array:
{1,2,3} this will yield 3 because there are 3 unique numbers
{1,2,3,3,3,4,4,4,5} this will yield 5 because there are still 5 unique numbers
First let's take a look at your loop:
for (int i = 0; i < whitelist.length; i++) {
if (whitelist[i] == whitelist[count]) {
count++;
}
}
You should be comparing consecutive elements in the list, like whitelist[0] == whitelist[1]?, whitelist[1] == whitelist[2]?, whitelist[3] == whitelist[4]?, etc. Doing whitelist[i] == whitelist[count] makes no sense in this context.
Now you have two options:
a. Increment your counter when you find two consecutive elements that are equal and subtract the result from the total size of the array:
for (int i = 0; i < whitelist.length - 1; i++) {
if (whitelist[i] == whitelist[i + 1]) {
count++;
}
}
int result = whitelist.length - count;
b. Change the condition to count the transitions between consecutive elements that are not equal. Since you are counting the number of transitions, you need to add 1 to count in the end to get the number of unique elements in the array:
for (int i = 0; i < whitelist.length - 1; i++) {
if (whitelist[i] != whitelist[i + 1]) {
count++;
}
}
int result = count + 1;
Note that, in both cases, we loop only until whitelist.length - 1, so that whitelist[i + 1] does not go out of bounds.
my probem is i have two strings like durgaprasad and spandana . here i want to compare 1st string first cahr to the second string all characters if the first sting first char is matched then remove that character from first & second string also, and then display the string (all chars except removed char).
like
durgaprasad
spandana
1st string 1st char - d
compare to all chars in 2nd string-
founded---at position[4]--d
remove that char from 1st string & 2nd string
so we get-----
1st string :urgaprasad
2nd string :spanana
finally i want to get --
1st string--urgrd2nd string--nn
i have tried a lot but i have getting compare to above my code is like this
for(int i = 0; i < firstStr.length(); i++) {
System.out.println("char position :"+firstStr.charAt(i));
int k = 0;
for( int j = 0; j < secondStr.length(); j++) {
//System.out.println("second position :"+secondStr.charAt(j));
if ( ( firstStr.charAt(i) == secondStr.charAt(j) ) && ( k == 0 ) ) {
secondStr = secondStr.substring( 0 , j ).concat(secondStr.substring( j + 1 ) );<br />firstStr = firstStr.substring( 0 , i ).concat(firstStr.substring( i + 1 ) );
}
}
}
for my requirement what changes i have done here
Thanks
Something like...this?
public void RemoveCharacter(String s1, String s2) {
System.out.println("First string: " + s1 + "\nSecond string: " + s2);
for (int i = 0; i < s1.length(); i++) {
for (int j = 0; j < s2.length(); j++) {
if (s1.charAt(i) == s2.charAt(j)) {
RemoveCharacter(s1.substring(0, i) + s1.substring(i + 1), s2.substring(0, j) + s2.substring(j + 1);
return;
}
}
}
}
It pretty much has to be a recursive function if you want to continually strip characters, because removing characters screws up the for-loop iterations (although I suppose you could do i-- and j-- inside the if-statement).
Here's some code.
for(int i = 0; i < firstStr.length(); i++) {
System.out.println("char position :" + firstStr.charAt(i));
for(int j = 0; j < secondStr.length(); j++) {
//System.out.println("second position :" + secondStr.charAt(j));
if (firstStr.charAt(i) == secondStr.charAt(j)) {
firstStr = firstStr.substring(0, i) + firstStr.substring(i + 1);
secondStr = secondStr.substring(0, j) + secondStr.substring(j + 1);
}
}
}
Mostly your code was valid. You must remove the character from firstStr as well as secondStr to achieve the wanted result. Also, you can concat strings with just +.