Java - Counting how many characters show up in another string - java

I am comparing two strings, in Java, to see how many characters from the first string show up in the second string. The following is some expectations:
matchingChars("AC", "BA") → 1
matchingChars("ABBA", "B") → 2
matchingChars("B", "ABBA") → 1
My approach is as follows:
public int matchingChars(String str1, String str2) {
int count = 0;
for (int a = 0; a < str1.length(); a++)
{
for (int b = 0; b < str2.length(); b++)
{ char str1Char = str1.charAt(a);
char str2Char = str2.charAt(b);
if (str1Char == str2Char)
{ count++;
str1 = str1.replace(str1Char, '0');
}
}
}
return count;
}
I know my approach is not the best, but I think it should do it. However, for
matchingChars("ABBA", "B") → 2
My code yields "1" instead of "2". Does anyone have any suggestion or advice? Thank you very much.

Assuming that comparing "AABBB" with "AAAABBBCCC" should return 15 (2*3 + 3*3 + 0*3) then:
For each string make a Map from the character of the string to the count of characters.
Compute the intersection of the keysets for the two maps.
For each element in the keyset accumulate the product of the values. Print the result.
This is linear in the size of the two strings.

Is it ok to supply working code on homework problems?
public long testStringCount() {
String a = "AABBBCCC";
String b = "AAABBBDDDDD";
Map<Character,Integer> aMap = mapIt(a);
Map<Character,Integer> bMap = mapIt(b);
Set<Character> chars = Sets.newHashSet(aMap.keySet());
chars.addAll(bMap.keySet());
long result = 0;
for (Character c : chars) {
Integer ac = aMap.get(c);
Integer bc = bMap.get(c);
if (null != ac && null != bc) {
result += ac*bc;
}
}
return result;
}
private Map<Character, Integer> mapIt(String a) {
Map<Character,Integer> result = Maps.newHashMap();
for (int i = 0; i < a.length(); i++) {
Character c = a.charAt(i);
Integer x = result.get(c);
if (null == x) {
x = 0;
}
x++;
result.put(c, x);
}
return result;
}

Clearly you have to make sure you only count unique characters from string 1. You're double-counting B because you're counting B's twice, once for each occurrence in string 1.

Well your code is only showing 1 because of this line:
str1 = str1.replace(str1Char, '0');
That's turning "ABBA" into "A00A" - so the second B doesn't get seen.
Perhaps you should turn the second string into a HashSet<Character> instead... then you could just use something like:
int count = 0;
for (int i = 0; i < str1.length; i++)
{
if (otherSet.contains(str1.charAt(i))
{
count++;
}
}
It's not clear what result you want to get from "ABBA" / "CBCB" - if it's 2 (because there are 2 Bs) then the above approach will work. If it's 4 (because each of the 2 Bs in the first string matches 2 Bs in the second string) then all you need to do is get rid of your replace call.
EDIT: With the clarifications, it sounds like you could just do this:
for (int a = 0; a < str1.length(); a++)
{
for (int b = 0; b < str2.length(); b++)
{
if (str1.charAt(a) == str2.charAt(b))
{
count++;
// Terminate the inner loop which is iterating over str2,
// and move on to the next character in str1
break;
}
}
}

Your solution works, but is quadratic. If all characters are below 256, then you can do something like this:
int matching(String s1, String s2) {
int[] count1 = frequencies(s1);
int[] count2 = frequencies(s2);
sum = 0;
for(int i = 0; i< 256; i++) {
sum += count1[i]*count2[i] != 0 ? Math.max(count1[i], count2[i]) : 0;
}
return sum;
}
int[] frequencies(String s) {
int[] ret = new int[256];
for(char c : s) {
int[c]+=1;
}
}
Otherwise, you'll need a multiset.

Related

How to compare without getting negative value when char is a space

Beginner here, We were assigned an assignment to find common consonants in two different strings. This code works perfectly if there is no space in the input but in this assignment we are taking inputs from our user and they are first and last names. If there is no space I get correct value of common characters but when there is a space in between first and last names it will give me an index out of bounds error because the space makes it a negative number. Any help would be nice thank you.
public static int commonCharacters(String string1, String string2) {
final int alphabetLength = 26;
int count = 0;
int[] counting1 = new int[alphabetLength];
int[] counting2 = new int[alphabetLength];
Arrays.fill(counting1, 0);
Arrays.fill(counting2, 0);
for (char c : string1.toCharArray()) {
c = Character.toLowerCase(c);
counting1[c - 'a']++;
}
for (char c : string2.toCharArray()) {
c = Character.toLowerCase(c);
counting2[c - 'a']++;
}
for(int i = 0; i < alphabetLength; i++) {
System.out.printf(String.valueOf(counting1[i]),counting2[i]);
count += Math.min(counting1[i], counting2[i]);
}
return count == 0 ? 1 :count;
}
}
you can trim space at the end of string string1 = string1.trim();
Here is some changes to your code. You just need if statement to check if the character is an alphabet. You do not need Arrays.fill because in Java array values are initialized to zero.
You wrote the assignment is about calculating consonants but your code calculates all common alphabets.
public static int commonCharacters(String string1, String string2) {
final int alphabetLength = 26;
int count = 0;
string1 = string1.toLowerCase();
string2 = string2.toLowerCase();
int[] counting1 = new int[alphabetLength];
int[] counting2 = new int[alphabetLength];
for (char c : string1.toCharArray()) {
if (c < 'a' || c > 'z') {
continue;
}
counting1[c - 'a']++;
}
for (char c : string2.toCharArray()) {
if (c < 'a' || c > 'z') {
continue;
}
counting2[c - 'a']++;
}
for(int i = 0; i < alphabetLength; i++) {
System.out.printf("%c %d %d%n", 'a' + i, counting1[i], counting2[i]);
count += Math.min(counting1[i], counting2[i]);
}
return count;
}

