I have 10,000 items in a set whereby each must be made into triads.
I need an algorithm to efficiently find each triad.
For example:
{A,B,C,D,...}
1.AAA
2.AAB
3.AAC
4.AAD
...
all the way to ZZY, ZZZ.
The method I'm using is very inefficient, I created a nested forloop of 3 which iterates through an array, which has a run-time of O(N^3) and terrible on performance obvious. Which kind of algo and data structure would be better for this? Thank you
Function to print all permutations of K length from a set of n characters with
repetition of characters:
static void printKLengthPerm(char[] set, String prefix, int n, int k)
{
if (k == 0)
{
System.out.println(prefix);
return;
}
for (int i = 0; i < n; i++)
{
String newPrefix = prefix + set[i];
printKLengthPerm(set, newPrefix, n, k - 1);
}
}
Calling the function to print all permutations of 3 length from a set all capital english alphabets:
char[] set = new char[26];
for(int i = 0; i < 26; i++)
set[i] = (char)(i+65);
int n = set.length;
printKLengthPerm(set, "", n, 3);
Related
Following this question, I want to now code "6 choose 2" times "4 choose 2." By that I mean, lets say I have 6 characters "A B C D E F." The first time I choose any two characters to delete. The 2nd time I want to choose 2 different letters to delete and then I append the results of these two trials. Hence, I will receive 90("6 choose 2" times "4 choose 2") eight character strings. The characters in the pattern are from the same pattern {1,2,3,4,5, 6}. All the characters are unique and no repetition.
Here is what I have so far.
public String[] genDelPatterns(String design){
char[] data = design.toCharArray();
String[] deletionPatterns = new String[15];
int x = 0;
StringBuilder sb = new StringBuilder("");
int index = 0;
for(int i = 0; i < (6-1); i++){
for(int j = i+1; j < 6; j++){
for(int k= 0; k < 6; k++){
if((k != j) && (k != i))
sb.append(String.valueOf(data[k]));
}
deletionPatterns[x++] = sb.toString();
sb = new StringBuilder("");
}
}
return deletionPatterns;
}
public String[] gen8String(String[] pattern1, String[] pattern2){
String[] combinedPatterns = new String[225];
int k = 0;
for(int i = 0; i < 15; i++)
{
for(int j = 0; j < 15; j++)
combinedPatterns[k++] = pattern1[i] + pattern2[j];
}
return combinedPatterns;
}
I will be calling the methods like this:
gen8String(genDelPatterns("143256"), genDelPatterns("254316"));
Currently, I am generating all the possible 8 letter strings. But I want to only generate the 8 character strings according to the aforementioned specifications. I am really stuck on how I can elegantly do this multiplication. The only way I can think of is to make another method that does "4 choose 2" and then combine the 2 string arrays. But this seems very roundabout.
EDIT: An example of an 8 character string would be something like "14322516", given the inputs I have already entered when calling gen8String, (143256,254316). Note that the first 4 characters are derived from 143256 with the 5 and 6 deleted. But since I deleted 5 and 6 in the first trail, I am no longer allowed to delete the same things in the 2nd pattern. Hence, I deleted the 3 and 4 from the 2nd pattern.
you have a chain of methods , each one called a variation itself.
For so, my advice is to use a recursive method!
to achieve your goal you have to have a little experience with this solution.
A simple example of a method that exploits the recursion:
public static long factorial(int n) {
if (n == 1) return 1;
return n * factorial(n-1);
}
I can also suggest you to pass objects (constructed to perfection) for the method parameter, if is too complex to pass simple variables
This is the heart of this solution in my opinion.
While what you tried to do is definitely working, it seems you are looking for other way to implement it. Here is the skeleton of what I would do given the small constrains.
// Very pseudo code
// FOR(x,y,z) := for(int x=y; x<z;x++)
string removeCharacter(string s, int banA, int banB){
string ret = "";
FOR(i,1,7){
if(i != banA && i != banB){
ret += s[i];
}
}
return ret;
}
List<string> Generate(s1,s2){
List<string> ret = new List<string>();
FOR(i,1,7) FOR(j,i+1,7) FOR(m,1,7) FOR(n,m+1,7){
if(m != i && m != j && n != i && n != j){
string firstHalf = removeCharacter(s1,i,j);
string secondHalf = removeCharacter(s2,m,n);
ret.Add(firstHalf + secondHalf);
}
}
return ret;
}
This should generate all possible 8-characters string.
Here is the solution I came up with. Doesn't really take "mathematical" approach, I guess. But it does the job.
//generating a subset of 90 eight character strings (unique deletion patterns)
public static String[] gen8String(String[] pattern1, String[] pattern2){
String[] combinedSubset = new String[90]; //emty array for the subset of 90 strings
String combinedString = ""; //string holder for each combined string
int index = 0; //used for combinedSubset array
int present = 0; //used to check if all 6 characters are present
for(int i = 0; i < 15; i++){
for(int j = 0; j < 15; j++){
combinedString = pattern1[i] + pattern2[j]; //combine both 4 letter strings into 8 char length string
char[] parsedString = combinedString.toCharArray(); //parse into array
//check if all 6 characters are present
for(int k = 1; k <= 6; k++)
{
if(new String(parsedString).contains(k+"")) {
present++;
}
else
break;
//if all 6 are present, then add it to combined subset
if(present == 6)
combinedSubset[index++] = combinedString;
}
present = 0;
}
}
return combinedSubset;
}
Problem
Given a string s and m queries. For each query delete the K-th occurrence of a character x.
For example:
abcdbcaab
5
2 a
1 c
1 d
3 b
2 a
Ans abbc
My approach
I am using BIT tree for update operation.
Code:
for (int i = 0; i < ss.length(); i++) {
char cc = ss.charAt(i);
freq[cc-97] += 1;
if (max < freq[cc-97]) max = freq[cc-97];
dp[cc-97][freq[cc-97]] = i; // Counting the Frequency
}
BIT = new int[27][ss.length()+1];
int[] ans = new int[ss.length()];
int q = in.nextInt();
for (int i = 0; i < q; i++) {
int rmv = in.nextInt();
char c = in.next().charAt(0);
int rr = rmv + value(rmv, BIT[c-97]); // Calculating the original Index Value
ans[dp[c-97][rr]] = Integer.MAX_VALUE;
update(rmv, 1, BIT[c-97], max); // Updating it
}
for (int i = 0; i < ss.length(); i++) {
if (ans[i] != Integer.MAX_VALUE) System.out.print(ss.charAt(i));
}
Time Complexity is O(M log N) where N is length of string ss.
Question
My solution gives me Time Limit Exceeded Error. How can I improve it?
public static void update(int i , int value , int[] arr , int xx){
while(i <= xx){
arr[i ]+= value;
i += (i&-i);
}
}
public static int value(int i , int[] arr){
int ans = 0;
while(i > 0){
ans += arr[i];
i -= (i &- i);
}
return ans ;
}
There are key operations not shown, and odds are that one of them (quite likely the update method) has a different cost than you think. Furthermore your stated complexity is guaranteed to be wrong because at some point you have to scan the string which is at minimum O(N).
But anyways the obviously right strategy here is to go through the queries, separate them by character, and then go through the queries in reverse order to figure out the initial positions of the characters to be suppressed. Then run through the string once, emitting characters only when it fits. This solution, if implemented well, should be doable in O(N + M log(M)).
The challenge is how to represent the deletions efficiently. I'm thinking of some sort of tree of relative offsets so that if you find that the first deletion was 3 a you can efficiently insert it into your tree and move every later deletion after that one. This is where the log(M) bit will be.
I'm trying to make an encryption program where the user enters a message and then converts the "letters into numbers".
For example the user enters a ABCD as his message. The converted number would be 1 2 3 4 and the numbers are stored into a one dimensional integer array. What I want to do is be able to put it into a 2x2 matrix with the use of two dimensional arrays.
Here's a snippet of my code:
int data[] = new int[] {10,20,30,40};
*for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
for (int ctr=0; ictr<data.length(); ictr++){
a[i][j] = data[ctr];}
}
}
I know there's something wrong with the code but I am really lost.
How do I output it as the following?
10 20
30 40
(instead of just 10,20,30,40)
Here's one way of doing it. It's not the only way. Basically, for each cell in the output, you calculate the corresponding index of the initial array, then do the assignment.
int data[] = new int[] {10, 20, 30, 40, 50, 60};
int width = 3;
int height = 2;
int[][] result = new int[height][width];
for(int i = 0; i < height; i++) {
for(int j = 0; j < width; j++) {
result[i][j] = data[i * width + j];
}
}
Seems like you want to output a 2xn matrix while still having the values stored in a one-dimensional array. If that's the case then you can to this:
Assume the cardinality m of your set of values is known. Then, since you want it to be 2 rows, you calculate n=ceil(m/2), which will be the column count for your 2xn matrix. Note that if m is odd then you will only have n-1 values in your second row.
Then, for your array data (one-dimension array) which stores the values, just do
for(i=0;i<2;i++) // For each row
{
for(j=0;j<n;j++) // For each column,
// where index is baseline+j in the original one-dim array
{
System.out.print(data[i*n+j]);
}
}
But make sure you check the very last value for an odd cardinality set. Also you may want to do Integer.toString() to print the values.
Your code is close but not quite right. Specifically, your innermost loop (the one with ctr) doesn't accomplish much: it really just repeatedly sets the current a[i][j] to every value in the 1-D array, ultimately ending up with the last value in the array in every cell. Your main problem is confusion around how to work ctr into those loops.
There are two general approaches for what you are trying to do here. The general assumption I am making is that you want to pack an array of length L into an M x N 2-D array, where M x N = L exactly.
The first approach is to iterate through the 2D array, pulling the appropriate value from the 1-D array. For example (I'm using M and N for sizes below):
for (int i = 0, ctr = 0; i < M; ++ i) {
for (int j = 0; j < N; ++ j, ++ ctr) {
a[i][j] = data[ctr];
}
} // The final value of ctr would be L, since L = M * N.
Here, we use i and j as the 2-D indices, and start ctr at 0 and just increment it as we go to step through the 1-D array. This approach has another variation, which is to calculate the source index explicitly rather than using an increment, for example:
for (int i = 0; i < M; ++ i) {
for (int j = 0; j < N; ++ j) {
int ctr = i * N + j;
a[i][j] = data[ctr];
}
}
The second approach is to instead iterate through the 1-D array, and calculate the destination position in the 2-D array. Modulo and integer division can help with that:
for (int ctr = 0; ctr < L; ++ ctr) {
int i = ctr / N;
int j = ctr % N;
a[i][j] = data[ctr];
}
All of these approaches work. Some may be more convenient than others depending on your situation. Note that the two explicitly calculated approaches can be more convenient if you have to do other transformations at the same time, e.g. the last approach above would make it very easy to, say, flip your 2-D matrix horizontally.
check this solution, it works for any length of data
public class ArrayTest
{
public static void main(String[] args)
{
int data[] = new int[] {10,20,30,40,50};
int length,limit1,limit2;
length=data.length;
if(length%2==0)
{
limit1=data.length/2;
limit2=2;
}
else
{
limit1=data.length/2+1;
limit2=2;
}
int data2[][] = new int[limit1][limit2];
int ctr=0;
//stores data in 2d array
for(int i=0;i<limit1;i++)
{
for(int j=0;j<limit2;j++)
{
if(ctr<length)
{
data2[i][j] = data[ctr];
ctr++;
}
else
{
break;
}
}
}
ctr=0;
//prints data from 2d array
for(int i=0;i<limit1;i++)
{
for(int j=0;j<limit2;j++)
{
if(ctr<length)
{
System.out.println(data2[i][j]);
ctr++;
}
else
{
break;
}
}
}
}
}
I am making a java program that will Use “brute force” by generating all possible permutations and checking if any are matching. Example: If G1 = “0-1 0-2 1-2 1-3 2-3” and G2 = “1-3 2-0 0-3 1-2 1-0” then the permutation 0123 → 2310 does not match, but 0123 → 2013 does match.
I need to make a graph class the represents the graph as a 2-D boolean array and has member functions to check if 2 vertices are an edge and to print a graph. The constructor should use the above string representing a list of edges.
I need to know how I would take the string in that format and put it in an array.
Overall, I want to find out if the two graphs are isomorphic.
The code below is the permutation generator.
// Generator of all permutations of: 0,1,2,...,n-1
public class PermutationGenerator
{
// private data
private int[] perm;
private boolean first;
// constructor
public PermutationGenerator (int n)
{
perm = new int [n];
first = true;
}
public int[] next ()
{
int n = perm.length;
// starting permutation: 0 1 2 3 ... n-1
if (first)
{
first = false;
for (int i = 0 ; i < n ; i++)
perm [i] = i;
return perm;
}
// construct the next permutation
// find largest k so that perm[k] < perm[k+1]; if none, finish
int i, j, k, l;
for (k = n - 2 ; k >= 0 && perm [k] >= perm [k + 1] ; k--)
;
if (k < 0)
return null; // no more
// find largest l so that perm[k] < perm[l]
for (l = n - 1 ; l >= 0 && perm [k] >= perm [l] ; l--)
;
// swap perm[k] and perm[l]
swap (perm, k, l);
// reverse perm[k+1]...perm[n-1]
for (i = k + 1, j = n - 1 ; i < j ; i++, j--)
swap (perm, i, j);
return perm;
}
// swap a[i] and a[j]
private static void swap (int a[], int i, int j)
{
int temp = a [i];
a [i] = a [j];
a [j] = temp;
}
}
I think there is an easier way to determine if the two graphs (represented by strings g1 and g2) are the same - how about:
new HashSet<String>(Arrays.asList(g1.split(" "))).equals(
new HashSet<String>(Arrays.asList(g2.split(" ")))
(Let me know if I'm missing something)
If you still wanted to parse the string and use it to fill a boolean adjacency matrix you could do this:
Split adjacency-list string on spaces to form an array, call it arr.
Loop over arr, split each element on "-" to form a new array, call it x (one such array will be produced for each element of arr, since you're looping over it).
Set matrix[i][j] to true, where i and j are the first and second elements of x (respectively) parsed as integers.
Split the string on the space using String.split() to get an array of strings {0-1,0-2,1-2,1-3,2-3}.
Loop through these and split on the - to pull each number which you can then put into an array. Not very efficient but simple way to parse your example string.
I am trying to find all substrings within a given string. For a random string like rymis the subsequences would be [i, is, m, mi, mis, r, ry, rym, rymi, rymis, s, y, ym, ymi, ymis]. From Wikipedia, a string of a length of n will have n * (n + 1) / 2 total substrings.
Which can be found by doing the following snippet of code:
final Set<String> substring_set = new TreeSet<String>();
final String text = "rymis";
for(int iter = 0; iter < text.length(); iter++)
{
for(int ator = 1; ator <= text.length() - iter; ator++)
{
substring_set.add(text.substring(iter, iter + ator));
}
}
Which works for small String lengths but obviously slows down for larger lengths as the algorithm is near O(n^2).
Also reading up on Suffix Trees which can do insertions in O(n) and noticed the same subsequences could be obtained by repeatedly inserting substrings by removing 1 character from the right until the string is empty. Which should be about O(1 + … + (n-1) + n) which is a summation of n -> n(n+1)/2 -> (n^2 + n)/ 2, which again is near O(n^2). Although there seems to be some Suffix Trees that can do insertions in log2(n) time which would be a factor better being O(n log2(n)).
Before I delve into Suffix Trees is this the correct route to be taking, is there some another algorithm that would be more efficient for this, or is O(n^2) as good as this will get?
I am fairly sure you can't beat O(n^2) for this as has been mentioned in comments to the question.
I was interested in different ways of coding that so I made one quickly, and I decided to post it here.
The solution I put here isn't asymptotically faster I don't think, but when counting the inner and outer loops there are less. There are also less duplicate insertions here - no duplicate insertions.
String str = "rymis";
ArrayList<String> subs = new ArrayList<String>();
while (str.length() > 0) {
subs.add(str);
for (int i=1;i<str.length();i++) {
subs.add(str.substring(i));
subs.add(str.substring(0,i));
}
str = str.substring(1, Math.max(str.length()-1, 1));
}
This is an inverted way of your example, but still o(n^2).
string s = "rymis";
ArrayList<string> al = new ArrayList<string>();
for(int i = 1; i < s.length(); i++){//collect substrings of length i
for(int k = 0; k < s.length(); k++){//start index for sbstr len i
if(i + k > s.length())break;//if the sbstr len i runs over end of s move on
al.add(s.substring(k, k + i));//add sbstr len i at index k to al
}
}
Let me see if I can post a recursive example. I started doing a couple recursive tries and came up with this iterative approach using dual sliding windows as a sort of improvement to the above method. I had a recursive example in mind but was having issues reducing the tree size.
string s = "rymis";
ArrayList<string> al = new ArrayList<string>();
for(int i = 1; i < s.length() + 1; i ++)
{
for(int k = 0; k < s.length(); k++)
{
int a = k;//left bound window 1
int b = k + i;//right bound window 1
int c = s.length() - 1 - k - i;//left bound window 2
int d = s.length() - 1 - k;//right bound window 2
al.add(s.substring(a,b));//add window 1
if(a < c)al.add(s.substring(c,d));//add window 2
}
}
There was an issue mentioned with using arraylist affecting performance so this next one will be with more basic structures.
string s = "rymis";
StringBuilder sb = new StringBuilder();
for(int i = 1; i < s.length() + 1; i ++)
{
for(int k = 0; k < s.length(); k++)
{
int a = k;//left bound window 1
int b = k + i;//right bound window 1
int c = s.length() - 1 - k - i;//left bound window 2
int d = s.length() - 1 - k;//right bound window 2
if(i > 1 && k > 0)sb.append(",");
sb.append(s.substring(a,b));//add window 1
if(a < c){
sb.append(",");
sb.append(s.substring(c,d));//add window 2
}
}
}
string s = sb.toString();
String[] sArray = s.split("\\,");
I am not sure about the exact algorithm but you may look into Ropes:
http://en.wikipedia.org/wiki/Rope_(computer_science)
In summary, ropes are better suited when the data is large and frequently modified.
I believe Rope outperforms String for your problem.