how many characters are same in two string - java

After several searches that did not result, I have come to ask your help. I have a slight problem. I have two string:
String values = "acceikoquy";
String values2 = "achips";
I would get the same number of characters so here:
3
Do you have any idea how to do that?
My code :
String values = "acceikoquy";
String values2 = "achips";
int test = StringUtils.countMatches(values, values2);
System.out.println(test);

Something like this:
public static int sameCharsCount(String left, String right, boolean countDuplicates) {
if ((null == left) || (null == right))
return 0;
HashMap<Character, Integer> occurence = new HashMap<Character, Integer>();
for (int i = 0; i < left.length(); ++i) {
Character ch = left.charAt(i);
if (!occurence.containsKey(ch))
occurence.put(ch, 1);
else
occurence.put(ch, occurence.get(ch) + 1);
}
int result = 0;
for (int i = 0; i < right.length(); ++i) {
Character ch = right.charAt(i);
if (occurence.containsKey(ch)) {
result += 1;
if (!countDuplicates || occurence.get(ch) <= 1)
occurence.remove(ch);
else
occurence.put(ch, occurence.get(ch) - 1);
}
}
return result;
}
...
String values = "acceikoquy";
String values2 = "achips";
//TODO: put true or false if you want to count duplicates or not
int result = sameCharsCount(values, values2, true); // <- returns 3
int withDups = sameCharsCount("aaba", "caa", true); // <- 2 (two 'a' are shared)
int noDups = sameCharsCount("aaba", "caa", false); // <- 1 (just a fact, 'a' is shared)

You can try in this way
String values = "acxa";
String values2 = "abada";
int count=0;
List<Character> list=new ArrayList<>();
List<Character> list1=new ArrayList<>();
for(int i=0;i<values2.length();i++){
list.add(values2.charAt(i));
}
for(int i=0;i<values.length();i++){
list1.add(values.charAt(i));
}
ListIterator<Character> listIterator=list.listIterator();
while (listIterator.hasNext()){
char val=listIterator.next();
if(list1.toString().contains(""+val)){
count++;
listIterator.remove();
int index=list1.indexOf(val);
list1.remove(index);
}
}
System.out.println(count);
Out put:
2

Related

How to find duplicate character in string without using in built methods of String Class in java methods like length(),toCharArray(),charAt()?

