What is an elegant way to find all the permutations of a string. E.g. permutation for ba, would be ba and ab, but what about longer string such as abcdefgh? Is there any Java implementation example?
public static void permutation(String str) {
permutation("", str);
}
private static void permutation(String prefix, String str) {
int n = str.length();
if (n == 0) System.out.println(prefix);
else {
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
}
}
(via Introduction to Programming in Java)
Use recursion.
Try each of the letters in turn as the first letter and then find all the permutations of the remaining letters using a recursive call.
The base case is when the input is an empty string the only permutation is the empty string.
Here is my solution that is based on the idea of the book "Cracking the Coding Interview" (P54):
/**
* List permutations of a string.
*
* #param s the input string
* #return the list of permutations
*/
public static ArrayList<String> permutation(String s) {
// The result
ArrayList<String> res = new ArrayList<String>();
// If input string's length is 1, return {s}
if (s.length() == 1) {
res.add(s);
} else if (s.length() > 1) {
int lastIndex = s.length() - 1;
// Find out the last character
String last = s.substring(lastIndex);
// Rest of the string
String rest = s.substring(0, lastIndex);
// Perform permutation on the rest string and
// merge with the last character
res = merge(permutation(rest), last);
}
return res;
}
/**
* #param list a result of permutation, e.g. {"ab", "ba"}
* #param c the last character
* #return a merged new list, e.g. {"cab", "acb" ... }
*/
public static ArrayList<String> merge(ArrayList<String> list, String c) {
ArrayList<String> res = new ArrayList<>();
// Loop through all the string in the list
for (String s : list) {
// For each string, insert the last character to all possible positions
// and add them to the new list
for (int i = 0; i <= s.length(); ++i) {
String ps = new StringBuffer(s).insert(i, c).toString();
res.add(ps);
}
}
return res;
}
Running output of string "abcd":
Step 1: Merge [a] and b:
[ba, ab]
Step 2: Merge [ba, ab] and c:
[cba, bca, bac, cab, acb, abc]
Step 3: Merge [cba, bca, bac, cab, acb, abc] and d:
[dcba, cdba, cbda, cbad, dbca, bdca, bcda, bcad, dbac, bdac, badc, bacd, dcab, cdab, cadb, cabd, dacb, adcb, acdb, acbd, dabc, adbc, abdc, abcd]
Of all the solutions given here and in other forums, I liked Mark Byers the most. That description actually made me think and code it myself.
Too bad I cannot voteup his solution as I am newbie.
Anyways here is my implementation of his description
public class PermTest {
public static void main(String[] args) throws Exception {
String str = "abcdef";
StringBuffer strBuf = new StringBuffer(str);
doPerm(strBuf,0);
}
private static void doPerm(StringBuffer str, int index){
if(index == str.length())
System.out.println(str);
else { //recursively solve this by placing all other chars at current first pos
doPerm(str, index+1);
for (int i = index+1; i < str.length(); i++) {//start swapping all other chars with current first char
swap(str,index, i);
doPerm(str, index+1);
swap(str,i, index);//restore back my string buffer
}
}
}
private static void swap(StringBuffer str, int pos1, int pos2){
char t1 = str.charAt(pos1);
str.setCharAt(pos1, str.charAt(pos2));
str.setCharAt(pos2, t1);
}
}
I prefer this solution ahead of the first one in this thread because this solution uses StringBuffer. I wouldn't say my solution doesn't create any temporary string (it actually does in system.out.println where the toString() of StringBuffer is called). But I just feel this is better than the first solution where too many string literals are created. May be some performance guy out there can evalute this in terms of 'memory' (for 'time' it already lags due to that extra 'swap')
A very basic solution in Java is to use recursion + Set ( to avoid repetitions ) if you want to store and return the solution strings :
public static Set<String> generatePerm(String input)
{
Set<String> set = new HashSet<String>();
if (input == "")
return set;
Character a = input.charAt(0);
if (input.length() > 1)
{
input = input.substring(1);
Set<String> permSet = generatePerm(input);
for (String x : permSet)
{
for (int i = 0; i <= x.length(); i++)
{
set.add(x.substring(0, i) + a + x.substring(i));
}
}
}
else
{
set.add(a + "");
}
return set;
}
All the previous contributors have done a great job explaining and providing the code. I thought I should share this approach too because it might help someone too. The solution is based on (heaps' algorithm )
Couple of things:
Notice the last item which is depicted in the excel is just for helping you better visualize the logic. So, the actual values in the last column would be 2,1,0 (if we were to run the code because we are dealing with arrays and arrays start with 0).
The swapping algorithm happens based on even or odd values of current position. It's very self explanatory if you look at where the swap method is getting called.You can see what's going on.
Here is what happens:
public static void main(String[] args) {
String ourword = "abc";
String[] ourArray = ourword.split("");
permute(ourArray, ourArray.length);
}
private static void swap(String[] ourarray, int right, int left) {
String temp = ourarray[right];
ourarray[right] = ourarray[left];
ourarray[left] = temp;
}
public static void permute(String[] ourArray, int currentPosition) {
if (currentPosition == 1) {
System.out.println(Arrays.toString(ourArray));
} else {
for (int i = 0; i < currentPosition; i++) {
// subtract one from the last position (here is where you are
// selecting the the next last item
permute(ourArray, currentPosition - 1);
// if it's odd position
if (currentPosition % 2 == 1) {
swap(ourArray, 0, currentPosition - 1);
} else {
swap(ourArray, i, currentPosition - 1);
}
}
}
}
Let's use input abc as an example.
Start off with just the last element (c) in a set (["c"]), then add the second last element (b) to its front, end and every possible positions in the middle, making it ["bc", "cb"] and then in the same manner it will add the next element from the back (a) to each string in the set making it:
"a" + "bc" = ["abc", "bac", "bca"] and "a" + "cb" = ["acb" ,"cab", "cba"]
Thus entire permutation:
["abc", "bac", "bca","acb" ,"cab", "cba"]
Code:
public class Test
{
static Set<String> permutations;
static Set<String> result = new HashSet<String>();
public static Set<String> permutation(String string) {
permutations = new HashSet<String>();
int n = string.length();
for (int i = n - 1; i >= 0; i--)
{
shuffle(string.charAt(i));
}
return permutations;
}
private static void shuffle(char c) {
if (permutations.size() == 0) {
permutations.add(String.valueOf(c));
} else {
Iterator<String> it = permutations.iterator();
for (int i = 0; i < permutations.size(); i++) {
String temp1;
for (; it.hasNext();) {
temp1 = it.next();
for (int k = 0; k < temp1.length() + 1; k += 1) {
StringBuilder sb = new StringBuilder(temp1);
sb.insert(k, c);
result.add(sb.toString());
}
}
}
permutations = result;
//'result' has to be refreshed so that in next run it doesn't contain stale values.
result = new HashSet<String>();
}
}
public static void main(String[] args) {
Set<String> result = permutation("abc");
System.out.println("\nThere are total of " + result.size() + " permutations:");
Iterator<String> it = result.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
This one is without recursion
public static void permute(String s) {
if(null==s || s.isEmpty()) {
return;
}
// List containing words formed in each iteration
List<String> strings = new LinkedList<String>();
strings.add(String.valueOf(s.charAt(0))); // add the first element to the list
// Temp list that holds the set of strings for
// appending the current character to all position in each word in the original list
List<String> tempList = new LinkedList<String>();
for(int i=1; i< s.length(); i++) {
for(int j=0; j<strings.size(); j++) {
tempList.addAll(merge(s.charAt(i), strings.get(j)));
}
strings.removeAll(strings);
strings.addAll(tempList);
tempList.removeAll(tempList);
}
for(int i=0; i<strings.size(); i++) {
System.out.println(strings.get(i));
}
}
/**
* helper method that appends the given character at each position in the given string
* and returns a set of such modified strings
* - set removes duplicates if any(in case a character is repeated)
*/
private static Set<String> merge(Character c, String s) {
if(s==null || s.isEmpty()) {
return null;
}
int len = s.length();
StringBuilder sb = new StringBuilder();
Set<String> list = new HashSet<String>();
for(int i=0; i<= len; i++) {
sb = new StringBuilder();
sb.append(s.substring(0, i) + c + s.substring(i, len));
list.add(sb.toString());
}
return list;
}
Well here is an elegant, non-recursive, O(n!) solution:
public static StringBuilder[] permutations(String s) {
if (s.length() == 0)
return null;
int length = fact(s.length());
StringBuilder[] sb = new StringBuilder[length];
for (int i = 0; i < length; i++) {
sb[i] = new StringBuilder();
}
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
int times = length / (i + 1);
for (int j = 0; j < times; j++) {
for (int k = 0; k < length / times; k++) {
sb[j * length / times + k].insert(k, ch);
}
}
}
return sb;
}
One of the simple solution could be just keep swapping the characters recursively using two pointers.
public static void main(String[] args)
{
String str="abcdefgh";
perm(str);
}
public static void perm(String str)
{ char[] char_arr=str.toCharArray();
helper(char_arr,0);
}
public static void helper(char[] char_arr, int i)
{
if(i==char_arr.length-1)
{
// print the shuffled string
String str="";
for(int j=0; j<char_arr.length; j++)
{
str=str+char_arr[j];
}
System.out.println(str);
}
else
{
for(int j=i; j<char_arr.length; j++)
{
char tmp = char_arr[i];
char_arr[i] = char_arr[j];
char_arr[j] = tmp;
helper(char_arr,i+1);
char tmp1 = char_arr[i];
char_arr[i] = char_arr[j];
char_arr[j] = tmp1;
}
}
}
python implementation
def getPermutation(s, prefix=''):
if len(s) == 0:
print prefix
for i in range(len(s)):
getPermutation(s[0:i]+s[i+1:len(s)],prefix+s[i] )
getPermutation('abcd','')
This is what I did through basic understanding of Permutations and Recursive function calling. Takes a bit of time but it's done independently.
public class LexicographicPermutations {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s="abc";
List<String>combinations=new ArrayList<String>();
combinations=permutations(s);
Collections.sort(combinations);
System.out.println(combinations);
}
private static List<String> permutations(String s) {
// TODO Auto-generated method stub
List<String>combinations=new ArrayList<String>();
if(s.length()==1){
combinations.add(s);
}
else{
for(int i=0;i<s.length();i++){
List<String>temp=permutations(s.substring(0, i)+s.substring(i+1));
for (String string : temp) {
combinations.add(s.charAt(i)+string);
}
}
}
return combinations;
}}
which generates Output as [abc, acb, bac, bca, cab, cba].
Basic logic behind it is
For each character, consider it as 1st character & find the combinations of remaining characters. e.g. [abc](Combination of abc)->.
a->[bc](a x Combination of (bc))->{abc,acb}
b->[ac](b x Combination of (ac))->{bac,bca}
c->[ab](c x Combination of (ab))->{cab,cba}
And then recursively calling each [bc],[ac] & [ab] independently.
Use recursion.
when the input is an empty string the only permutation is an empty string.Try for each of the letters in the string by making it as the first letter and then find all the permutations of the remaining letters using a recursive call.
import java.util.ArrayList;
import java.util.List;
class Permutation {
private static List<String> permutation(String prefix, String str) {
List<String> permutations = new ArrayList<>();
int n = str.length();
if (n == 0) {
permutations.add(prefix);
} else {
for (int i = 0; i < n; i++) {
permutations.addAll(permutation(prefix + str.charAt(i), str.substring(i + 1, n) + str.substring(0, i)));
}
}
return permutations;
}
public static void main(String[] args) {
List<String> perms = permutation("", "abcd");
String[] array = new String[perms.size()];
for (int i = 0; i < perms.size(); i++) {
array[i] = perms.get(i);
}
int x = array.length;
for (final String anArray : array) {
System.out.println(anArray);
}
}
}
this worked for me..
import java.util.Arrays;
public class StringPermutations{
public static void main(String args[]) {
String inputString = "ABC";
permute(inputString.toCharArray(), 0, inputString.length()-1);
}
public static void permute(char[] ary, int startIndex, int endIndex) {
if(startIndex == endIndex){
System.out.println(String.valueOf(ary));
}else{
for(int i=startIndex;i<=endIndex;i++) {
swap(ary, startIndex, i );
permute(ary, startIndex+1, endIndex);
swap(ary, startIndex, i );
}
}
}
public static void swap(char[] ary, int x, int y) {
char temp = ary[x];
ary[x] = ary[y];
ary[y] = temp;
}
}
Java implementation without recursion
public Set<String> permutate(String s){
Queue<String> permutations = new LinkedList<String>();
Set<String> v = new HashSet<String>();
permutations.add(s);
while(permutations.size()!=0){
String str = permutations.poll();
if(!v.contains(str)){
v.add(str);
for(int i = 0;i<str.length();i++){
String c = String.valueOf(str.charAt(i));
permutations.add(str.substring(i+1) + c + str.substring(0,i));
}
}
}
return v;
}
Let me try to tackle this problem with Kotlin:
fun <T> List<T>.permutations(): List<List<T>> {
//escape case
if (this.isEmpty()) return emptyList()
if (this.size == 1) return listOf(this)
if (this.size == 2) return listOf(listOf(this.first(), this.last()), listOf(this.last(), this.first()))
//recursive case
return this.flatMap { lastItem ->
this.minus(lastItem).permutations().map { it.plus(lastItem) }
}
}
Core concept: Break down long list into smaller list + recursion
Long answer with example list [1, 2, 3, 4]:
Even for a list of 4 it already kinda get's confusing trying to list all the possible permutations in your head, and what we need to do is exactly to avoid that. It is easy for us to understand how to make all permutations of list of size 0, 1, and 2, so all we need to do is break them down to any of those sizes and combine them back up correctly. Imagine a jackpot machine: this algorithm will start spinning from the right to the left, and write down
return empty/list of 1 when list size is 0 or 1
handle when list size is 2 (e.g. [3, 4]), and generate the 2 permutations ([3, 4] & [4, 3])
For each item, mark that as the last in the last, and find all the permutations for the rest of the item in the list. (e.g. put [4] on the table, and throw [1, 2, 3] into permutation again)
Now with all permutation it's children, put itself back to the end of the list (e.g.: [1, 2, 3][,4], [1, 3, 2][,4], [2, 3, 1][, 4], ...)
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class hello {
public static void main(String[] args) throws IOException {
hello h = new hello();
h.printcomp();
}
int fact=1;
public void factrec(int a,int k){
if(a>=k)
{fact=fact*k;
k++;
factrec(a,k);
}
else
{System.out.println("The string will have "+fact+" permutations");
}
}
public void printcomp(){
String str;
int k;
Scanner in = new Scanner(System.in);
System.out.println("enter the string whose permutations has to b found");
str=in.next();
k=str.length();
factrec(k,1);
String[] arr =new String[fact];
char[] array = str.toCharArray();
while(p<fact)
printcomprec(k,array,arr);
// if incase u need array containing all the permutation use this
//for(int d=0;d<fact;d++)
//System.out.println(arr[d]);
}
int y=1;
int p = 0;
int g=1;
int z = 0;
public void printcomprec(int k,char array[],String arr[]){
for (int l = 0; l < k; l++) {
for (int b=0;b<k-1;b++){
for (int i=1; i<k-g; i++) {
char temp;
String stri = "";
temp = array[i];
array[i] = array[i + g];
array[i + g] = temp;
for (int j = 0; j < k; j++)
stri += array[j];
arr[z] = stri;
System.out.println(arr[z] + " " + p++);
z++;
}
}
char temp;
temp=array[0];
array[0]=array[y];
array[y]=temp;
if (y >= k-1)
y=y-(k-1);
else
y++;
}
if (g >= k-1)
g=1;
else
g++;
}
}
/** Returns an array list containing all
* permutations of the characters in s. */
public static ArrayList<String> permute(String s) {
ArrayList<String> perms = new ArrayList<>();
int slen = s.length();
if (slen > 0) {
// Add the first character from s to the perms array list.
perms.add(Character.toString(s.charAt(0)));
// Repeat for all additional characters in s.
for (int i = 1; i < slen; ++i) {
// Get the next character from s.
char c = s.charAt(i);
// For each of the strings currently in perms do the following:
int size = perms.size();
for (int j = 0; j < size; ++j) {
// 1. remove the string
String p = perms.remove(0);
int plen = p.length();
// 2. Add plen + 1 new strings to perms. Each new string
// consists of the removed string with the character c
// inserted into it at a unique location.
for (int k = 0; k <= plen; ++k) {
perms.add(p.substring(0, k) + c + p.substring(k));
}
}
}
}
return perms;
}
Here is a straightforward minimalist recursive solution in Java:
public static ArrayList<String> permutations(String s) {
ArrayList<String> out = new ArrayList<String>();
if (s.length() == 1) {
out.add(s);
return out;
}
char first = s.charAt(0);
String rest = s.substring(1);
for (String permutation : permutations(rest)) {
out.addAll(insertAtAllPositions(first, permutation));
}
return out;
}
public static ArrayList<String> insertAtAllPositions(char ch, String s) {
ArrayList<String> out = new ArrayList<String>();
for (int i = 0; i <= s.length(); ++i) {
String inserted = s.substring(0, i) + ch + s.substring(i);
out.add(inserted);
}
return out;
}
We can use factorial to find how many strings started with particular letter.
Example: take the input abcd. (3!) == 6 strings will start with every letter of abcd.
static public int facts(int x){
int sum = 1;
for (int i = 1; i < x; i++) {
sum *= (i+1);
}
return sum;
}
public static void permutation(String str) {
char[] str2 = str.toCharArray();
int n = str2.length;
int permutation = 0;
if (n == 1) {
System.out.println(str2[0]);
} else if (n == 2) {
System.out.println(str2[0] + "" + str2[1]);
System.out.println(str2[1] + "" + str2[0]);
} else {
for (int i = 0; i < n; i++) {
if (true) {
char[] str3 = str.toCharArray();
char temp = str3[i];
str3[i] = str3[0];
str3[0] = temp;
str2 = str3;
}
for (int j = 1, count = 0; count < facts(n-1); j++, count++) {
if (j != n-1) {
char temp1 = str2[j+1];
str2[j+1] = str2[j];
str2[j] = temp1;
} else {
char temp1 = str2[n-1];
str2[n-1] = str2[1];
str2[1] = temp1;
j = 1;
} // end of else block
permutation++;
System.out.print("permutation " + permutation + " is -> ");
for (int k = 0; k < n; k++) {
System.out.print(str2[k]);
} // end of loop k
System.out.println();
} // end of loop j
} // end of loop i
}
}
//insert each character into an arraylist
static ArrayList al = new ArrayList();
private static void findPermutation (String str){
for (int k = 0; k < str.length(); k++) {
addOneChar(str.charAt(k));
}
}
//insert one char into ArrayList
private static void addOneChar(char ch){
String lastPerStr;
String tempStr;
ArrayList locAl = new ArrayList();
for (int i = 0; i < al.size(); i ++ ){
lastPerStr = al.get(i).toString();
//System.out.println("lastPerStr: " + lastPerStr);
for (int j = 0; j <= lastPerStr.length(); j++) {
tempStr = lastPerStr.substring(0,j) + ch +
lastPerStr.substring(j, lastPerStr.length());
locAl.add(tempStr);
//System.out.println("tempStr: " + tempStr);
}
}
if(al.isEmpty()){
al.add(ch);
} else {
al.clear();
al = locAl;
}
}
private static void printArrayList(ArrayList al){
for (int i = 0; i < al.size(); i++) {
System.out.print(al.get(i) + " ");
}
}
//Rotate and create words beginning with all letter possible and push to stack 1
//Read from stack1 and for each word create words with other letters at the next location by rotation and so on
/* eg : man
1. push1 - man, anm, nma
2. pop1 - nma , push2 - nam,nma
pop1 - anm , push2 - amn,anm
pop1 - man , push2 - mna,man
*/
public class StringPermute {
static String str;
static String word;
static int top1 = -1;
static int top2 = -1;
static String[] stringArray1;
static String[] stringArray2;
static int strlength = 0;
public static void main(String[] args) throws IOException {
System.out.println("Enter String : ");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader bfr = new BufferedReader(isr);
str = bfr.readLine();
word = str;
strlength = str.length();
int n = 1;
for (int i = 1; i <= strlength; i++) {
n = n * i;
}
stringArray1 = new String[n];
stringArray2 = new String[n];
push(word, 1);
doPermute();
display();
}
public static void push(String word, int x) {
if (x == 1)
stringArray1[++top1] = word;
else
stringArray2[++top2] = word;
}
public static String pop(int x) {
if (x == 1)
return stringArray1[top1--];
else
return stringArray2[top2--];
}
public static void doPermute() {
for (int j = strlength; j >= 2; j--)
popper(j);
}
public static void popper(int length) {
// pop from stack1 , rotate each word n times and push to stack 2
if (top1 > -1) {
while (top1 > -1) {
word = pop(1);
for (int j = 0; j < length; j++) {
rotate(length);
push(word, 2);
}
}
}
// pop from stack2 , rotate each word n times w.r.t position and push to
// stack 1
else {
while (top2 > -1) {
word = pop(2);
for (int j = 0; j < length; j++) {
rotate(length);
push(word, 1);
}
}
}
}
public static void rotate(int position) {
char[] charstring = new char[100];
for (int j = 0; j < word.length(); j++)
charstring[j] = word.charAt(j);
int startpos = strlength - position;
char temp = charstring[startpos];
for (int i = startpos; i < strlength - 1; i++) {
charstring[i] = charstring[i + 1];
}
charstring[strlength - 1] = temp;
word = new String(charstring).trim();
}
public static void display() {
int top;
if (top1 > -1) {
while (top1 > -1)
System.out.println(stringArray1[top1--]);
} else {
while (top2 > -1)
System.out.println(stringArray2[top2--]);
}
}
}
Another simple way is to loop through the string, pick the character that is not used yet and put it to a buffer, continue the loop till the buffer size equals to the string length. I like this back tracking solution better because:
Easy to understand
Easy to avoid duplication
The output is sorted
Here is the java code:
List<String> permute(String str) {
if (str == null) {
return null;
}
char[] chars = str.toCharArray();
boolean[] used = new boolean[chars.length];
List<String> res = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
Arrays.sort(chars);
helper(chars, used, sb, res);
return res;
}
void helper(char[] chars, boolean[] used, StringBuilder sb, List<String> res) {
if (sb.length() == chars.length) {
res.add(sb.toString());
return;
}
for (int i = 0; i < chars.length; i++) {
// avoid duplicates
if (i > 0 && chars[i] == chars[i - 1] && !used[i - 1]) {
continue;
}
// pick the character that has not used yet
if (!used[i]) {
used[i] = true;
sb.append(chars[i]);
helper(chars, used, sb, res);
// back tracking
sb.deleteCharAt(sb.length() - 1);
used[i] = false;
}
}
}
Input str: 1231
Output list: {1123, 1132, 1213, 1231, 1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211}
Noticed that the output is sorted, and there is no duplicate result.
Recursion is not necessary, even you can calculate any permutation directly, this solution uses generics to permute any array.
Here is a good information about this algorihtm.
For C# developers here is more useful implementation.
public static void main(String[] args) {
String word = "12345";
Character[] array = ArrayUtils.toObject(word.toCharArray());
long[] factorials = Permutation.getFactorials(array.length + 1);
for (long i = 0; i < factorials[array.length]; i++) {
Character[] permutation = Permutation.<Character>getPermutation(i, array, factorials);
printPermutation(permutation);
}
}
private static void printPermutation(Character[] permutation) {
for (int i = 0; i < permutation.length; i++) {
System.out.print(permutation[i]);
}
System.out.println();
}
This algorithm has O(N) time and space complexity to calculate each permutation.
public class Permutation {
public static <T> T[] getPermutation(long permutationNumber, T[] array, long[] factorials) {
int[] sequence = generateSequence(permutationNumber, array.length - 1, factorials);
T[] permutation = generatePermutation(array, sequence);
return permutation;
}
public static <T> T[] generatePermutation(T[] array, int[] sequence) {
T[] clone = array.clone();
for (int i = 0; i < clone.length - 1; i++) {
swap(clone, i, i + sequence[i]);
}
return clone;
}
private static int[] generateSequence(long permutationNumber, int size, long[] factorials) {
int[] sequence = new int[size];
for (int j = 0; j < sequence.length; j++) {
long factorial = factorials[sequence.length - j];
sequence[j] = (int) (permutationNumber / factorial);
permutationNumber = (int) (permutationNumber % factorial);
}
return sequence;
}
private static <T> void swap(T[] array, int i, int j) {
T t = array[i];
array[i] = array[j];
array[j] = t;
}
public static long[] getFactorials(int length) {
long[] factorials = new long[length];
long factor = 1;
for (int i = 0; i < length; i++) {
factor *= i <= 1 ? 1 : i;
factorials[i] = factor;
}
return factorials;
}
}
My implementation based on Mark Byers's description above:
static Set<String> permutations(String str){
if (str.isEmpty()){
return Collections.singleton(str);
}else{
Set <String> set = new HashSet<>();
for (int i=0; i<str.length(); i++)
for (String s : permutations(str.substring(0, i) + str.substring(i+1)))
set.add(str.charAt(i) + s);
return set;
}
}
Permutation of String:
public static void main(String args[]) {
permu(0,"ABCD");
}
static void permu(int fixed,String s) {
char[] chr=s.toCharArray();
if(fixed==s.length())
System.out.println(s);
for(int i=fixed;i<s.length();i++) {
char c=chr[i];
chr[i]=chr[fixed];
chr[fixed]=c;
permu(fixed+1,new String(chr));
}
}
Here is another simpler method of doing Permutation of a string.
public class Solution4 {
public static void main(String[] args) {
String a = "Protijayi";
per(a, 0);
}
static void per(String a , int start ) {
//bse case;
if(a.length() == start) {System.out.println(a);}
char[] ca = a.toCharArray();
//swap
for (int i = start; i < ca.length; i++) {
char t = ca[i];
ca[i] = ca[start];
ca[start] = t;
per(new String(ca),start+1);
}
}//per
}
A java implementation to print all the permutations of a given string considering duplicate characters and prints only unique characters is as follow:
import java.util.Set;
import java.util.HashSet;
public class PrintAllPermutations2
{
public static void main(String[] args)
{
String str = "AAC";
PrintAllPermutations2 permutation = new PrintAllPermutations2();
Set<String> uniqueStrings = new HashSet<>();
permutation.permute("", str, uniqueStrings);
}
void permute(String prefixString, String s, Set<String> set)
{
int n = s.length();
if(n == 0)
{
if(!set.contains(prefixString))
{
System.out.println(prefixString);
set.add(prefixString);
}
}
else
{
for(int i=0; i<n; i++)
{
permute(prefixString + s.charAt(i), s.substring(0,i) + s.substring(i+1,n), set);
}
}
}
}
String permutaions using Es6
Using reduce() method
const permutations = str => {
if (str.length <= 2)
return str.length === 2 ? [str, str[1] + str[0]] : [str];
return str
.split('')
.reduce(
(acc, letter, index) =>
acc.concat(permutations(str.slice(0, index) + str.slice(index + 1)).map(val => letter + val)),
[]
);
};
console.log(permutations('STR'));
In case anyone wants to generate the permutations to do something with them, instead of just printing them via a void method:
static List<int[]> permutations(int n) {
class Perm {
private final List<int[]> permutations = new ArrayList<>();
private void perm(int[] array, int step) {
if (step == 1) permutations.add(array.clone());
else for (int i = 0; i < step; i++) {
perm(array, step - 1);
int j = (step % 2 == 0) ? i : 0;
swap(array, step - 1, j);
}
}
private void swap(int[] array, int i, int j) {
int buffer = array[i];
array[i] = array[j];
array[j] = buffer;
}
}
int[] nVector = new int[n];
for (int i = 0; i < n; i++) nVector [i] = i;
Perm perm = new Perm();
perm.perm(nVector, n);
return perm.permutations;
}
I'm writing a program that will print the unique character in a string (entered through a scanner). I've created a method that tries to accomplish this but I keep getting characters that are not repeats, instead of a character (or characters) that is unique to the string. I want the unique letters only.
Here's my code:
import java.util.Scanner;
public class Sameness{
public static void main (String[]args){
Scanner kb = new Scanner (System.in);
String word = "";
System.out.println("Enter a word: ");
word = kb.nextLine();
uniqueCharacters(word);
}
public static void uniqueCharacters(String test){
String temp = "";
for (int i = 0; i < test.length(); i++){
if (temp.indexOf(test.charAt(i)) == - 1){
temp = temp + test.charAt(i);
}
}
System.out.println(temp + " ");
}
}
And here's sample output with the above code:
Enter a word:
nreena
nrea
The expected output would be: ra
Based on your desired output, you have to replace a character that initially has been already added when it has a duplicated later, so:
public static void uniqueCharacters(String test){
String temp = "";
for (int i = 0; i < test.length(); i++){
char current = test.charAt(i);
if (temp.indexOf(current) < 0){
temp = temp + current;
} else {
temp = temp.replace(String.valueOf(current), "");
}
}
System.out.println(temp + " ");
}
How about applying the KISS principle:
public static void uniqueCharacters(String test) {
System.out.println(test.chars().distinct().mapToObj(c -> String.valueOf((char)c)).collect(Collectors.joining()));
}
The accepted answer will not pass all the test case for example
input -"aaabcdd"
desired output-"bc"
but the accepted answer will give -abc
because the character a present odd number of times.
Here I have used ConcurrentHasMap to store character and the number of occurrences of character then removed the character if the occurrences is more than one time.
import java.util.concurrent.ConcurrentHashMap;
public class RemoveConductive {
public static void main(String[] args) {
String s="aabcddkkbghff";
String[] cvrtar=s.trim().split("");
ConcurrentHashMap<String,Integer> hm=new ConcurrentHashMap<>();
for(int i=0;i<cvrtar.length;i++){
if(!hm.containsKey(cvrtar[i])){
hm.put(cvrtar[i],1);
}
else{
hm.put(cvrtar[i],hm.get(cvrtar[i])+1);
}
}
for(String ele:hm.keySet()){
if(hm.get(ele)>1){
hm.remove(ele);
}
}
for(String key:hm.keySet()){
System.out.print(key);
}
}
}
Though to approach a solution I would suggest you to try and use a better data structure and not just string. Yet, you can simply modify your logic to delete already existing duplicates using an else as follows :
public static void uniqueCharacters(String test) {
String temp = "";
for (int i = 0; i < test.length(); i++) {
char ch = test.charAt(i);
if (temp.indexOf(ch) == -1) {
temp = temp + ch;
} else {
temp.replace(String.valueOf(ch),""); // added this to your existing code
}
}
System.out.println(temp + " ");
}
This is an interview question. Find Out all the unique characters of a string.
Here is the complete solution. The code itself is self explanatory.
public class Test12 {
public static void main(String[] args) {
String a = "ProtijayiGiniGina";
allunique(a);
}
private static void allunique(String a) {
int[] count = new int[256];// taking count of characters
for (int i = 0; i < a.length(); i++) {
char ch = a.charAt(i);
count[ch]++;
}
for (int i = 0; i < a.length(); i++) {
char chh = a.charAt(i);
// character which has arrived only one time in the string will be printed out
if (count[chh] == 1) {
System.out.println("index => " + i + " and unique character => " + a.charAt(i));
}
}
}// unique
}
In Python :
def firstUniqChar(a):
count = [0] *256
for i in a: count[ord(i)] += 1
element = ""
for item in a:
if (count[ord(item)] == 1):
element = item;
break;
return element
a = "GiniGinaProtijayi";
print(firstUniqChar(a)) # output is P
public static String input = "10 5 5 10 6 6 2 3 1 3 4 5 3";
public static void uniqueValue (String numbers) {
String [] str = input.split(" ");
Set <String> unique = new HashSet <String> (Arrays.asList(str));
System.out.println(unique);
for (String value:unique) {
int count = 0;
for ( int i= 0; i<str.length; i++) {
if (value.equals(str[i])) {
count++;
}
}
System.out.println(value+"\t"+count);
}
}
public static void main(String [] args) {
uniqueValue(input);
}
Step1: To find the unique characters in a string, I have first taken the string from user.
Step2: Converted the input string to charArray using built in function in java.
Step3: Considered two HashSet (set1 for storing all characters even if it is getting repeated, set2 for storing only unique characters.
Step4 : Run for loop over the array and check that if particular character is not there in set1 then add it to both set1 and set2. if that particular character is already there in set1 then add it to set1 again but remove it from set2.( This else part is useful when particular character is getting repeated odd number of times).
Step5 : Now set2 will have only unique characters. Hence, just print that set2.
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String str = input.next();
char arr[] = str.toCharArray();
HashSet<Character> set1=new HashSet<Character>();
HashSet<Character> set2=new HashSet<Character>();
for(char i:arr)
{
if(set1.contains(i))
{
set1.add(i);
set2.remove(i);
}
else
{
set1.add(i);
set2.add(i);
}
}
System.out.println(set2);
}
I would store all the characters of the string in an array that you will loop through to check if the current characters appears there more than once. If it doesn't, then add it to temp.
public static void uniqueCharacters(String test) {
String temp = "";
char[] array = test.toCharArray();
int count; //keep track of how many times the character exists in the string
outerloop: for (int i = 0; i < test.length(); i++) {
count = 0; //reset the count for every new letter
for(int j = 0; j < array.length; j++) {
if(test.charAt(i) == array[j])
count++;
if(count == 2){
count = 0;
continue outerloop; //move on to the next letter in the string; this will skip the next two lines below
}
}
temp += test.charAt(i);
System.out.println("Adding.");
}
System.out.println(temp);
}
I have added comments for some more detail.
import java.util.*;
import java.lang.*;
class Demo
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
System.out.println("Enter String");
String s1=sc.nextLine();
try{
HashSet<Object> h=new HashSet<Object>();
for(int i=0;i<s1.length();i++)
{
h.add(s1.charAt(i));
}
Iterator<Object> itr=h.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
catch(Exception e)
{
System.out.println("error");
}
}
}
If you don't want to use additional space:
String abc="developer";
System.out.println("The unique characters are-");
for(int i=0;i<abc.length();i++)
{
for(int j=i+1;j<abc.length();j++)
{
if(abc.charAt(i)==abc.charAt(j))
abc=abc.replace(String.valueOf(abc.charAt(j))," ");
}
}
System.out.println(abc);
Time complexity O(n^2) and no space.
This String algorithm is used to print unique characters in a string.It runs in O(n) runtime where n is the length of the string.It supports ASCII characters only.
static String printUniqChar(String s) {
StringBuilder buildUniq = new StringBuilder();
boolean[] uniqCheck = new boolean[128];
for (int i = 0; i < s.length(); i++) {
if (!uniqCheck[s.charAt(i)]) {
uniqCheck[s.charAt(i)] = true;
if (uniqCheck[s.charAt(i)])
buildUniq.append(s.charAt(i));
}
}
public class UniqueCharactersInString {
public static void main(String []args){
String input = "aabbcc";
String output = uniqueString(input);
System.out.println(output);
}
public static String uniqueString(String s){
HashSet<Character> uniques = new HashSet<>();
uniques.add(s.charAt(0));
String out = "";
out += s.charAt(0);
for(int i =1; i < s.length(); i++){
if(!uniques.contains(s.charAt(i))){
uniques.add(s.charAt(i));
out += s.charAt(i);
}
}
return out;
}
}
What would be the inneficiencies of this answer? How does it compare to other answers?
Based on your desired output you can replace each character already present with a blank character.
public static void uniqueCharacters(String test){
String temp = "";
for(int i = 0; i < test.length(); i++){
if (temp.indexOf(test.charAt(i)) == - 1){
temp = temp + test.charAt(i);
} else {
temp.replace(String.valueOf(temp.charAt(i)), "");
}
}
System.out.println(temp + " ");
}
public void uniq(String inputString) {
String result = "";
int inputStringLen = inputStr.length();
int[] repeatedCharacters = new int[inputStringLen];
char inputTmpChar;
char tmpChar;
for (int i = 0; i < inputStringLen; i++) {
inputTmpChar = inputStr.charAt(i);
for (int j = 0; j < inputStringLen; j++) {
tmpChar = inputStr.charAt(j);
if (inputTmpChar == tmpChar)
repeatedCharacters[i]++;
}
}
for (int k = 0; k < inputStringLen; k++) {
inputTmpChar = inputStr.charAt(k);
if (repeatedCharacters[k] == 1)
result = result + inputTmpChar + " ";
}
System.out.println ("Unique characters: " + result);
}
In first for loop I count the number of times the character repeats in the string. In the second line I am looking for characters repetitive once.
how about this :)
for (int i=0; i< input.length();i++)
if(input.indexOf(input.charAt(i)) == input.lastIndexOf(input.charAt(i)))
System.out.println(input.charAt(i) + " is unique");
package extra;
public class TempClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
String abcString="hsfj'pwue2hsu38bf74sa';fwe'rwe34hrfafnosdfoasq7433qweid";
char[] myCharArray=abcString.toCharArray();
TempClass mClass=new TempClass();
mClass.countUnique(myCharArray);
mClass.countEach(myCharArray);
}
/**
* This is the program to find unique characters in array.
* #add This is nice.
* */
public void countUnique(char[] myCharArray) {
int arrayLength=myCharArray.length;
System.out.println("Array Length is: "+arrayLength);
char[] uniqueValues=new char[myCharArray.length];
int uniqueValueIndex=0;
int count=0;
for(int i=0;i<arrayLength;i++) {
for(int j=0;j<arrayLength;j++) {
if (myCharArray[i]==myCharArray[j] && i!=j) {
count=count+1;
}
}
if (count==0) {
uniqueValues[uniqueValueIndex]=myCharArray[i];
uniqueValueIndex=uniqueValueIndex+1;
count=0;
}
count=0;
}
for(char a:uniqueValues) {
System.out.println(a);
}
}
/**
* This is the program to find count each characters in array.
* #add This is nice.
* */
public void countEach(char[] myCharArray) {
}
}
Here str will be your string to find the unique characters.
function getUniqueChars(str){
let uniqueChars = '';
for(let i = 0; i< str.length; i++){
for(let j= 0; j< str.length; j++) {
if(str.indexOf(str[i]) === str.lastIndexOf(str[j])) {
uniqueChars += str[i];
}
}
}
return uniqueChars;
}
public static void main(String[] args) {
String s = "aaabcdd";
char a[] = s.toCharArray();
List duplicates = new ArrayList();
List uniqueElements = new ArrayList();
for (int i = 0; i < a.length; i++) {
uniqueElements.add(a[i]);
for (int j = i + 1; j < a.length; j++) {
if (a[i] == a[j]) {
duplicates.add(a[i]);
break;
}
}
}
uniqueElements.removeAll(duplicates);
System.out.println(uniqueElements);
System.out.println("First Unique : "+uniqueElements.get(0));
}
Output :
[b, c]
First Unique : b
import java.util.*;
public class Sameness{
public static void main (String[]args){
Scanner kb = new Scanner (System.in);
String word = "";
System.out.println("Enter a word: ");
word = kb.nextLine();
uniqueCharacters(word);
}
public static void uniqueCharacters(String test){
for(int i=0;i<test.length();i++){
if(test.lastIndexOf(test.charAt(i))!=i)
test=test.replaceAll(String.valueOf(test.charAt(i)),"");
}
System.out.println(test);
}
}
public class Program02
{
public static void main(String[] args)
{
String inputString = "abhilasha";
for (int i = 0; i < inputString.length(); i++)
{
for (int j = i + 1; j < inputString.length(); j++)
{
if(inputString.toCharArray()[i] == inputString.toCharArray()[j])
{
inputString = inputString.replace(String.valueOf(inputString.charAt(j)), "");
}
}
}
System.out.println(inputString);
}
}
Hi I've been doing this java program, i should input a string and output the longest palindrome that can be found ..
but my program only output the first letter of the longest palindrome .. i badly need your help .. thanks!
SHOULD BE:
INPUT : abcdcbbcdeedcba
OUTPUT : bcdeedcb
There are two palindrome strings : bcdcb and bcdeedcb
BUT WHEN I INPUT : abcdcbbcdeedcba
output : b
import javax.swing.JOptionPane;
public class Palindrome5
{ public static void main(String args[])
{ String word = JOptionPane.showInputDialog(null, "Input String : ", "INPUT", JOptionPane.QUESTION_MESSAGE);
String subword = "";
String revword = "";
String Out = "";
int size = word.length();
boolean c;
for(int x=0; x<size; x++)
{ for(int y=x+1; y<size-x; y++)
{ subword = word.substring(x,y);
c = comparisonOfreverseword(subword);
if(c==true)
{
Out = GetLongest(subword);
}
}
}
JOptionPane.showMessageDialog(null, "Longest Palindrome : " + Out, "OUTPUT", JOptionPane.PLAIN_MESSAGE);
}
public static boolean comparisonOfreverseword(String a)
{ String rev = "";
int tempo = a.length();
boolean z=false;
for(int i = tempo-1; i>=0; i--)
{
char let = a.charAt(i);
rev = rev + let;
}
if(a.equalsIgnoreCase(rev))
{
z=true;
}
return(z);
}
public static String GetLongest(String sWord)
{
int sLength = sWord.length();
String Lpalindrome = "";
int storage = 0;
if(storage<sLength)
{
storage = sLength;
Lpalindrome = sWord;
}
return(Lpalindrome);
}
}
modified program..this program will give the correct output
package pract1;
import javax.swing.JOptionPane;
public class Palindrome5
{
public static void main(String args[])
{
String word = JOptionPane.showInputDialog(null, "Input String : ", "INPUT", JOptionPane.QUESTION_MESSAGE);
String subword = "";
String revword = "";
String Out = "";
int size = word.length();
boolean c;
String Lpalindrome = "";
int storage=0;
String out="";
for(int x=0; x<size; x++)
{ for(int y=x+1; y<=size; y++)
{ subword = word.substring(x,y);
c = comparisonOfreverseword(subword);
if(c==true)
{
int sLength = subword.length();
if(storage<sLength)
{
storage = sLength;
Lpalindrome = subword;
out=Lpalindrome;
}
}
}
}
JOptionPane.showMessageDialog(null, "Longest Palindrome : " + out, "OUTPUT", JOptionPane.PLAIN_MESSAGE);
}
public static boolean comparisonOfreverseword(String a)
{ String rev = "";
int tempo = a.length();
boolean z=false;
for(int i = tempo-1; i>=0; i--)
{
char let = a.charAt(i);
rev = rev + let;
}
if(a.equalsIgnoreCase(rev))
{
z=true;
}
return(z);
}
}
You have two bugs:
1.
for(int y=x+1; y<size-x; y++)
should be
for(int y=x+1; y<size; y++)
since you still want to go all the way to the end of the string. With the previous loop, since x increases throughout the loop, your substring sizes decrease throughout the loop (by removing x characters from their end).
2.
You aren't storing the longest string you've found so far or its length. The code
int storage = 0;
if(storage<sLength) {
storage = sLength;
...
is saying 'if the new string is longer than zero characters, then I will assume it is the longest string found so far and return it as LPalindrome'. That's no help, since we may have previously found a longer palindrome.
If it were me, I would make a static variable (e.g. longestSoFar) to hold the longest palindrome found so far (initially empty). With each new palindrome, check if the new one is longer than longestSoFar. If it is longer, assign it to longestSoFar. Then at the end, display longestSoFar.
In general, if you're having trouble 'remembering' something in the program (e.g. previously seen values) you have to consider storing something statically, since local variables are forgotten once their methods finish.
public class LongestPalindrome {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String S= "abcdcba";
printLongestPalindrome(S);
}
public static void printLongestPalindrome(String S)
{
int maxBack=-1;
int maxFront = -1;
int maxLength=0;
for (int potentialCenter = 0 ; potentialCenter < S.length();potentialCenter ++ )
{
int back = potentialCenter-1;
int front = potentialCenter + 1;
int longestPalindrome = 0;
while(back >=0 && front<S.length() && S.charAt(back)==S.charAt(front))
{
back--;
front++;
longestPalindrome++;
}
if (longestPalindrome > maxLength)
{
maxLength = longestPalindrome+1;
maxBack = back + 1;
maxFront = front;
}
back = potentialCenter;
front = potentialCenter + 1;
longestPalindrome=0;
while(back >=0 && front<S.length() && S.charAt(back)==S.charAt(front))
{
back--;
front++;
longestPalindrome++;
}
if (longestPalindrome > maxLength)
{
maxLength = longestPalindrome;
maxBack = back + 1;
maxFront = front;
}
}
if (maxLength == 0) System.out.println("There is no Palindrome in the given String");
else{
System.out.println("The Longest Palindrome is " + S.substring(maxBack,maxFront) + "of " + maxLength);
}
}
}
I have my own way to get longest palindrome in a random word. check this out
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println(longestPalSubstr(in.nextLine().toLowerCase()));
}
static String longestPalSubstr(String str) {
char [] input = str.toCharArray();
Set<CharSequence> out = new HashSet<CharSequence>();
int n1 = str.length()-1;
for(int a=0;a<=n1;a++)
{
for(int m=n1;m>a;m--)
{
if(input[a]==input[m])
{
String nw = "",nw2="";
for (int y=a;y<=m;y++)
{
nw=nw+input[y];
}
for (int t=m;t>=a;t--)
{
nw2=nw2+input[t];
}
if(nw2.equals(nw))
{
out.add(nw);
break;
}
}
}
}
int a = out.size();
int maxpos=0;
int max=0;
Object [] s = out.toArray();
for(int q=0;q<a;q++)
{
if(max<s[q].toString().length())
{
max=s[q].toString().length();
maxpos=q;
}
}
String output = "longest palindrome is : "+s[maxpos].toString()+" and the lengths is : "+ max;
return output;
}
this method will return the max length palindrome and the length of it. its a way that i tried and got the answer. and this method will run whether its a odd length or even length.
public class LongestPalindrome {
public static void main(String[] args) {
HashMap<String, Integer> result = findLongestPalindrome("ayrgabcdeedcbaghihg123444456776");
result.forEach((k, v) -> System.out.println("String:" + k + " Value:" + v));
}
private static HashMap<String, Integer> findLongestPalindrome(String str) {
int i = 0;
HashMap<String, Integer> map = new HashMap<String, Integer>();
while (i < str.length()) {
String alpha = String.valueOf(str.charAt(i));
if (str.indexOf(str.charAt(i)) != str.lastIndexOf(str.charAt(i))) {
String pali = str.substring(i, str.lastIndexOf(str.charAt(i)) + 1);
if (isPalindrome(pali)) {
map.put(pali, pali.length());
i = str.lastIndexOf(str.charAt(i));
}
}
i++;
}
return map;
}
public static boolean isPalindrome(String input) {
for (int i = 0; i <= input.length() / 2; i++) {
if (input.charAt(i) != input.charAt(input.length() - 1 - i)) {
return false;
}
}
return true;
}
}
This approach is simple.
Output:
String:abcdeedcba Value:10
String:4444 Value:4
String:6776 Value:4
String:ghihg Value:5
This is my own way to get longest palindrome. this will return the length and the palindrome word
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println(longestPalSubstr(in.nextLine().toLowerCase()));
}
static String longestPalSubstr(String str) {
char [] input = str.toCharArray();
Set<CharSequence> out = new HashSet<CharSequence>();
int n1 = str.length()-1;
for(int a=0;a<=n1;a++)
{
for(int m=n1;m>a;m--)
{
if(input[a]==input[m])
{
String nw = "",nw2="";
for (int y=a;y<=m;y++)
{
nw=nw+input[y];
}
for (int t=m;t>=a;t--)
{
nw2=nw2+input[t];
}
if(nw2.equals(nw))
{
out.add(nw);
break;
}
}
}
}
int a = out.size();
int maxpos=0;
int max=0;
Object [] s = out.toArray();
for(int q=0;q<a;q++)
{
if(max<s[q].toString().length())
{
max=s[q].toString().length();
maxpos=q;
}
}
String output = "longest palindrome is : "+s[maxpos].toString()+" and the lengths is : "+ max;
return output;
}
this method will return the max length palindrome and the length of it. its a way that i tried and got the answer. and this method will run whether its a odd length or even length.
I need to create a method that receives a String and also returns a String.
Ex input: AAABBBBCC
Ex output: 3A4B2C
Well, this is quite embarrassing and I couldn't manage to do it on the interview that I had today ( I was applying for a Junior position ), now, trying at home I made something that works statically, I mean, not using a loop which is kind of useless but I don't know if I'm not getting enough hours of sleep or something but I can't figure it out how my for loop should look like. This is the code:
public static String Comprimir(String texto){
StringBuilder objString = new StringBuilder();
int count;
char match;
count = texto.substring(texto.indexOf(texto.charAt(1)), texto.lastIndexOf(texto.charAt(1))).length()+1;
match = texto.charAt(1);
objString.append(count);
objString.append(match);
return objString.toString();
}
Thanks for your help, I'm trying to improve my logic skills.
Loop through the string remembering what you last saw. Every time you see the same letter count. When you see a new letter put what you have counted onto the output and set the new letter as what you have last seen.
String input = "AAABBBBCC";
int count = 1;
char last = input.charAt(0);
StringBuilder output = new StringBuilder();
for(int i = 1; i < input.length(); i++){
if(input.charAt(i) == last){
count++;
}else{
if(count > 1){
output.append(""+count+last);
}else{
output.append(last);
}
count = 1;
last = input.charAt(i);
}
}
if(count > 1){
output.append(""+count+last);
}else{
output.append(last);
}
System.out.println(output.toString());
You can do that using the following steps:
Create a HashMap
For every character, Get the value from the hashmap
-If the value is null, enter 1
-else, replace the value with (value+1)
Iterate over the HashMap and keep concatenating (Value+Key)
use StringBuilder (you did that)
define two variables - previousChar and counter
loop from 0 to str.length() - 1
each time get str.charat(i) and compare it to what's stored in the previousChar variable
if the previous char is the same, increment a counter
if the previous char is not the same, and counter is 1, increment counter
if the previous char is not the same, and counter is >1, append counter + currentChar, reset counter
after the comparison, assign the current char previousChar
cover corner cases like "first char"
Something like that.
The easiest approach:- Time Complexity - O(n)
public static void main(String[] args) {
String str = "AAABBBBCC"; //input String
int length = str.length(); //length of a String
//Created an object of a StringBuilder class
StringBuilder sb = new StringBuilder();
int count=1; //counter for counting number of occurances
for(int i=0; i<length; i++){
//if i reaches at the end then append all and break the loop
if(i==length-1){
sb.append(str.charAt(i)+""+count);
break;
}
//if two successive chars are equal then increase the counter
if(str.charAt(i)==str.charAt(i+1)){
count++;
}
else{
//else append character with its count
sb.append(str.charAt(i)+""+count);
count=1; //reseting the counter to 1
}
}
//String representation of a StringBuilder object
System.out.println(sb.toString());
}
In the count=... line, lastIndexOf will not care about consecutive values, and will just give the last occurence.
For instance, in the string "ABBA", the substring would be the whole string.
Also, taking the length of the substring is equivalent to subtracting the two indexes.
I really think that you need a loop.
Here is an example :
public static String compress(String text) {
String result = "";
int index = 0;
while (index < text.length()) {
char c = text.charAt(index);
int count = count(text, index);
if (count == 1)
result += "" + c;
else
result += "" + count + c;
index += count;
}
return result;
}
public static int count(String text, int index) {
char c = text.charAt(index);
int i = 1;
while (index + i < text.length() && text.charAt(index + i) == c)
i++;
return i;
}
public static void main(String[] args) {
String test = "AAABBCCC";
System.out.println(compress(test));
}
Please try this one. This may help to print the count of characters which we pass on string format through console.
import java.util.*;
public class CountCharacterArray {
private static Scanner inp;
public static void main(String args[]) {
inp = new Scanner(System.in);
String str=inp.nextLine();
List<Character> arrlist = new ArrayList<Character>();
for(int i=0; i<str.length();i++){
arrlist.add(str.charAt(i));
}
for(int i=0; i<str.length();i++){
int freq = Collections.frequency(arrlist, str.charAt(i));
System.out.println("Frequency of "+ str.charAt(i)+ " is: "+freq);
}
}
}
Java's not my main language, hardly ever use it, but I wanted to give it a shot :]
Not even sure if your assignment requires a loop, but here's a regexp approach:
public static String compress_string(String inp) {
String compressed = "";
Pattern pattern = Pattern.compile("([\\w])\\1*");
Matcher matcher = pattern.matcher(inp);
while(matcher.find()) {
String group = matcher.group();
if (group.length() > 1) compressed += group.length() + "";
compressed += group.charAt(0);
}
return compressed;
}
This is just one more way of doing it.
public static String compressor(String raw) {
StringBuilder builder = new StringBuilder();
int counter = 0;
int length = raw.length();
int j = 0;
while (counter < length) {
j = 0;
while (counter + j < length && raw.charAt(counter + j) == raw.charAt(counter)) {
j++;
}
if (j > 1) {
builder.append(j);
}
builder.append(raw.charAt(counter));
counter += j;
}
return builder.toString();
}
The following can be used if you are looking for a basic solution. Iterate through the string with one element and after finding all the element occurrences, remove that character. So that it will not interfere in the next search.
public static void main(String[] args) {
String string = "aaabbbbbaccc";
int counter;
String result="";
int i=0;
while (i<string.length()){
counter=1;
for (int j=i+1;j<string.length();j++){
System.out.println("string length ="+string.length());
if (string.charAt(i) == string.charAt(j)){
counter++;
}
}
result = result+string.charAt(i)+counter;
string = string.replaceAll(String.valueOf(string.charAt(i)), "");
}
System.out.println("result is = "+result);
}
And the output will be :=
result is = a4b5c3
private String Comprimir(String input){
String output="";
Map<Character,Integer> map=new HashMap<Character,Integer>();
for(int i=0;i<input.length();i++){
Character character=input.charAt(i);
if(map.containsKey(character)){
map.put(character, map.get(character)+1);
}else
map.put(character, 1);
}
for (Entry<Character, Integer> entry : map.entrySet()) {
output+=entry.getValue()+""+entry.getKey().charValue();
}
return output;
}
One other simple way using Multiset of guava-
import java.util.Arrays;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Multiset.Entry;
public class WordSpit {
public static void main(String[] args) {
String output="";
Multiset<String> wordsMultiset = HashMultiset.create();
String[] words="AAABBBBCC".split("");
wordsMultiset.addAll(Arrays.asList(words));
for (Entry<String> string : wordsMultiset.entrySet()) {
if(!string.getElement().isEmpty())
output+=string.getCount()+""+string.getElement();
}
System.out.println(output);
}
}
consider the below Solution in which the String s1 identifies the unique characters that are available in a given String s (for loop 1), in the second for loop build a string s2 that contains unique character and no of times it is repeated by comparing string s1 with s.
public static void main(String[] args)
{
// TODO Auto-generated method stub
String s = "aaaabbccccdddeee";//given string
String s1 = ""; // string to identify how many unique letters are available in a string
String s2=""; //decompressed string will be appended to this string
int count=0;
for(int i=0;i<s.length();i++) {
if(s1.indexOf(s.charAt(i))<0) {
s1 = s1+s.charAt(i);
}
}
for(int i=0;i<s1.length();i++) {
for(int j=0;j<s.length();j++) {
if(s1.charAt(i)==s.charAt(j)) {
count++;
}
}
s2=s2+s1.charAt(i)+count;
count=0;
}
System.out.println(s2);
}
It may help you.
public class StringCompresser
{
public static void main(String[] args)
{
System.out.println(compress("AAABBBBCC"));
System.out.println(compress("AAABC"));
System.out.println(compress("A"));
System.out.println(compress("ABBDCC"));
System.out.println(compress("AZXYC"));
}
static String compress(String str)
{
StringBuilder stringBuilder = new StringBuilder();
char[] charArray = str.toCharArray();
int count = 1;
char lastChar = 0;
char nextChar = 0;
lastChar = charArray[0];
for (int i = 1; i < charArray.length; i++)
{
nextChar = charArray[i];
if (lastChar == nextChar)
{
count++;
}
else
{
stringBuilder.append(count).append(lastChar);
count = 1;
lastChar = nextChar;
}
}
stringBuilder.append(count).append(lastChar);
String compressed = stringBuilder.toString();
return compressed;
}
}
Output:
3A4B2C
3A1B1C
1A
1A2B1D2C
1A1Z1X1Y1C
The answers which used Map will not work for cases like aabbbccddabc as in that case the output should be a2b3c2d2a1b1c1.
In that case this implementation can be used :
private String compressString(String input) {
String output = "";
char[] arr = input.toCharArray();
Map<Character, Integer> myMap = new LinkedHashMap<>();
for (int i = 0; i < arr.length; i++) {
if (i > 0 && arr[i] != arr[i - 1]) {
output = output + arr[i - 1] + myMap.get(arr[i - 1]);
myMap.put(arr[i - 1], 0);
}
if (myMap.containsKey(arr[i])) {
myMap.put(arr[i], myMap.get(arr[i]) + 1);
} else {
myMap.put(arr[i], 1);
}
}
for (Character c : myMap.keySet()) {
if (myMap.get(c) != 0) {
output = output + c + myMap.get(c);
}
}
return output;
}
O(n) approach
No need for hashing. The idea is to find the first Non-matching character.
The count of each character would be the difference in the indices of both characters.
for a detailed answer: https://stackoverflow.com/a/55898810/7972621
The only catch is that we need to add a dummy letter so that the comparison for
the last character is possible.
private static String compress(String s){
StringBuilder result = new StringBuilder();
int j = 0;
s = s + '#';
for(int i=1; i < s.length(); i++){
if(s.charAt(i) != s.charAt(j)){
result.append(i-j);
result.append(s.charAt(j));
j = i;
}
}
return result.toString();
}
The code below will ask the user for user to input a specific character to count the occurrence .
import java.util.Scanner;
class CountingOccurences {
public static void main(String[] args) {
Scanner inp = new Scanner(System.in);
String str;
char ch;
int count=0;
System.out.println("Enter the string:");
str=inp.nextLine();
System.out.println("Enter th Char to see the occurence\n");
ch=inp.next().charAt(0);
for(int i=0;i<str.length();i++)
{
if(str.charAt(i)==ch)
{
count++;
}
}
System.out.println("The Character is Occuring");
System.out.println(count+"Times");
}
}
public static char[] compressionTester( char[] s){
if(s == null){
throw new IllegalArgumentException();
}
HashMap<Character, Integer> map = new HashMap<>();
for (int i = 0 ; i < s.length ; i++) {
if(!map.containsKey(s[i])){
map.put(s[i], 1);
}
else{
int value = map.get(s[i]);
value++;
map.put(s[i],value);
}
}
String newer="";
for( Character n : map.keySet()){
newer = newer + n + map.get(n);
}
char[] n = newer.toCharArray();
if(s.length > n.length){
return n;
}
else{
return s;
}
}
package com.tell.datetime;
import java.util.Stack;
public class StringCompression {
public static void main(String[] args) {
String input = "abbcccdddd";
System.out.println(compressString(input));
}
public static String compressString(String input) {
if (input == null || input.length() == 0)
return input;
String finalCompressedString = "";
String lastElement="";
char[] charArray = input.toCharArray();
Stack stack = new Stack();
int elementCount = 0;
for (int i = 0; i < charArray.length; i++) {
char currentElement = charArray[i];
if (i == 0) {
stack.push((currentElement+""));
continue;
} else {
if ((currentElement+"").equalsIgnoreCase((String)stack.peek())) {
stack.push(currentElement + "");
if(i==charArray.length-1)
{
while (!stack.isEmpty()) {
lastElement = (String)stack.pop();
elementCount++;
}
finalCompressedString += lastElement + "" + elementCount;
}else
continue;
}
else {
while (!stack.isEmpty()) {
lastElement = (String)stack.pop();
elementCount++;
}
finalCompressedString += lastElement + "" + elementCount;
elementCount=0;
stack.push(currentElement+"");
}
}
}
if (finalCompressedString.length() >= input.length())
return input;
else
return finalCompressedString;
}
}
public class StringCompression {
public static void main(String[] args){
String s = "aabcccccaaazdaaa";
char check = s.charAt(0);
int count = 0;
for(int i=0; i<s.length(); i++){
if(s.charAt(i) == check) {
count++;
if(i==s.length()-1){
System.out.print(s.charAt(i));
System.out.print(count);
}
} else {
System.out.print(s.charAt(i-1));
System.out.print(count);
check = s.charAt(i);
count = 1;
if(i==s.length()-1){
System.out.print(s.charAt(i));
System.out.print(count);
}
}
}
}
// O(N) loop through entire character array
// match current char with next one, if they matches count++
// if don't then just append current char and counter value and then reset counter.
// special case is the last characters, for that just check if count value is > 0, if it's then append the counter value and the last char
private String compress(String str) {
char[] c = str.toCharArray();
String newStr = "";
int count = 1;
for (int i = 0; i < c.length - 1; i++) {
int j = i + 1;
if (c[i] == c[j]) {
count++;
} else {
newStr = newStr + c[i] + count;
count = 1;
}
}
// this is for the last strings...
if (count > 0) {
newStr = newStr + c[c.length - 1] + count;
}
return newStr;
}
public class StringCompression {
public static void main(String... args){
String s="aabbcccaa";
//a2b2c3a2
for(int i=0;i<s.length()-1;i++){
int count=1;
while(i<s.length()-1 && s.charAt(i)==s.charAt(i+1)){
count++;
i++;
}
System.out.print(s.charAt(i));
System.out.print(count);
}
System.out.println(" ");
}
}
This is a leet code problem 443. Most of the answers here uses StringBuilder or a HashMap, the actual problem statement is to solve using the input char array and in place array modification.
public int compress(char[] chars) {
int startIndex = 0;
int lastArrayIndex = 0;
if (chars.length == 1) {
return 1;
}
if (chars.length == 0) {
return 0;
}
for (int j = startIndex + 1; j < chars.length; j++) {
if (chars[startIndex] != chars[j]) {
chars[lastArrayIndex] = chars[startIndex];
lastArrayIndex++;
if ((j - startIndex) > 1) {
for (char c : String.valueOf(j - startIndex).toCharArray()) {
chars[lastArrayIndex] = c;
lastArrayIndex++;
}
}
startIndex = j;
}
if (j == chars.length - 1) {
if (j - startIndex >= 1) {
j = chars.length;
chars[lastArrayIndex] = chars[startIndex];
lastArrayIndex++;
for (char c : String.valueOf(j - startIndex).toCharArray()) {
chars[lastArrayIndex] = c;
lastArrayIndex++;
}
} else {
chars[lastArrayIndex] = chars[startIndex];
lastArrayIndex++;
}
}
}
return lastArrayIndex;
}
}