String Occurrence According to the order - java

I have a Problem where i need to find the first occurrence of the char according to the order which they occur in the given String.
For Example :
I have a String "Unitedin" where the char "n" and "i" have a multiple occurrence in the String.
char n occurred at charAt(1,7)
char i occurred at charAt (2,6)
But the char "i" had occurred first before char "n".
I have Tried Something like this But i am not getting the required output.Can Anyone Help me please?
Note : Challenge is Not to use any type of List or Hashset or Hashmap
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
StringBuilder nodup = new StringBuilder();
StringBuilder dup = new StringBuilder();
System.out.println("Enter a string : ");
String instring = in.next();
for (int i = 0; i < instring.length(); i++) {
for (int j = i + 1; j < instring.length(); j++) {
if (instring.charAt(i) == instring.charAt(j)) {
nodup.append(instring.charAt(i));
} else {
dup.append(instring.charAt(i));
}
}
}
System.out.print(nodup.toString());
i am getting the OutPut as : ni . but the Required output is in.

The LinkedHashMap class works really well for your particular problem. You may iterate the character array from your input string, and then add the characters, along with their counts, as keys, into the LinkedHashMap. Since LinkedHashMap preserves insertion order, to get the output you want you need only iterate the map and print out all keys whose counts are greater than one. The order of the character keys will be fixed at the first occurrence of each letter.
String input = "Unitedin";
LinkedHashMap<Character, Integer> map = new LinkedHashMap<>();
for (char chr : input.toCharArray()) {
Integer count = map.get(chr);
map.put(chr, count == null ? 1 : count + 1);
}
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
if (entry.getValue() > 1) System.out.println(entry.getKey());
}
This prints:
n
i

If your objective is to view the first recurrence of a character, then this should do it. The order will be the order in which a repeated character is found in your string.
String input = "Unitedin";
Stringbuilder sb = new Stringbuilder();
Map<Character, Integer> map = new HashMap<>();
for (char chr : input.toCharArray()) {
Integer count = map.get(chr);
count = count != null ? count + 1 else 1;
map.put(chr, count);
if(count > 1) {
sb.append(chr);
}
}
System.out.println(sb.toString()); // Output: in
EDIT: I understand from your comment that you cannot use an instance of List, HashSet, or HashMap? Then is LinkedHashMap allowed? If not, then you'll need to recreate that functionality somehow.
You could map characters a-z and A-Z in an int array of 52 (26 + 26). Rather than insert the count into a map, you map the character to its appropriate spot in the array and update the count. Good luck!

Related

Comparing if a string's character exist in an array of characters

I want the user to input a string, then I want to check if each charachter in this string exists in an array of charachters I created. Even if it's not in the correct order.
The way I go about it is initialise the array of chars then through using the scanner have a String input from the user.
public static char[]aa={'A','C','D','E','F','G','H','I','K','L','M','N','P','Q','R','S','T','V','W','Y','U','O','B','J','Z','X'};
I created a function
private static void isValidSequence(String sequence, char[] k) {
outter :for (int j = 0; j < sequence.length(); j++) {
for (int i = 0; i < k.length; i++) {
if(sequence.charAt(j) == k[i]){
break;
} else {
System.out.println("invalid");
break outter;
}
}
}
}
What happens is that if for example the first letter of the the string doesn't match the first input of array it gives me an 'invalid' input. How can I go around that? and make it iterate through the whole array of characters before giving the invalid output.
An approach would be to sort your array, and then use the Binary Search Algorithm (BSA):
// sort the array once
Arrays.sort(aa);
// iterate over the input string
for(int i = 0, length = sequence.length(); i < length; i++) {
// the java implementation of the BSA returns negative numbers for not found elements
if(Arrays.binarySearch(aa, sequence.charAt(i)) < 0) {
// char was not found, break loop
return;
}
}
Note: If the array is not sorted / can not be sorted, then the BSA is useless and will produce undefined results.
Note 2: The BSA is faster (O(log n)) than simple iteration (O(n))
This can also be done as below :
char[]aa={'A','C','D','E','F','G','H','I','K','L','M','N','P','Q','R','S','T','V','W','Y','U','O','B','J','Z','X'};
String s = "aStrinG";
for (char c : s.toCharArray()) {
for (char c2 : aa) {
if (c2 == c) {
System.out.println("String char " + c + " exists in char array");
}
}
}
It produces :
String char S exists in char array
String char G exists in char array
Best way is to use SET instead of an Array. A set contains no duplicate elements and then simply you can use it using the method contains()
Using Java 9 (Unmodifiable Sets)
Set<Character> alphabetSet = Set.of('A', 'B', 'C');
//Another way
//Set<Character> alphabetSet = new HashSet<>(Arrays.asList('A', 'B', 'C'));
for(char c: sequence)
{
if(alphabetSet.contains(c)){
//do something
}
else{
//do something
}
}
Read more about Set:
https://docs.oracle.com/javase/7/docs/api/java/util/Set.html
To directly answer your question:
Solution 1:
Use continue instead of break this will print "invalid" each time a character is not in k.
Solution 2:
You can use a counter and increment it every time you have a character not in k, then outside the loop you will have visibility on how many invalid characters you have.
Solution 3:
If you want even more detail you can have a list of characters and add each invalid character to this list. This will give you visibility on exactly what characters are invalid.
I am not sure what you are trying to do so I don't know which method is better for you, you can also use an altogether approach using streams for example.
If you start using the Collection provided, you could use a Set to do your checks.
First, convert the array into the Set :
char[] array = "abcdefghijklmnopqrstuvwxyz".toCharArray();
Set<Character> setAllowed = new TreeSet<>();
for(char c : array){
setAllowed.add(c);
}
Then, you just have to iterate and check for each character. I would add another Set to retrieve every characters not allowed, giving a better output.
Set<Character> setError = new TreeSet<>();
for(char c : s.toCharArray()){
if(setAllowed.contains(c)){
setError.add(c);
}
}
Test :
public static void main(String[] args) {
String s = "foobar123";
char[] array = "abcdefghijklmnopqrstuvwxyz".toCharArray();
//INIT
Set<Character> setAllowed = new TreeSet<>();
Set<Character> setError = new TreeSet<>();
for(char c : array){
setAllowed .add(c);
}
//RESEARCH
for(char c : s.toCharArray()){
if(setAllowed.contains(c)){
setError.add(c);
}
}
//OUTPUT
System.out.println(setError);
}
[1, 2, 3]

