I want to get specific combination of permutation of string like alphabet. To understand me, I'll show you the code that I using:
public class PermutationExample {
public static List<String> getPermutation(String input) {
List<String> collection = null;
if (input.length() == 1) {
collection = new ArrayList<String>();
collection.add(input);
return collection;
} else {
collection = getPermutation(input.substring(1));
Character first = input.charAt(0);
List<String> result = new ArrayList<String>();
for (String str : collection) {
for (int i = 0; i < str.length(); i++) {
String item = str.substring(0, i) + first
+ str.substring(i);
result.add(item);
}
String item = str.concat(first.toString());
result.add(item);
}
return result;
}
}
public static void main(String[] args) {
System.out.println(PermutationExample.getPermutation("ABCD"));
}
}
This code works well and i can get every combination, I can take it from the list, if I need 5-th element, I can receive it. But if the string is the alphabet ... , didn't works, it's too big. What I have to do, to get the specific element like 1221-th from all 26! combinations ?
I solved a similar problem a while ago, only in python.
If what you need is simply the n-th permutation, then you can do a lot better then generating every permutation and returning the n-th, if you try to think about generating only the permutation you need.
You can do this "simply" by figuring out what should be the element in front for the number of permutations you want, and then what should be the remaining of the elements recursively.
Assume a collection of values [0, ... ,X], for any values such that col[n] < col[n+1]
For N elements, there are N! possible permutations, the case when the collection will be perfectly reversed.
We will see the change in the head of the collection after each (N-1)! permutations, so if n < (N-1)!, the head is the head. You then have a remaining number of permutations, and you can apply the same logic recursively.
Does this help? I know it's fairly high level and you'll have to think a bit about it, but maybe it'll get you on the right track.
Related
I a having two string's
Here the + is missing after 5 characters so the answer is +5|. The logic I wrote has a problem when I use list1.contains(s) and if the number s is more than once then also index will increase and the wrong position will be saved as +1| which is wrong.
Here I am facing one more issue difference in list I am not getting the answer.
String s1 = "7 + 8 = 7 8";
String s2 = "7 + 8 = 7 + 8";
List<String> list1 = Arrays.asList(s1.split("\\s+"));
List<String> list2 = Arrays.asList(s2.split("\\s+"));
int index = 0;
for(String s : list2){
if(list1.contains(s)){
index++;
}else{
System.out.print(s+index+"|");
}
}
This function I created to find the difference, sometimes it returns the difference but sometimes it does not
public static <T> List<T> difference(List<T> answer, List<T> header) {
List<T> toReturn = new ArrayList<>(answer);
toReturn.removeAll(header);
return toReturn;
}
Your question indicates that a difference is not only defined by the elements being present in both lists but that their order matters too, i.e. 1,2,3 would be different from 3,2,1.
Hence, don't use contains() as this only reports whether one list contains an element but doesn't take the order into account.
To find positional differences, you need to compare elements at the same index. Here's a simple example of what that could look like (note that this would be inefficient when using LinkedList in which case you'd better use an iterator).
<T> int findFirstDifference(List<T> list1, List<T> list2) {
//restrict iteration to the size of the smaller list
int smallerSize = Math.min(list1.size(), list2.size());
for( int index = 0; index < smallerSize; index++) {
T e1 = list1.get(index);
T e2 = list2.get(index);
//objects are different, this is the first difference
if(!Objects.equals(e1, e2)) {
return index;
}
}
//at this point the smaller list completely matches the start of the larger list
//if there is a larger list the first difference is the index after the end of the matching portion
if( list1.size() != list2.size() ) {
return smallerSize;
}
//no difference found
return -1;
}
I have a map:
Map<String, String> abc = new HashMap<>();
"key1" : "value1",
"key2" : "value2"
And an array:
String[] options= {"value1", "value2", "value3"}
I am creating this array as following (I am using following method to do something else which is not relevant to the question that I am asking here):
public String[] getOptions() {
List<String> optionsList = getOptionsFromAMethod(WebElementA);
String[] options = new String[optionsList.size()];
options = optionsList.toArray(options);
return options;
}
What is the best way to verify if String[] contains each value from Map?
I am thinking about doing this:
for (Object value : abc.values()) {
Arrays.asList(options).contains(value);
}
Explanation
Your current approach creates an ArrayList (from java.util.Arrays, not to confuse with the regular ArrayList from java.util) wrapping the given array.
You then call, for each value of the map, the ArrayList#contains method. However this method is very slow. It walks through the whole list in order to search for something.
Your current approach thus yields O(n^2) which doesn't scale very well.
Solution
We can do better by using a data-structure which is designed for a fast contains query, namely a HashSet.
So instead of putting all your values into an ArrayList we will put them into a HashSet whose contains method is fast:
boolean doesContainAll = true;
HashSet<String> valuesFromArray = new HashSet<>(Arrays.asList(options));
for (String value : abc.values()) {
if (!valuesFromArray.contains(value)) {
doesContainAll = false;
break;
}
}
// doesContainAll now is correctly set to 'true' or 'false'
The code now works in O(n) which is far better and also optimal in terms of complexity.
Of course you can optimize further to speedup by constant factors. For example you can first check the size, if options.length is greater than abc.values().size() then you can directly return with false.
JStream solution
You can also use Java 8 and Streams to simplify the above code, the result and also the procedure behind the scenes is the same:
HashSet<String> valuesFromArray = new HashSet<>(Arrays.asList(options));
boolean doesContainAll = abc.values().stream()
.allMatch(valuesFromArray::contains);
Insights of ArrayList#contains
Let's take a closer look into java.util.Arrays.ArrayList. You can find its code here.
Here is its code for the contains method:
public boolean contains(Object o) {
return indexOf(o) != -1;
}
Lets see how indexOf is implemented:
public int indexOf(Object o) {
E[] a = this.a;
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
} else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}
So indeed, in all cases the method will traverse from left to right through the source array in order to find the object. There is no fancy method that is able to directly access the information whether the object is contained or not, it runs in O(n) and not in O(1).
Note on duplicates
If either of your data may contain duplicates and you plan to count them individually, then you will need a slightly different approach since contains will not bother for the amount of duplicates.
For this you may collect your abc.values() first into a List for example. Then, every time you checked an element, you will remove the matched element from the List.
Alternatively you can setup a HashMap<String, Integer> which counts for every element its occurrences. Then, every time you checked an element, decrease the counter by one.
You can use https://docs.oracle.com/javase/7/docs/api/java/util/List.html#containsAll(java.util.Collection)
Arrays.asList("value1", "value2", "value3").containsAll(abc.values())
I would recommend using a stream:
final List<String> optionsList = Arrays.asList(options);
abc.values().stream().allMatch(optionsList::contains);
I have the following code which sorts a mixed array of items while maintaining the position of types:
For example:
[20, "abc", "moose", 2,1] turns into [1, "abc", "moose", 2, 20]
Algorithm:
public class Algorithm {
public static String[] sortMixedArray(String[] input){
if (input.length == 0){
return input;
}
// make new arraylist for strings and numbers respectively
List<String> strs = new ArrayList<String>();
List<Integer> numbers = new ArrayList<Integer>();
// add values to the arraylist they belong to
for (String item : input){
if (NumberUtils.isNumber(item)){
numbers.add(Integer.valueOf(item));
} else {
strs.add(item);
}
}
// sort for O(nlogn)
Collections.sort(strs);
Collections.sort(numbers);
// reuse original array
for (int i = 0; i < input.length; i++){
if (NumberUtils.isNumber(input[i])) {
input[i] = String.valueOf(numbers.remove(0));
} else {
input[i] = strs.remove(0);
}
}
return input;
}
public static void main(String[] args) {
String[] test = new String[] {"moo", "boo"};
System.out.println(Arrays.toString(sortMixedArray(test)));
}
I have a two-part question:
1. Is switching between array and arraylist efficient? That is, should I have used arrays everywhere instead of arraylist if my input MUST be an array.
2. What is the best way to place arraylist items back into a array? I am checking for type, is there a better way?
1.If you do it the way you have it in your code then it's perfectly fine. If you know beforehand how many elements you will have it's better to use arrays but thats not the case in your example.
2.The best and easiest way is to use the toArray() function of the List interface.
ArrayList<String> list = ...;
String[] array = list.toArray(new String[list.size()]);
But this won't work for your code since you are merging two lists into one array. You can still improve your code a bit because you do not actually have to remove the items from the lists when putting them back in the array. This safes some computation since removing the first element from an ArrayList is very inefficient (O(N) runtime per remove operation).
for (int i = 0, s = 0, n = 0; i < input.length; i++) {
if (NumberUtils.isNumber(input[i])) {
input[i] = Integer.toString(numbers.get(n++));
} else {
input[i] = strs.get(s++);
}
}
No but it highly unlikely to matter unless you have a million of elements.
Do whatever you believe is simplest and most efficient for you, the developer.
BTW the least efficient operations is remove(0) which is O(N) so you might change that.
I am trying to work out the solution to the above problem and I came up with this
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class Subset_K {
public static void main(String[]args)
{
Set<String> x;
int n=4;
int k=2;
int arr[]={1,2,3,4};
StringBuilder sb=new StringBuilder();
for(int i=1;i<=(n-k);i++)
sb.append("0");
for(int i=1;i<=k;i++)
sb.append("1");
String bin=sb.toString();
x=generatePerm(bin);
Set<ArrayList <Integer>> outer=new HashSet<ArrayList <Integer>>();
for(String s:x){
int dec=Integer.parseInt(s,2);
ArrayList<Integer> inner=new ArrayList<Integer>();
for(int j=0;j<n;j++){
if((dec&(1<<j))>0)
inner.add(arr[j]);
}
outer.add(inner);
}
for(ArrayList<Integer> z:outer){
System.out.println(z);
}
}
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;
}
}
I am working on a 4 element set for test purpose and using k=2. What I try to do is initially generate a binary string where k bits are set and n-k bits are not set. Now using this string I find all the possible permutations of this string. And then using these permutations I output the respective element in the set. Now i cant figure out the complexity of this code because I used the generatePerm method from someone else. Can someone help me with the time complexity of the generatePerm method and also the overall time complexity of my solution. I found other recursive implementation of this problem in here Find all subsets of length k in an array However I cant figure out the complexity of it either. So need some help there.
Also I was trying to re-factor my code so that its not just for integers but for all types of data. I dont have much experience with generics. so when I try to modify ArrayList< Integer> to ArrayList< ?> in line 21 eclipse says
Cannot instantiate the type ArrayList< ?>
How do I correct that?
You can use ArrayList<Object> throughout. That will accept any kind of object. If you want a specific type that is determined by the calling code, you will need to introduce a generic type parameter.
Note that in your generatePerm method, you should not use the test
if (input == "")
Instead, you should use:
if ("".equals(input))
Your current code will only succeed if input is the interned string "". It will not work, for instance, if input is computed as a substring() with zero length. In general you should always compare strings with .equals() rather than with == (except under very specific conditions when you are looking for object identity rather than object equality).
I have an arraylist of Strings that want to have all possible combinations stored into another collection.
For example:
[air,bus,car]
->
[air]
[bus]
[car]
[air,bus]
[air,car]
[bus,air]
[bus,car]
[car,air]
[car,bus]
[air,bus,car]
[air,car,bus]
...
[car,bus,air]
Repetitions are not important. The code right now I have is:
public ArrayList<String> comb(ArrayList<String> wrds, ArrayList<String> str, int size)
{
ArrayList<String> s = new ArrayList<String>();
s.addAll(str);
if(size != a1.size())
{
Iterator e = a1.iterator();
while(e.hasNext())
{
s.add((String)e.next());
}
size++;
}
}
I am trying to get it to recursively call itself so it can store the combinations. Can I get any help as to where or which part I am missing in my code?
Seeing as this is homework, I'll try to give you background to the answer.
The key to solving this is to use recursion.
First imagine you have two items in your array. You'd could remove the first item to give you your first combination. Adding the remaining item to the first item gives you the second combination. Removing the second item give you the third combination. Adding the remaining item gives you the forth combination. If you had ["air", "bus"] it'd be something like:
["air"]
["air", "bus"]
["bus"]
["bus", "air"]
A method that returns that might look like:
String[][] combinations(String[] strings)
The important things to note are the an array containing a single string can be passed to this method and it can return an array containing an array with a single string in it.
The problem is complicated a little because you have to keep a tally of the string combinations, so before we get to solving that, it's important that you understand recursion.
Imagine you wanted to write a multiplication method that takes two numbers and multiplies them but you only have addition and subtraction at your disposal. You could write a recursive function that adds one of the numbers to itself until the other number reaches an exit condition, something like:
public int multiply(int value1, int value2)
{
if (value1 > 1)
{
int remaining = value1 - 1;
return value2 + multiply(remaining, value2);
}
else
{
return value2;
}
}
You can do just the same thing with an array, only instead to exiting when the a value hit's 1 you exit when the array contains one item, something like:
public String[][] combinations(String[] strings)
{
if (strings.length > 1)
{
...
}
else
{
return new String[][]{strings};
}
}
For reasons with the Java API it's much easier to use java.util.List rather than arrays so you want something like:
public List<List<String>> combinations(List<String> strings)
{
if (strings.size()> 1)
{
...
}
else
{
List<List<String>> result = new ArrayList<List<String>>();
result.add(strings);
return result;
}
}
Now it's the ... that's the important bit. You need to keep an list-of-lists that will be the result and iterate over the strings. For each of the strings you can add that string to the results and then you need create a sub-list that is minus the current string, which you use to call the combinations method again iterating over the result adding the current string each list it contains. In code it looks something like:
public List<List<String>> combinations(List<String> strings)
{
if (strings.size() > 1)
{
List<List<String>> result = new ArrayList<List<String>>();
for (String str : strings)
{
List<String> subStrings = new ArrayList<String>(strings);
subStrings.remove(str);
result.add(new ArrayList<String>(Arrays.asList(str)));
for (List<String> combinations : combinations(subStrings))
{
combinations.add(str);
result.add(combinations);
}
}
return result;
}
else
{
List<List<String>> result = new ArrayList<List<String>>();
result.add(new ArrayList<String>(strings));
return result;
}
}
In summary, what you're doing is reducing the list of strings down to a single item, then combining it with the preceeding items to produce all the possible combinations as the thread returns up the call stack.
public static void combination(Object[] array){
for(int x = 0; x < (1 << array.length); x++){
System.out.print("[");
for(int y = 0; y < array.length; y++){
if(checkIsOn(x, y){
System.out.print(array[y]);
}
}
System.out.println("]");
}
}
public static boolean checkIsOn(int mast, int position){
return (mast & (1 << position) > 0);
}
Use the list as a parameter to the recursive function. You can call the function from within itself with a new list containing everything except the first item.