Given 2 strings, a and b, return the number of the positions where they contain the same length 2 substring

So here is my code to the above question. I am curious to know why the code doesn't work in all scenarios such as:
System.out.println(stringMatch("aabbccdd", "abbbxxd")); // Should be 1, but was 3
System.out.println(stringMatch("aaxxaaxx", "iaxxai")); // Should be 3, but was 5
System.out.println(stringMatch("iaxxai", "aaxxaaxx")); // Should be 3, but was 5
public int stringMatch(String a, String b) {
int counter = 0;
for (int i = 0; i < a.length() - 1; i++) {
for (int j = 0; j < b.length() - 1; j++) {
String aSub = a.substring(i, i + 2);
String bSub = b.substring(j, j + 2);
if (aSub.equals(bSub)) {
counter++;
}
}
}
return counter;
}
As Ashu mentioned, your program is actually calculating the number of strings which are the same of length two.
Take the first example you mentioned..
aabbccdd, abbbxxd
So your for loops are structured in a way where the 'aa' substring is being compared with each two letter substring in the second string 'abbbxxd'
In the end you have ab matching with ab, bb matching with bb, bb with bb again,
(since you have 3 b's in the second string) and therefore you get 3 as the output, when really it should be 1, since only one bb is matched to the same position (third and fourth letters)
The question asks you to put two Strings next to each other and check on how many positions they have the same set of two characters (be careful that they can overlop). In other words:
aabbccdd aaxxaaxx iaxxai
abbbxxd iaxxai aaxxaaxx
--^^---- (1) -^^^^--- (3) -^^^^--- (3)
(bb) (ax, xx, xa) (ax, xx, xa)
As you can hopefully see, you need only one loop to do this, since you're always comparing the same indices of String a and String b. But your code has 2 loops. What is does is check if any two characters of String a are anywhere in String b:
for string "aabbccdd":
Iteration i1: Iteration i2: Iteration i3: Iteration i4: etc...
abbbxxd abbbxxd abbbxxd abbbxxd
aa (0) ab (1) bbb (2) bc (0)
You need to get rid of the first loop and then fix your loop to run until the 2 before the end of the shortest String so you don't get an ArrayIndexOutOfBoundsException:
public int stringMatch(String a, String b) {
int counter = 0;
for(int i = 0; ((i < a.length() - 2) && (i < b.length() -2)); i++){
String aSub = a.substring(i, i + 2);
String bSub = b.substring(i, i + 2);
if(aSub.equals(bSub)){
counter++;
}
}
return counter;
}
Thanks Faaiz Haque for spotting the error in my for statement! Both statements must be true for the loop to keep running, not either.
One error is < ?.length() - 2 as the iteration is for i+2 < length().
public static int stringMatch(String a, String b) {
int counter = 0;
for (int i = 0; i < a.length() - 1; i++) {
for (int j = 0; j < b.length() - 1; j++) {
String aSub = a.substring(i, i + 2);
String bSub = b.substring(j, j + 2);
if (aSub.equals(bSub)) {
System.out.println(aSub);
counter++;
}
}
}
return counter;
}
public static void main(String[] args) {
System.out.print(stringMatch("aabbccdd", "abbbxxd"));
System.out.println("****");
System.out.println(stringMatch("aaxxaaxx", "iaxxai"));
System.out.println("****");
System.out.println(stringMatch("iaxxai", "aaxxaaxx"));
}
Use the above code to generate the substring matches. The output generated is following:
ab
bb
bb
3
****
ax
xx
xa
ax
xx
5
****
ax
ax
xx
xx
xa
5
Which is, in turn, a correct output as per your code. If you want a unique count for the matched substrings, you can try to insert substrings in a set and return the size of the set as the output of your function.
Firstly you should find greater string :
String tempA = "";
String tempB = "";
if (a.length() > b.length()){
tempA = a;
tempB = b;
}else{
tempA = b;
tempB = a;
}
Then you need control some special cases such as when i equals aTemp.length()-1 or j equals bTemp.length()-1.In this cases aTemp.substring(i, i + 2); and bTemp.substring(j, j + 2); statements occur errors.
i should iterate until aTemp.length()-2
j should iterate until bTemp.length()-2
You need to store finded position to avoid duplicate counting (I did is by using ArrayList)
For this example : stringMatch("iaxxai", "aaxxaaxx")
The answer must be 3 :
ax : iaxxai aaxxaaxx
xx : iaxxai aaxxaaxx
xa : iaxxai aaxxaaxx
public static int stringMatch(String a, String b) {
ArrayList<String> list = new ArrayList<String>();
int counter = 0;
String tempA = "";
String tempB = "";
if (a.length() > b.length()){//to find the bigger string
tempA = a;
tempB = b;
}else{
tempA = b;
tempB = a;
}
for(int i = 0; i < tempA.length() - 2; i++){
for(int j = 0; j < tempB.length() - 2; j++){
String aSub;
String bSub;
if (i == tempA.length() - 2){//when i == tempA.length() - 2 you need to take the substring(i to end of the string)
aSub = tempA.substring(i);
}else{
aSub = tempA.substring(i, i + 2);
}
if (j == tempB.length() - 2){
bSub = tempB.substring(j);
}else{
bSub = tempB.substring(j, j + 2);
}
if(aSub.equals(bSub) && list.indexOf(aSub) == -1 ){//list.indexOf(aSub) == -1 means there is no element in the list
list.add(aSub);//or bSub
counter++;
}
}
}
return counter;
}

Finding shortest possible substring that contains a String

This was a question asked in a recent programming interview.
Given a random string S and another string T with unique elements, find the minimum consecutive sub-string of S such that it contains all the elements in T.
Say,
S='adobecodebanc'
T='abc'
Answer='banc'
I've come up with a solution,
public static String completeSubstring(String T, String S){
String minSub = T;
StringBuilder sb = new StringBuilder();
for (int i = 0; i <T.length()-1; i++) {
for (int j = i + 1; j <= T.length() ; j++) {
String sub = T.substring(i,j);
if(stringContains(sub, S)){
if(sub.length() < minSub.length()) minSub = sub;
}
}
}
return minSub;
}
private static boolean stringContains(String t, String s){
//if(t.length() <= s.length()) return false;
int[] arr = new int[256];
for (int i = 0; i <t.length() ; i++) {
char c = t.charAt(i);
arr[c -'a'] = 1;
}
boolean found = true;
for (int i = 0; i <s.length() ; i++) {
char c = s.charAt(i);
if(arr[c - 'a'] != 1){
found = false;
break;
}else continue;
}
return found;
}
This algorithm has a O(n3) complexity, which but naturally isn't great. Can someone suggest a better algorithm.
Here's the O(N) solution.
The important thing to note re: complexity is that each unit of work involves incrementing either start or end, they don't decrease, and the algorithm stops before they both get to the end.
public static String findSubString(String s, String t)
{
//algorithm moves a sliding "current substring" through s
//in this map, we keep track of the number of occurrences of
//each target character there are in the current substring
Map<Character,int[]> counts = new HashMap<>();
for (char c : t.toCharArray())
{
counts.put(c,new int[1]);
}
//how many target characters are missing from the current substring
//current substring is initially empty, so all of them
int missing = counts.size();
//don't waste my time
if (missing<1)
{
return "";
}
//best substring found
int bestStart = -1, bestEnd = -1;
//current substring
int start=0, end=0;
while (end<s.length())
{
//expand the current substring at the end
int[] cnt = counts.get(s.charAt(end++));
if (cnt!=null)
{
if (cnt[0]==0)
{
--missing;
}
cnt[0]+=1;
}
//while the current substring is valid, remove characters
//at the start to see if a shorter substring that ends at the
//same place is also valid
while(start<end && missing<=0)
{
//current substring is valid
if (end-start < bestEnd-bestStart || bestEnd<0)
{
bestStart = start;
bestEnd = end;
}
cnt = counts.get(s.charAt(start++));
if (cnt != null)
{
cnt[0]-=1;
if (cnt[0]==0)
{
++missing;
}
}
}
//current substring is no longer valid. we'll add characters
//at the end until we get another valid one
//note that we don't need to add back any start character that
//we just removed, since we already tried the shortest valid string
//that starts at start-1
}
return(bestStart<=bestEnd ? s.substring(bestStart,bestEnd) : null);
}
I know that there already is an adequate O(N) complexity answer, but I tried to figure it out on my own without looking it up, just because it's a fun problem to solve and thought I would share. Here's the O(N) solution that I came up with:
public static String completeSubstring(String S, String T){
int min = S.length()+1, index1 = -1, index2 = -1;
ArrayList<ArrayList<Integer>> index = new ArrayList<ArrayList<Integer>>();
HashSet<Character> targetChars = new HashSet<Character>();
for(char c : T.toCharArray()) targetChars.add(c);
//reduce initial sequence to only target chars and keep track of index
//Note that the resultant string does not allow the same char to be consecutive
StringBuilder filterS = new StringBuilder();
for(int i = 0, s = 0 ; i < S.length() ; i++) {
char c = S.charAt(i);
if(targetChars.contains(c)) {
if(s > 0 && filterS.charAt(s-1) == c) {
index.get(s-1).add(i);
} else {
filterS.append(c);
index.add(new ArrayList<Integer>());
index.get(s).add(i);
s++;
}
}
}
//Not necessary to use regex, loops are fine, but for readability sake
String regex = "([abc])((?!\\1)[abc])((?!\\1)(?!\\2)[abc])";
Matcher m = Pattern.compile(regex).matcher(filterS.toString());
for(int i = 0, start = -1, p1, p2, tempMin, charSize = targetChars.size() ; m.find(i) ; i = start+1) {
start = m.start();
ArrayList<Integer> first = index.get(start);
p1 = first.get(first.size()-1);
p2 = index.get(start+charSize-1).get(0);
tempMin = p2-p1;
if(tempMin < min) {
min = tempMin;
index1 = p1;
index2 = p2;
}
}
return S.substring(index1, index2+1);
}
I'm pretty sure the complexity is O(N), please correct if I'm wrong
Alternative implementation of O(N) algorithm proposed by #MattTimmermans, which uses Map<Integer, Integer> to count occurrences and Set<Integer> to store chars from T that are present in current substring:
public static String completeSubstring(String s, String t) {
Map<Integer, Integer> occ
= t.chars().boxed().collect(Collectors.toMap(c -> c, c -> 0));
Set<Integer> found = new HashSet<>(); // characters from T found in current match
int start = 0; // current match
int bestStart = Integer.MIN_VALUE, bestEnd = -1;
for (int i = 0; i < s.length(); i++) {
int ci = s.charAt(i); // current char
if (!occ.containsKey(ci)) // not from T
continue;
occ.put(ci, occ.get(ci) + 1); // add occurrence
found.add(ci);
for (int j = start; j < i; j++) { // try to reduce current match
int cj = s.charAt(j);
Integer c = occ.get(cj);
if (c != null) {
if (c == 1) { // cannot reduce anymore
start = j;
break;
} else
occ.put(cj, c - 1); // remove occurrence
}
}
if (found.size() == occ.size() // all chars found
&& (i - start < bestEnd - bestStart)) {
bestStart = start;
bestEnd = i;
}
}
return bestStart < 0 ? null : s.substring(bestStart, bestEnd + 1);
}

How to get the count of unmatched character in two strings?

I need to get the count of Unmatched character in two strings. for example
string 1 "hari", string 2 "malar"
Now i need to remove the duplicates from both string ['a' & 'r'] are common in both strings so remove that, now string 1 contain "hi" string 2 contain "mla".
Remaining count = 5
I tried this code, its working fine if duplicate / repeart is not available in same sting like here 'a' come twice in string 2 so my code is didn't work properly.
for (int i = 0; i < first.length; i++) {
for (int j = 0; j < second.length; j++) {
if(first[i] == second[j])
{
getstrings = new ArrayList<String>();
count=count+1;
Log.d("Matches", "string char that matched "+ first[i] +"==" + second[j]);
}
}
}
int tot=(first.length + second.length) - count;
here first & second refers to
char[] first = nameone.toCharArray();
char[] second = nametwo.toCharArray();
this code is working fine for String 1 "sri" string 2 "hari" here in a string character didn't repeat so this above code is working fine. Help me to solve this ?
Here is my solution,
public static void RemoveMatchedCharsInnStrings(String first,String second)
{
for(int i = 0 ;i < first.length() ; i ++)
{
char c = first.charAt(i);
if(second.indexOf(c)!= -1)
{
first = first.replaceAll(""+c, "");
second = second.replaceAll(""+c, "");
}
}
System.out.println(first);
System.out.println(second);
System.out.println(first.length() + second.length());
}
Hope it is what you need. if not i'll update my answer
I saw the other answers and thought: There must be a more declarative and composable way of doing this!
There is, but it's far longer...
public static void main(String[] args) {
String first = "hari";
String second = "malar";
Map<Character, Integer> differences = absoluteDifference(characterCountOf(first), characterCountOf(second));
System.out.println(sumOfCounts(differences));
}
public static Map<Character, Integer> characterCountOf(String text) {
Map<Character, Integer> result = new HashMap<Character, Integer>();
for (int i=0; i < text.length(); i++) {
Character c = text.charAt(i);
result.put(c, result.containsKey(c) ? result.get(c) + 1 : 1);
}
return result;
}
public static <K> Set<K> commonKeys(Map<K, ?> first, Map<K, ?> second) {
Set<K> result = new HashSet<K>(first.keySet());
result.addAll(second.keySet());
return result;
}
public static <K> Map<K, Integer> absoluteDifference(Map<K, Integer> first, Map<K, Integer> second) {
Map<K, Integer> result = new HashMap<K, Integer>();
for (K key: commonKeys(first, second)) {
Integer firstCount = first.containsKey(key) ? first.get(key) : 0;
Integer secondCount = second.containsKey(key) ? second.get(key) : 0;
Integer resultCount = Math.max(firstCount, secondCount) - Math.min(firstCount, secondCount);
if (resultCount > 0) result.put(key, resultCount);
}
return result;
}
public static Integer sumOfCounts(Map<?, Integer> map) {
Integer sum = 0;
for (Integer count: map.values()) {
sum += count;
}
return sum;
}
This is the solution I prefer - but it's lot longer. You've tagged the question with Android, so I didn't use any Java 8 features, which would reduce it a bit (but not as much as I would have hoped for).
However it produces meaningful intermediate results. But it's still so much longer :-(
Try out this code:
String first = "hari";
String second = malar;
String tempFirst = "";
String tempSecond = "";
int maxSize = ((first.length() > second.length()) ? (first.length()) : (second.length()));
for (int i = 0; i < maxSize; i++) {
if (i >= second.length()) {
tempFirst += first.charAt(i);
} else if (i >= first.length()) {
tempSecond += second.charAt(i);
} else if (first.charAt(i) != second.charAt(i)) {
tempFirst += first.charAt(i);
tempSecond += second.charAt(i);
}
}
first = tempFirst;
second = tempSecond;
you need to break; as soon as the match is found:
public static void main(String[] args) {
String nameone="hari";
String nametwo="malar";
char[] first = nameone.toCharArray();
char[] second = nametwo.toCharArray();
List<String>getstrings=null;
int count=0;
for (int i = 0; i < first.length; i++) {
for (int j = 0; j < second.length; j++) {
if(first[i] == second[j])
{
getstrings = new ArrayList<String>();
count++;
System.out.println("Matches"+ "string char that matched "+ first[i] +"==" + second[j]);
break;
}
}
}
//System.out.println(count);
int tot=(first.length-count )+ (second.length - count);
System.out.println("Remaining after match from both strings:"+tot);
}
prints:
Remaining after match from both strings:5
Two things you are missing here.
In the if condition, when the two characters matches, you need to increment count by 2, not one as you are eliminating from both strings.
You need to put a break in the in condition as you are always matching for the first occurrence of the character.
Made those two changes in your code as below, and now it prints the result as you expected.
for (int i = 0; i < first.length; i++) {
for (int j = 0; j < second.length; j++) {
if(first[i] == second[j])
{
count=count+2;
break;
}
}
}
int tot=(first.length + second.length) - count;
System.out.println("Result = "+tot);
You just need to loop over two strings if characters are matched increment the count and just remove those count from total len of two characters
s = 'hackerhappy'\
t = 'hackerrank'\
count = 0
for i in range(len(s)):
for j in range(len(t)):
if s[i] == t[j]:
count += 2
break
char_unmatched = (len(s)+len(t)) - count
char_unmatched contains the count of number of characters from both the strings that are not equal

Permutate a String to upper and lower case

I have a string, "abc". How would a program look like (if possible, in Java) who permute the String?
For example:
abc
ABC
Abc
aBc
abC
ABc
abC
AbC
Something like this should do the trick:
void printPermutations(String text) {
char[] chars = text.toCharArray();
for (int i = 0, n = (int) Math.pow(2, chars.length); i < n; i++) {
char[] permutation = new char[chars.length];
for (int j =0; j < chars.length; j++) {
permutation[j] = (isBitSet(i, j)) ? Character.toUpperCase(chars[j]) : chars[j];
}
System.out.println(permutation);
}
}
boolean isBitSet(int n, int offset) {
return (n >> offset & 1) != 0;
}
As you probably already know, the number of possible different combinations is 2^n, where n equals the length of the input string.
Since n could theoretically be fairly large, there's a chance that 2^n will exceed the capacity of a primitive type such as an int. (The user may have to wait a few years for all of the combinations to finish printing, but that's their business.)
Instead, let's use a bit vector to hold all of the possible combinations. We'll set the number of bits equal to n and initialize them all to 1. For example, if the input string is "abcdefghij", the initial bit vector values will be {1111111111}.
For every combination, we simply have to loop through all of the characters in the input string and set each one to uppercase if its corresponding bit is a 1, else set it to lowercase. We then decrement the bit vector and repeat.
For example, the process would look like this for an input of "abc":
Bits:   Corresponding Combo:
111    ABC
110    ABc
101    AbC
100    Abc
011    aBC
010    aBc
001    abC
000    abc
By using a loop rather than a recursive function call, we also avoid the possibility of a stack overflow exception occurring on large input strings.
Here is the actual implementation:
import java.util.BitSet;
public void PrintCombinations(String input) {
char[] currentCombo = input.toCharArray();
// Create a bit vector the same length as the input, and set all of the bits to 1
BitSet bv = new BitSet(input.length());
bv.set(0, currentCombo.length);
// While the bit vector still has some bits set
while(!bv.isEmpty()) {
// Loop through the array of characters and set each one to uppercase or lowercase,
// depending on whether its corresponding bit is set
for(int i = 0; i < currentCombo.length; ++i) {
if(bv.get(i)) // If the bit is set
currentCombo[i] = Character.toUpperCase(currentCombo[i]);
else
currentCombo[i] = Character.toLowerCase(currentCombo[i]);
}
// Print the current combination
System.out.println(currentCombo);
// Decrement the bit vector
DecrementBitVector(bv, currentCombo.length);
}
// Now the bit vector contains all zeroes, which corresponds to all of the letters being lowercase.
// Simply print the input as lowercase for the final combination
System.out.println(input.toLowerCase());
}
public void DecrementBitVector(BitSet bv, int numberOfBits) {
int currentBit = numberOfBits - 1;
while(currentBit >= 0) {
bv.flip(currentBit);
// If the bit became a 0 when we flipped it, then we're done.
// Otherwise we have to continue flipping bits
if(!bv.get(currentBit))
break;
currentBit--;
}
}
String str = "Abc";
str = str.toLowerCase();
int numOfCombos = 1 << str.length();
for (int i = 0; i < numOfCombos; i++) {
char[] combinations = str.toCharArray();
for (int j = 0; j < str.length(); j++) {
if (((i >> j) & 1) == 1 ) {
combinations[j] = Character.toUpperCase(str.charAt(j));
}
}
System.out.println(new String(combinations));
}
You can also use backtracking to solve this problem:
public List<String> letterCasePermutation(String S) {
List<String> result = new ArrayList<>();
backtrack(0 , S, "", result);
return result;
}
private void backtrack(int start, String s, String temp, List<String> result) {
if(start >= s.length()) {
result.add(temp);
return;
}
char c = s.charAt(start);
if(!Character.isAlphabetic(c)) {
backtrack(start + 1, s, temp + c, result);
return;
}
if(Character.isUpperCase(c)) {
backtrack(start + 1, s, temp + c, result);
c = Character.toLowerCase(c);
backtrack(start + 1, s, temp + c, result);
}
else {
backtrack(start + 1, s, temp + c, result);
c = Character.toUpperCase(c);
backtrack(start + 1, s, temp + c, result);
}
}
Please find here the code snippet for the above :
public class StringPerm {
public static void main(String[] args) {
String str = "abc";
String[] f = permute(str);
for (int x = 0; x < f.length; x++) {
System.out.println(f[x]);
}
}
public static String[] permute(String str) {
String low = str.toLowerCase();
String up = str.toUpperCase();
char[] l = low.toCharArray();
char u[] = up.toCharArray();
String[] f = new String[10];
f[0] = low;
f[1] = up;
int k = 2;
char[] temp = new char[low.length()];
for (int i = 0; i < l.length; i++)
{
temp[i] = l[i];
for (int j = 0; j < u.length; j++)
{
if (i != j) {
temp[j] = u[j];
}
}
f[k] = new String(temp);
k++;
}
for (int i = 0; i < u.length; i++)
{
temp[i] = u[i];
for (int j = 0; j < l.length; j++)
{
if (i != j) {
temp[j] = l[j];
}
}
f[k] = new String(temp);
k++;
}
return f;
}
}
You can do something like
```
import java.util.*;
public class MyClass {
public static void main(String args[]) {
String n=(args[0]);
HashSet<String>rs = new HashSet();
helper(rs,n,0,n.length()-1);
System.out.println(rs);
}
public static void helper(HashSet<String>rs,String res , int l, int n)
{
if(l>n)
return;
for(int i=l;i<=n;i++)
{
res=swap(res,i);
rs.add(res);
helper(rs,res,l+1,n);
res=swap(res,i);
}
}
public static String swap(String st,int i)
{
char c = st.charAt(i);
char ch[]=st.toCharArray();
if(Character.isUpperCase(c))
{
c=Character.toLowerCase(c);
}
else if(Character.isLowerCase(c))
{
c=Character.toUpperCase(c);
}
ch[i]=c;
return new String(ch);
}
}
```

Categories

Resources