Count of distinct duplicated characters in Java

I've written code to find the amount of duplicated characters in a string input. However after reading the specification, I realise this isn't what is being asked. Yes, I need to count the duplicated characters, but not the amount of that particular character, I need the amount of all characters being duplicated.
I've given an input and output to help explain better. I don't think I'm doing a good job.
Input:
"abcdea" => "a" is duplicated =>
Output:
1
Input:
"abcdeae" => "a" and "e" is duplicated =>
Output:
2
Input:
"abcdeaed" => "a", "d" and "e" is duplicated =>
Output:
3
I've put my code below. Can anyone help adjust my code please?
public static int duplicatesCount(String text)
{
Map<Character,Integer> map = new HashMap<Character,Integer>();
char[] carray = text.toCharArray();
for (char c : carray)
{
if (map.containsKey(c))
{
map.put(c, map.get(c) +1);
}
else
{
map.put(c, 1);
}
}
Set <Character> setChar = map.keySet();
int returnC = 1;
for (Character c : setChar)
{
if (map.get(c) > 1)
{
returnC = map.get(c);
}
}
return returnC;
A better way to do this is to sort the string and then iterate through it. If the previous character = the current character, you increase the duplicate number and don't increment it again util you see the character change.
This requires no extra storage (e.g. the hash map).
This can also be used to count the number of duplicates of each letter with a minor change :).
At the end of your snippet...
int returnC = 0;
for (Character c : setChar)
{
if (map.get(c) > 1)
{
returnC ++; //for each which has more than one instance
}
}
return returnC;
Just count everytime you come across a character that has a value greater than 1 in your hashmap
int returnC = 0;
for (Character c : setChar)
{
if (map.get(c) > 1)
returnC++;
}
Or you can do it while you're creating your hashmap like this
Map<Character,Integer> map = new HashMap<Character,Integer>();
char[] carray = text.toCharArray();
Set <Character> setChar = new Set<Character>(); //initialize the set up here
for (char c : carray)
{
if (map.containsKey(c))
{
map.put(c, map.get(c) +1);
setChar.add(c); //just add to set when a char already exists
}
else
{
map.put(c, 1);
}
}
return setChar.size(); //then simply return the size of the set
Here is another approach - without using Map or sorting algorithm.
public static int duplicatesCount(String text) {
int cnt = 0;
while (text.length() > 1) {
char firstLetter = text.charAt(0);
if (text.lastIndexOf(firstLetter) > 0) {
cnt++;
text = text.replaceAll(("" + firstLetter), "");
} else {
text = text.substring(1, text.length());
}
}
return cnt;
}
The basic idea is to go through a string, char-by-char and check does the character exist somewhere in the string ( if (text.lastIndexOf(firstLetter) > 0)). If it exists increment cnt and then remove all occurrences of the character in the string.
Otherwise, just remove the fist character (text = text.substring(1, text.length());)
You could use String methods
int count = 0;
String s = "abcdeabc";
while(s.length() > 0) {
String c = s.substring(0, 1);
if(s.lastIndexOf(c) != 0) {
count++;
}
s = s.replaceAll(c, "");
}
In your current code you are returning the value not the count.
For Eg:
If your input was "abcdea", then returnC holds the value 2 which is the
number of times the key a has repeated.
If your input was "abcdabeb" where a is repeated twice and b is repeated
thrice. Your output will be 3, as returnC will be holding the value for the key
b.
You can modify your code like this.
Set <Character> setChar = map.keySet();
int returnC = 0;
for (Character c : setChar) {
if (map.get(c) > 1) {
returnC++;
}
}
return returnC;
Also we can user String Buffer class to to create another string of duplicate charracters-- and then we can display it--
public static void main(String arghya[])
{
String name="ARGHYA MUKHERJEE";
StringBuffer duplicate=new StringBuffer();
Set<Character> charlist=new HashSet<Character>();
for(int i=0;i<name.length();i++) {
Character c=name.charAt(i);
if(charlist.contains(c))
{
duplicate.append(c);
//System.out.println(c+ " is repeatitive character in the string");
}
else {
charlist.add(c);
}
}
System.out.print("Duplicate characters which has appeared are as follows: "+duplicate);
}