How to find the duplicate character in the string without using inbuilt methods of String Class in java methods like length(), toCharArray(), charAt()?
Ask in an interview please give me solutions on this
input : abcdeddrb
output: db
You can do this with reflection:
public String findDuplicateChars(String input)
throws NoSuchFieldException, IllegalAccessException {
Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
char[] chars = (char[]) valueField.get(input);
List<Character> duplicatedChars = new ArrayList<>();
for (int i = 0; i < chars.length; i++) {
char aChar = chars[i];
for (int j = i + 1; j < chars.length; j++) {
char anotherChar = chars[j];
if (aChar == anotherChar) {
if (!duplicatedChars.contains(aChar)) {
duplicatedChars.add(aChar);
}
}
}
}
char[] charArray = new char[duplicatedChars.size()];
for (int i = 0; i < duplicatedChars.size(); i++) {
charArray[i] = duplicatedChars.get(i);
}
return new String(charArray);
}
Since b is the first duplicated char the output will be bd though, not db.
Maybe the point of the interview's question was to check if you know reflection or to check if you would try to quit the interview with an answer like "Why should anyone do that?".
Maybe change String to CharSequence and use its methods as charAt
CharSequence cs = s;
My guess here is that your interviewer wanted you to use a map to keep track of which characters have been seen and which have not.
String input = "abcdeddrb";
Map<Character, Integer> map = new HashMap<>();
for (int i=0; i < input.length(); ++i) {
Integer count = map.get(input.charAt(i));
map.put(input.charAt(i), count == null ? 1 : count + 1);
}
map.entrySet().stream()
.filter(entry -> entry.getValue() > 1)
.forEach(System.out::println);
b=2
d=3
public static void main(String[] args) {
String testStr = "abcdeddrb";
Map<Character, Integer> map = new HashMap<>();
Map<Character, Integer> duplicateStrMap = null;
int count = 0;
int i = 0;
CharacterIterator it = new StringCharacterIterator(testStr);
// Loop Characters in a String.
for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
if(map.containsKey(c)){
if(duplicateStrMap == null){
duplicateStrMap = new HashMap<>();
}
duplicateStrMap.put(c, count);
count++;
}
else{
map.put(c, ++i);
}
}
// Print Results
if(duplicateStrMap != null){
System.out.println("Total Duplcates Found :"+duplicateStrMap.size());
Iterator<Character> itr = duplicateStrMap.keySet().iterator();
System.out.println("Duplicate Characters :");
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output:
Total Duplcates Found :2 Duplicate Characters : b d

Common characters in n strings

I m trying to make a function that prints the number of characters common in given n strings. (note that characters may be used multiple times)
I am struggling to perform this operation on n strings However I did it for 2 strings without any characters repeated more than once.
I have posted my code.
public class CommonChars {
public static void main(String[] args) {
String str1 = "abcd";
String str2 = "bcde";
StringBuffer sb = new StringBuffer();
// get unique chars from both the strings
str1 = uniqueChar(str1);
str2 = uniqueChar(str2);
int count = 0;
int str1Len = str1.length();
int str2Len = str2.length();
for (int i = 0; i < str1Len; i++) {
for (int j = 0; j < str2Len; j++) {
// found match stop the loop
if (str1.charAt(i) == str2.charAt(j)) {
count++;
sb.append(str1.charAt(i));
break;
}
}
}
System.out.println("Common Chars Count : " + count + "\nCommon Chars :" +
sb.toString());
}
public static String uniqueChar(String inputString) {
String outputstr="",temp="";
for(int i=0;i<inputstr.length();i++) {
if(temp.indexOf(inputstr.charAt(i))<0) {
temp+=inputstr.charAt(i);
}
}
System.out.println("completed");
return temp;
}
}
3
abcaa
bcbd
bgc
3
their may be chances that a same character can be present multiple times in
a string and you are not supposed to eliminate those characters instead
check the no. of times they are repeated in other strings. for eg
3
abacd
aaxyz
aatre
output should be 2
it will be better if i get solution in java
You have to convert all Strings to Set of Characters and retain all from the first one. Below solution has many places which could be optimised but you should understand general idea.
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static void main(String[] args) {
List<String> input = Arrays.asList("jonas", "ton", "bonny");
System.out.println(findCommonCharsFor(input));
}
public static Collection<Character> findCommonCharsFor(List<String> strings) {
if (strings == null || strings.isEmpty()) {
return Collections.emptyList();
}
Set<Character> commonChars = convertStringToSetOfChars(strings.get(0));
strings.stream().skip(1).forEach(s -> commonChars.retainAll(convertStringToSetOfChars(s)));
return commonChars;
}
private static Set<Character> convertStringToSetOfChars(String string) {
if (string == null || string.isEmpty()) {
return Collections.emptySet();
}
Set<Character> set = new HashSet<>(string.length() + 10);
for (char c : string.toCharArray()) {
set.add(c);
}
return set;
}
}
Above code prints:
[n, o]
A better strategy for your problem is to use this method:
public int[] countChars(String s){
int[] count = new int[26];
for(char c: s.toCharArray()){
count[c-'a']++;
}
return count;
}
Now if you have n Strings (String[] strings) just find the min of common chars for each letter:
int[][] result = new int[n][26]
for(int i = 0; i<strings.length;i++){
result[i] = countChars(s);
}
// now if you sum the min common chars for each counter you are ready
int commonChars = 0;
for(int i = 0; i< 26;i++){
int min = result[0][i];
for(int i = 1; i< n;i++){
if(min>result[j][i]){
min = result[j][i];
}
}
commonChars+=min;
}
Get list of characters for each string:
List<Character> chars1 = s1.chars() // list of chars for first string
.mapToObj(c -> (char) c)
.collect(Collectors.toList());
List<Character> chars2 = s2.chars() // list of chars for second string
.mapToObj(c -> (char) c)
.collect(Collectors.toList());
Then use retainAll method:
chars1.retainAll(chars2); // retain in chars1 only the chars that are contained in the chars2 also
System.out.println(chars1.size());
If you want to get number of unique chars just use Collectors.toSet() instead of toList()
Well if one goes for hashing:
public static int uniqueChars(String first, String second) {
boolean[] hash = new boolean[26];
int count = 0;
//reduce first string to unique letters
for (char c : first.toLowerCase().toCharArray()) {
hash[c - 'a'] = true;
}
//reduce to unique letters in both strings
for(char c : second.toLowerCase().toCharArray()){
if(hash[c - 'a']){
count++;
hash[c - 'a'] = false;
}
}
return count;
}
This is using bucketsort which gives a n+m complexity but needs the 26 buckets(the "hash" array).
Imo one can't do better in regards of complexity as you need to look at every letter at least once which sums up to n+m.
Insitu the best you can get is imho somewhere in the range of O(n log(n) ) .
Your aproach is somewhere in the league of O(n²)
Addon: if you need the characters as a String(in essence the same as above with count is the length of the String returned):
public static String uniqueChars(String first, String second) {
boolean[] hash = new boolean[26];
StringBuilder sb = new StringBuilder();
for (char c : first.toLowerCase().toCharArray()) {
hash[c - 'a'] = true;
}
for(char c : second.toLowerCase().toCharArray()){
if(hash[c - 'a']){
sb.append(c);
hash[c - 'a'] = false;
}
}
return sb.toString();
}
public static String getCommonCharacters(String... words) {
if (words == null || words.length == 0)
return "";
Set<Character> unique = words[0].chars().mapToObj(ch -> (char)ch).collect(Collectors.toCollection(TreeSet::new));
for (String word : words)
unique.retainAll(word.chars().mapToObj(ch -> (char)ch).collect(Collectors.toSet()));
return unique.stream().map(String::valueOf).collect(Collectors.joining());
}
Another variant without creating temporary Set and using Character.
public static String getCommonCharacters(String... words) {
if (words == null || words.length == 0)
return "";
int[] arr = new int[26];
boolean[] tmp = new boolean[26];
for (String word : words) {
Arrays.fill(tmp, false);
for (int i = 0; i < word.length(); i++) {
int pos = Character.toLowerCase(word.charAt(i)) - 'a';
if (tmp[pos])
continue;
tmp[pos] = true;
arr[pos]++;
}
}
StringBuilder buf = new StringBuilder(26);
for (int i = 0; i < arr.length; i++)
if (arr[i] == words.length)
buf.append((char)('a' + i));
return buf.toString();
}
Demo
System.out.println(getCommonCharacters("abcd", "bcde")); // bcd