Counting letter frequencies and print letter:count, but not duplicates in java strings

public static void main(String[] args) {
TextIO.putln("Text?");
String line = TextIO.getln();
line = line.toLowerCase();
char[] arr = line.toCharArray();
for(int i = 0; i < line.length(); i++){
if(Character.isLetter(arr[i])){
int count;
int j;
for(j = 0,count = 0; j < line.length(); j++){;
if( arr[i] == arr[j]){
count++;
}
}
System.out.printf("%c:%d\n", arr[i],count);
}
}
}
If I enter the string josh it prints out
j:1
o:1
s:1
h:1
If I enter joshh it prints
j:1
o:1
s:1
h:2
h:2
but I want
j:1
o:1
s:1
h:2
How do I, for any string with duplicates, only print out the unique letter and how many times it occurs total? I was thinking of maybe implementing a for loop that just checks for each letter and increment it such as
for ('a' : string)
total++
and then increment the 'a' by one, so the next loop would check how many occurrences of b, then c, and so on.
How much java do you know? Is this an assignment? Have you been through data structures? Two options:
Sort and then count
Use a map (dictionary if you come from Python as your username suggests), increment in the first pass and then iterate over the keys to print the values
From what I can tell, it looks like the issue lies in the for loop you are using while printing.
What happens is that you evaluate for every single character in the string and print. Once you evaluate for the first h in josh, your program then moves on to the second h, evaluates again, and as a result, prints h and its count again.
You could try a data structure such as a dictionary which accounts for unique elements. Or, as you count how many times letters appear, you can have another array that holds letters already seen. If you check against this array before counting how many times a letter appears you can see if the letter has already been counted, if so you can just skip this character and move on to the next. It isnt the most elegant solution, but it would work
public static void main(String[] args) {
TextIO.putln("Text?");
String line = TextIO.getln();
line = line.toLowerCase();
// char[] arr = line.toCharArray();
Map<Character, Integer> occurrences=new LinkedHashMap<Character, Integer>();
for(int i = 0; i < line.length(); i++){
int ch=line.charAt(i);
if(Character.isLetter(ch)){
if(occurrences.containsKey(ch)) {
occurrences.put(ch, occurrences.get(ch)+1); // increment
}
else {
occurrences.put(ch, 1);
}
}
}
for(char ch : occurrences.keySet()) {
System.out.print(ch+":"+occurrences.get(ch)+";");
}
System.out.println();
}
Try this.
Map<Character, Integer> map = new LinkedHashMap<>();
for (char c : line.toCharArray())
if (Character.isLetter(c))
map.compute(c, (k, v) -> v == null ? 1 : v + 1);
for (Entry<Character, Integer> e : map.entrySet())
System.out.printf("%c:%d\n", e.getKey(), e.getValue());

Find if a string is unique or not

I want to use hashtable to find unique characters as it seems more efficient to me so for example, hello in hashtable would be=> {h:1,e:1,l:2,o:1} & since value is more than 1 then string isnt unique. I know I can do ascii way of counting unique characters but I want to implement the hashtable way.
Please note, I do not want a regex implementation.
static void findHashUnique(String str)
{
Hashtable<Character, Integer> ht = new Hashtable<Character, Integer>();
for(int i=0;i<str.length();i++)
{
int cnt=1;
if(!ht.containsKey(str.charAt(i)))
{
ht.put(str.charAt(i), cnt);
}
}
System.out.print(ht);
}
I am stuck at the part of how will I first initialize the hashtable & also check if value exists then increment. In case of 'l' it will increment to 2 instead of being 1 since the key is the same.
Also Is this solution efficient?
Here's my approach.
String string = "hello";
Hashtable<Character, Integer> map = new Hashtable<>();
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (map.containsKey(c)) {
map.put(c, map.get(c) + 1);
} else {
map.put(c, 1);
}
}
System.out.println(map);
Output: {e=1, o=1, l=2, h=1}
Well, I don't know exactly what character encodings you will be examining, but if you are constraining yourself to only ASCII characters, you can use a simple array of 128 elements.
public static String uniqueLetters(String s) {
// storage for ascii characters
char[] letters = new char[128];
// mark counts of all letters
for(int i = 0; i < s.length(); i++) {
letters[ (int)s.charAt(i) ]++;
}
// find unique letters
String uniques = "";
for(int i = 0; i < letters.length; i++) {
if ( letters[i] == 1 ) {
uniques += Character.toString( (char)letters[i] );
}
}
return uniques;
}
To "fix" your code, use a HashSet<Character>, which uses a Hashtable internally, but you don't have to know or worry about that. Just keep adding the chars to the set and you'll be left with a unique set of chars at the end.
To achieve the intention more easily:
String uniqueChars = str.replaceAll("(.)(?=.*\\1)", "");

Java Isomorphic Code

I am kind of stuck on this java problem involving returning the number of isomorphic pairs in an array of Strings. The code I have written keeps returning incorrect number of isomorphic word pairs.
The definition of isomorphic words is given as follows: Two words are called isomorphic if the letters in one word can be remapped to get the second word. Remapping a letter means replacing all occurrences of it with another letter. The ordering of the letters remains unchanged. No two letters may map to the same letter, but a letter may map to itself.
For example, the words "abca" and "zbxz" are isomorphic because we can map 'a' to 'z', 'b' to 'b' and 'c' to 'x'.
I am not inlcuding the getMap method which I call in the function. The getMap method take any string as input, and returns a map where the keys are the letters in the string, and the corresponding values are the number of times the letter appears in the string.
public class IsomorphicWords {
public int countPairs(String[] words) {
Set <String> pairs = new HashSet<String>();
for (String word:words){
Map noOfOccurencesOfEachLetter= getMap(word);
ArrayList<Integer> valuesFromFirstWord = new ArrayList<Integer>(noOfOccurencesOfEachLetter.values());
Collections.sort(valuesFromFirstWord);
java.util.List<String> list = new ArrayList<String>(Arrays.asList(words));
list.remove(word);
String[] oneLessWord = list.toArray(new String[words.length-1]);
for(String secondWord:oneLessWord){
Map secondNoOfOccurencesOfEachLetter = getMap(secondWord);
ArrayList<Integer> valuesFromSecondWord = new ArrayList<Integer>(secondNoOfOccurencesOfEachLetter.values());
Collections.sort(valuesFromSecondWord);
if (valuesFromFirstWord.equals(valuesFromSecondWord)){
pairs.add(""+word+","+secondWord+"");
}
else{
continue;
}
}
}
return pairs.size()/2;
public Map getMap(String word){
HashMap<String,Integer> noOfOccurencesOfEachLetter= new HashMap<String,Integer>();
for (int i=0;i<word.length();i++){
char letter = word.charAt(i);
String letterInDictionary= Character.toString(letter);
if (noOfOccurencesOfEachLetter.containsKey(letterInDictionary)==true){
int count= noOfOccurencesOfEachLetter.get(letterInDictionary);
noOfOccurencesOfEachLetter.put(letterInDictionary, count+1);
}
else{
noOfOccurencesOfEachLetter.put(letterInDictionary, 1);
}
}
return noOfOccurencesOfEachLetter;
}
}
I'd really appreciate any feedback you can give me on this code.
Thanks,
Junaid
The reason why it gives the incorrect answer probably comes from you take the letter count, and don't look at the position that they have in both words. The first solution that comes up in me, is to create a new array in which you translate the letters to the index of the first occurrence of this letter for each word. For example: "abcd" would be "0123", "abca" would be "0120" and "fhjf" would be "0120" as well. Then you can simply compare the results. I hope this helps...
public int countPairs(String[] words) {
int isomorphicPairs = 0;
for (int i = 0; i < words.length; i++) {
for (int j = i+1; j < words.length; j++) {
if (words[i].length() == words[j].length()) {
String tmp = new String(words[j]);
for (int k = 0; k < tmp.length(); k++)
tmp = tmp.replaceAll("" + tmp.charAt(k), "" + words[i].charAt(k));
if (words[i].equals(tmp)) isomorphicPairs++;
}
}
}
return isomorphicPairs;
}

Categories

Resources