sub arraylist's size isn't correct

After hard searchig I still haven't found the proper answer for my question and there is it:
I have to write a java program that enters an array of strings and finds in it the largest sequence of equal elements. If several sequences have the same longest length, the program should print the leftmost of them. The input strings are given as a single line, separated by a space.
For example:
if the input is: "hi yes yes yes bye",
the output should be: "yes yes yes".
And there is my source code:
public static void main(String[] args) {
System.out.println("Please enter a sequence of strings separated by spaces:");
Scanner inputStringScanner = new Scanner(System.in);
String[] strings = inputStringScanner.nextLine().split(" ");
System.out.println(String.join(" ", strings));
ArrayList<ArrayList<String>> stringsSequencesCollection = new ArrayList<ArrayList<String>>();
ArrayList<String> stringsSequences = new ArrayList<String>();
stringsSequences.add(strings[0]);
for (int i = 1; i < strings.length; i++) {
if(strings[i].equals(strings[i - 1])) {
stringsSequences.add(strings[i]);
} else {
System.out.println(stringsSequences + " " + stringsSequences.size());
stringsSequencesCollection.add(stringsSequences);
stringsSequences.clear();
stringsSequences.add(strings[i]);
//ystem.out.println("\n" + stringsSequences);
}
if(i == strings.length - 1) {
stringsSequencesCollection.add(stringsSequences);
stringsSequences.clear();
System.out.println(stringsSequences + " " + stringsSequences.size());
}
}
System.out.println(stringsSequencesCollection.size());
System.out.println(stringsSequencesCollection.get(2).size());
System.out.println();
int maximalStringSequence = Integer.MIN_VALUE;
int index = 0;
ArrayList<String> currentStringSequence = new ArrayList<String>();
for (int i = 0; i < stringsSequencesCollection.size(); i++) {
currentStringSequence = stringsSequencesCollection.get(i);
System.out.println(stringsSequencesCollection.get(i).size());
if (stringsSequencesCollection.get(i).size() > maximalStringSequence) {
maximalStringSequence = stringsSequencesCollection.get(i).size();
index = i;
//System.out.println("\n" + index);
}
}
System.out.println(String.join(" ", stringsSequencesCollection.get(index)));
I think it should be work correct but there is a problem - the sub array list's count isn't correct: All the sub arrayList's size is 1 and for this reason the output is not correct. I don't understand what is the reason for this. If anybody can help me to fix the code I will be gratefull!
I think it is fairly straight forward just keep track of a max sequence length as you go through the array building sequences.
String input = "hi yes yes yes bye";
String sa[] = input.split(" ");
int maxseqlen = 1;
String last_sample = sa[0];
String longest_seq = last_sample;
int seqlen = 1;
String seq = last_sample;
for (int i = 1; i < sa.length; i++) {
String sample = sa[i];
if (sample.equals(last_sample)) {
seqlen++;
seq += " " + sample;
if (seqlen > maxseqlen) {
longest_seq = seq;
maxseqlen = seqlen;
}
} else {
seqlen = 1;
seq = sample;
}
last_sample = sample;
}
System.out.println("longest_seq = " + longest_seq);
Lots of issues.
First of all, when dealing with the last string of the list you are not actually printing it before clearing it. Should be:
if(i == strings.length - 1)
//...
System.out.println(stringsSequences + " " + stringsSequences.size());
stringsSequences.clear();
This is the error in the output.
Secondly, and most importantly, when you do stringsSequencesCollection.add you are adding an OBJECT, i.e. a reference to the collection. When after you do stringsSequences.clear(), you empty the collection you just added too (this is because it's not making a copy, but keeping a reference!). You can verify this by printing stringsSequencesCollection after the first loop finishes: it will contain 3 empty lists.
So how do we do this? First of all, we need a more appropriate data structure. We are going to use a Map that, for each string, contains the length of its longest sequence. Since we want to manage ties too, we'll also have another map that for each string stores the leftmost ending position of the longest sequence:
Map<String, Integer> lengths= new HashMap<>();
Map<String, Integer> indexes= new HashMap<>();
String[] split = input.split(" ");
lengths.put(split[0], 1);
indexes.put(split[0], 0);
int currentLength = 1;
int maxLength = 1;
for (int i = 1; i<split.length; i++) {
String s = split[i];
if (s.equals(split[i-1])) {
currentLength++;
}
else {
currentLength = 1;
}
int oldLength = lengths.getOrDefault(s, 0);
if (currentLength > oldLength) {
lengths.put(s, currentLength);
indexes.put(s, i);
}
maxLength = Math.max(maxLength, currentLength);
}
//At this point, youll have in lengths a map from string -> maxSeqLengt, and in indexes a map from string -> indexes for the leftmost ending index of the longest sequence. Now we need to reason on those!
Now we can just scan for the strings with the longest sequences:
//Find all strings with equal maximal length sequences
Set<String> longestStrings = new HashSet<>();
for (Map.Entry<String, Integer> e: lengths.entrySet()) {
if (e.value == maxLength) {
longestStrings.add(e.key);
}
}
//Of those, search the one with minimal index
int minIndex = input.length();
String bestString = null;
for (String s: longestStrings) {
int index = indexes.get(s);
if (index < minIndex) {
bestString = s;
}
}
System.out.println(bestString);
Below code results in output as you expected:
public static void main(String[] args) {
System.out.println("Please enter a sequence of strings separated by spaces:");
Scanner inputStringScanner = new Scanner(System.in);
String[] strings = inputStringScanner.nextLine().split(" ");
System.out.println(String.join(" ", strings));
List <ArrayList<String>> stringsSequencesCollection = new ArrayList<ArrayList<String>>();
List <String> stringsSequences = new ArrayList<String>();
//stringsSequences.add(strings[0]);
boolean flag = false;
for (int i = 1; i < strings.length; i++) {
if(strings[i].equals(strings[i - 1])) {
if(flag == false){
stringsSequences.add(strings[i]);
flag= true;
}
stringsSequences.add(strings[i]);
}
}
int maximalStringSequence = Integer.MIN_VALUE;
int index = 0;
List <String> currentStringSequence = new ArrayList<String>();
for (int i = 0; i < stringsSequencesCollection.size(); i++) {
currentStringSequence = stringsSequencesCollection.get(i);
System.out.println(stringsSequencesCollection.get(i).size());
if (stringsSequencesCollection.get(i).size() > maximalStringSequence) {
maximalStringSequence = stringsSequencesCollection.get(i).size();
index = i;
//System.out.println("\n" + index);
}
}
System.out.println(stringsSequences.toString());

Change a certain occurrence of a letter in a string

Say I have a string, and I want to change the second "a" in that string to an "e".
String elephant = "elaphant";
I tried using String.replace(), but that replaces all the a's in the string, returning "elephent".
elephant.replace("a", "e");
Is there any loop or method I can use to accomplish this? Thank you all.
You could convert it to a char array, switch out the desired letter, then convert it back to String?
String elephant = "elaphant";
int index = -1;
int count = 0;
while(count < 2) {
index = elephant.indexOf("a", index+1);
count++;
}
if(index >= 0 && index < elephant.length()) {
char[] tmp = elephant.toCharArray();
tmp[index] = "e";
elephant = new String(tmp);
}
Or if you prefer StringBuilder
StringBuilder sbTemp = new StringBuilder(elephant);
sbTmp = sbTmp.replace(index, index+1, "e");
elephant = sbTmp.toString();
You need to get the index of the first occurrence of a letter.
Try using the indexOf method.
int myIndex = elephant.indexOf('a');
Once you have the index, use StringBuilder to replace the value. Something like:
StringBuilder sb = new StringBuilder(elephant);
sb[index] = myIndex;
elephant = sb.ToString();
Code:
String elephant = "elaphant";
//convert the string to array of string
String[] sp = elephant.split("");
int countA = 0;
boolean seenTwice = false;
String result = "";
for (int i = 0; i < sp.length; i++) {
//count number of times that a has been seen
if (sp[i].equals("a")) {
countA++;
}
// if a has been seen twice and flag seenTwice has not been see
if (countA == 2 && !seenTwice) {
result += "e";
seenTwice = true;
} else {
result += sp[i];
}
}
System.out.println(result);
Output:
elaphent

Sort integer array into decreasing order of frequency

I need to take a string from a jTextFrame then sort it into order of occurence and then print it out. eg. babablackbike return: bbbbaaakkceil
String word = (String)jTextField1.getText();
String indexes = "abcdefghijklmnopqrstuvwxyz";
int[] count = new int[indexes.length()];
for (int i = 0; i < word.length(); i++)
{
int index = indexes.indexOf(word.charAt(i));
if (index < 0)
continue;
count[index]++;
}
for (int j = 0; j < count.length; j++)
{
if (count[j] < 1)
continue;
char[] indiv = indexes.toCharArray();
for (int p = 0; p < count[j];p++)
{
jTextArea1.append(""+indiv[j]);
System.out.println(indiv[(j)] +"="+ count[j] + p);
}
}
You first need to get counts of each character in your input:
final String in = "babablackbike";
final Map<Character, Integer> counts = new HashMap<>();
final List<Character> inList = new ArrayList<>();
for (final char c : in.toCharArray()) {
Integer count = counts.get(c);
if (count == null) {
counts.put(c, 1);
} else {
counts.put(c, count + 1);
}
inList.add(c);
}
As Java is a bit peculiar with char[] versus Character[] - there is no way to sort primitives with a custom comparator due to generics not working with primitives - I also build a List<Character> at the same time.
Now we just need to sort the List<Character> using a custom Comparator and the information in the Map counts:
Collections.sort(inList, new Comparator<Character>() {
#Override
public int compare(final Character o1, final Character o2) {
int c = counts.get(o1).compareTo(counts.get(o2));
if (c != 0) {
return -c;
}
return o1.compareTo(o2);
}
});
So first we sort by the count of the character in the input (reverse order) and then we sort by the characters themselves.
Now we simply need to build the List back into a String:
final StringBuilder outBuilder = new StringBuilder();
for (final Character c : inList) {
outBuilder.append(c);
}
System.out.println(outBuilder.toString());
Output:
bbbbaaakkceil
I think that, the best solution it would be to create a HashMap like this
Map<Character, Integer> quantity = new HashMap<Character, Integer>();
Then, you can do a loop like this:
for (int i = 0; i < str.length() - 1; i++) {
char c = str.charAt(i);
// increment value of c in quantity map
}
After that, you can sort it by value and easily print.
Here is the general algorithm:
Map each character in the string to the number of times it appears in it.
Sort the map keys (characters) by decreasing order of their values (count).
Print each character according to the number of times it appears in the string.
And here is a coding example:
public void Print(String string)
{
HashMap<Character,Integer> hashMap = new HashMap<Character,Integer>();
TreeMap<Character,Integer> treeMap = new TreeMap<Character,Integer>(new ValueComparator(hashMap));
for (Character key : string.toCharArray())
{
Integer value = hashMap.get(key);
if (value == null)
hashMap.put(key,1);
else
hashMap.put(key,value+1);
}
treeMap.putAll(hashMap);
for (Character key : treeMap.keySet())
{
Integer value = hashMap.get(key);
for (Integer i=0; i<value; i++)
System.out.print(key);
}
}
private class ValueComparator implements Comparator<Character>
{
Map<Character,Integer> base;
public ValueComparator(Map<Character,Integer> base)
{
this.base = base;
}
public int compare(Character a,Character b)
{
if (base.get(a) >= base.get(b))
return -1;
else
return +1;
}
}

Categories