Unsure about the time complexity of this code [duplicate] - java

This question already has answers here:
How can I find the time complexity of an algorithm?
(10 answers)
Closed 5 years ago.
I recently solved a problem presented on https://www.geeksforgeeks.org/find-given-string-can-represented-substring-iterating-substring-n-times/
The problem is determining if a particular string can be represented from a substring by iterating the substring n times.
For example the string "abcabcabc" can be represented by iterating the substring "abc" 3.
I came up with this Java solution
public static boolean canForm (String str) {
if(str.isEmpty()||str.length()==1) return true;
int end;
if (str.length()%2==0) {
end = str.length()/2;
} else {
end = (str.length()-1)/2;
}
for (int i=1; i<=end; i++) {
String s = str.substring(0,i);
String compare = "";
while (compare.length()<str.length()) {
compare += s;
}
if (compare.equals(str)) return true;
}
return false;
}
One condition of the problem is for the solution to be O(n). I concluded it was O(n) but I am unsure if my solution really is O(n) or it is in fact O(n^2) and why.

Your program runs in O(n^2), where n is propotional to the length of the string. Your code has a while loops that iterates n times in a for loop that iterates n times.
Hence the order of the program is O(n*n)=O(n^2).

Related

Java write recursive function that accept int : k and print to screen k of "*" [duplicate]

This question already has answers here:
How Do I Print the values in a recursive Program in Java?
(5 answers)
Closed 2 years ago.
java write recursive function that accept int : k and print to screen k of "*"
Attempt:
public static String numStarec(int k) {
String ans = "";
if (k == 0) {
ans += "*";
return ans;
}
return numStarec(k-1);
}
this code not work and print for me only "*" ones I know the problem
I tried to fix that but , unfortunately without successes
Example :
k = 3
console : ***
You can append an asterisk after each recursive call, with the base case returning an empty string when k is 0.
public static String numStarec(int k) {
if(k == 0) return "";
return numStarec(k-1) + "*";
}
Demo
Before writing the solution to the problem, I think it would be valuable for you to understand the definition of recursion and what is it that you want to happen. First things first, "recursion is a method of solving a problem where the solution depends on solutions to smaller instances of the same problem" (Source).
If the previous definition still confuses you a bit then lets take a look at the solution to your problem:
public static String numStarec(int k) {
if (k == 0) {
return "";
}
return numStarec(k-1) + "*";
}
As the definition says, "method of solving a problem..." (In this specific case the problem you have is that you want to print the character * an amount K of times on screen) "...where the solution depends on solutions to smaller instances of the same problem" (Where these smaller instances of the same problem consist on finding out how many characters '*' are left to be printed, which is what the value of K is for)
What is happening when you provide the function numStarec with a certain number K is that it will take K and check whether it is 0 or not. If K == 0 evaluates to true then the return statement will be "" but while K != 0 evaluates to true, what will happen is that the function will return the character "*" and keep on invoking itself with the value of K-1 and once again return accordingly.
Hope it helps you understand a little bit about recursion.

Dynamic Programming approach - Interleaving Parentheses

Below is my code for the problem described on https://community.topcoder.com/stat?c=problem_statement&pm=14635. It keeps track of possible interleaves (as described in the problem description given) through a static variable countPossible.
public class InterleavingParentheses{
public static int countPossible = 0;
public static Set<String> dpyes = new HashSet<>(); //used for dp
public static Set<String> dpno = new HashSet<>(); //used for dp
public static void numInterleaves(char[] s1, char[] s2, int size1, int size2){
char[] result = new char[size1+size2];
numInterleavesHelper(result,s1,s2,size1,size2,0,0,0);
}
public static void numInterleavesHelper(char[] res, char[] s1, char[] s2, int size1, int size2, int pos, int start1, int start2){
if (pos == size1+size2){
if (dpyes.contains(new String(res))){
countPossible+=1;
}
else{
if(dpno.contains(new String(res))){
countPossible+=0;
}
else if (isValid(res)){
dpyes.add(new String(res));
countPossible+=1;
}
else{
dpno.add(new String(res));
}
}
}
if (start1 < size1){
res[pos] = s1[start1];
numInterleavesHelper(res,s1,s2,size1,size2,pos+1,start1+1,start2);
}
if (start2 < size2){
res[pos] = s2[start2];
numInterleavesHelper(res,s1,s2,size1,size2,pos+1,start1,start2+1);
}
}
private static boolean isValid(char[] string){
//basically checking to see if parens are balanced
LinkedList<Character> myStack = new LinkedList<>();
for (int i=0; i<string.length; i++){
if (string[i] == "(".charAt(0)){
myStack.push(string[i]);
}
else{
if (myStack.isEmpty()){
return false;
}
if (string[i] == ")".charAt(0)){
myStack.pop();
}
}
}
return myStack.isEmpty();
}
}
I use the scanner class to put in the input strings s1 = "()()()()()()()()()()()()()()()()()()()()" and s2 = "()()()()()()()()()()()()()()()()()" into this function and while the use of the HashSet greatly lowers the time because duplicate interleaves are accounted for, large input strings still take up a lot of time. The sizes of the input strings are supposed to be at most 2500 characters and my code is not working for strings that long. How can i modify this to make it better?
Your dp set is only used at the end, so at best you can save an O(n), but you've already done many O(n) operations to reach that point so the algorithm completexity is about the same. For dp to be effective, you need to be reducing O(2^n) operations to, say O(n^2).
As one of the testcases has an answer of 487,340,184, then for your program to produce this answer, it would need that number of calls to numInterleavesHelper because each call can only increment countPossible by 1. The question asking for the answer "modulo 10^9 + 7" as well indicates that there is a large number expected as an answer.
This rules out things like creating every possible resulting string, most string manipulation, and counting 1 string at a time. Even if you optimized it, then the number of iterations alone makes it unfeasible.
Instead, think of algorithms that have about 10,000,000 iterations. Each string has a length of 2500. These constraints were chosen on purpose so that 2500 * 2500 fits within this number of iterations, suggesting a 2D dp solution.
If you create an array:
int ways[2501][2501] = new int[2501][2501];
then you want the answer to be:
ways[2500][2500]
Here ways[x][y] is the number of ways of creating valid strings where x characters have been taken from the first string, and y characters have been taken from the second string. Each time you add a character, you have 2 choices, taking from the first string or taking from the second. The new number of ways is the sum of the previous ones, so:
ways[x][y] = ways[x-1][y] + ways[x][y-1]
You also need to check that each string is valid. They're valid if each time you add a character, the number of opening parens minus the number of closing parens is 0 or greater, and this number is 0 at the end. The number of parens of each type in every prefix of s1 and s2 can be precalculated to make this a constant-time check.

Java: Unknown number of 'for' loops [duplicate]

This question already has answers here:
Generating all permutations of a given string
(57 answers)
Closed 7 years ago.
I want to make a program that would un-jumble some words.
I need to try all possible combinations of the words that can be formed, and then check if it is contained in a String variable, named dict.
My code is:
public class UnJumble
{
public static void main(String args[])
{
String dict = "cat, rat, mat dog, let, den, pen, tag, art,";
String t = "tra";
int l = t.length();
for(int i=0; i<l; i++)
{
char a=t.charAt(i);
t = t.replaceFirst(a+"","");
l--;
for(int j=0; j<l; j++)
{
char b = t.charAt(j);
t = t.replaceFirst(b+"","");
l--;
for(int k=0; k<l; k++)
{
char c = t.charAt(k);
if(dict.contains(""+a+b+c+","))
{
System.out.println("\'"+a+b+c+"\' found.");
break;
}
}
l++;
t = new StringBuilder(t).insert(j,b+"").toString();
}
t = new StringBuilder(t).insert(i,a+"").toString();
l++;
}
}
}
The variable t contains the word to be un-jumbled.
With this code, the output is:
'rat' found.
'art' found.
I think that I would need as many for loops as there as characters in the String t.
But I want to make it able to un-jumble words of an unknown length. So how can I achieve this?
I have tried searching on the Internet, and on SO. I found some answers on SO that are written in other programming languages which I don't understand.
You should look for recursive methods.
For example, given a string str of n characters, you can write a function that basicaly do this :
List<String> compute(String str)
// TODO : Handle case where str has only 1 character
List<String> list = compute(str.substring(0,n-2))
// TODO : Compute all combinations of str[n-1] with list
return list;
I guess this can be improved a lot in some cases.
There is a tricky way to do this without a for loop for each letter in your variable t, but it's code-intensive.
You can set up a loop that counts in base n, where n is the length of t. Assume i is your counter: Each pass through that loop you use the individual digits in i as indices into t, then build a ' word' and test that word against your dictionary. You are using i two different ways: as a counter and as a set of digits that represent indices into your t.
For example, if your t has three letters then you want to count in base 3 like this: 012, 020, 021, 022, 100, 101, 110,111, and so forth. Now the logic needs to verify that your combination of digits is unique so you don't use a letter twice when you build a word.
It's a lot of work but the algorithm is correct. The benefit is that it works for strings of any length.
I know I will be voted down, but oh well.

Why are the quotes necessary in this code? [duplicate]

This question already has answers here:
this method must return a result of type boolean, java
(5 answers)
Closed 7 years ago.
Hi sorry if this is a dumb question, probably is... this is from codingbat (exercise: everNth)
why is it that this works?
public String everyNth(String str, int n) {
String characters = "";
for (int i = 0; i < str.length(); i = i + n) {
characters = characters + Character.toString(str.charAt(i));
}
return characters;
}
but this one doesn't?
public String everyNth(String str, int n) {
for (int i = 0; i < str.length(); i = i + n) {
return Character.toString(str.charAt(i));
}
}
^^ gives me the error: "This method must return a result of type String"
However, doesn't the Character.string() method already create a string?
Why do I have to add in additional quotation marks? Thanks guys!!~~ peace and love
It has nothing to do with the quotation marks. The problem is that you don't have a return statement after the for loop.
The compiler is warning you that if the for loop is never entered, then you will never return anything. You need to make sure your method returns a string value under all circumstances, not just when the loop is entered.
To better understand, walk through your method, and consider what would happen if str has a length of zero. What would your method return then?
EDIT
However, as pointed out by WalterM, keep in mind that, even if you fix the compiler error, your 2nd method's logic is different from your first one. The 2nd method only ever returns the 1st character of the string.

Wrong output from a while loop using indexOf [duplicate]

This question already has answers here:
While loop doesn't run a indexOf search
(4 answers)
Closed 8 years ago.
I'm trying to find out how many times one string appears in another. For my testing, I'm using "ea" for wordOne and "Ilikedthebestontheeastbeachleast" for wordTwo. My output is returning 2 for my "appearance" variable, which should store how many times "ea" appears in wordTwo. It should return 3.
I've tried messing with variable initializations, and trying to think of the math differently, but I'm pretty much out of ideas.
Here's the relevant code section:
int wordTwoLength = wordTwo.length();
System.out.println(wordTwoLength);
while (wordTwoLength > 0)
{
positionCount = wordTwo.indexOf(wordOne, positionCount);
appearances++;
wordTwoLength = (wordTwoLength - positionCount);
}
System.out.println(appearances);
Thanks!
Edit: I forgot to add that I tried other test inputs and got crazy outputs. It would return numbers way higher than expected for some, and lower for others.
So now the problem is that .indexOf still returns the true index of "ea" in wordTwo - it doesn't take into account where you start from. Also, setting positionCount equal to where you find the word and then searching from that position again is just going to make you immediately find the same instance of that word, not the next one.
The index of the first instance of "ea" in wordTwo is 18, so wordTwoLength will be set to 32-18, or 14. Then you'll find the same instance of ea in wordTwo, and wordTwoLength will be set to 14-18, or -4. Then you'll exit the while loop, with appearances being 2.
for (int index = 0; (index = wordTwo.indexOf(wordOne, index)) > -1; index ++)
appearances ++;
Try this simpler code:
class Demo{
public static void main(String[] args){
String wordOne = "ea";
String wordTwo = "Ilikedthebestontheeastbeachleast";
String[] arr = wordTwo.split(wordOne);
int cnt = arr.length - 1;
System.out.printf("[%s] has occured for %s time(s) in [%s]", wordOne, cnt, wordTwo);
}
}
You can simplify your above work by "Converting String to Character array".Because it will be more Efficient(I think).I have provided a sample code here,
String wordOne="Ilikedthebestontheeastbeachleast";
String wordTwo="ea";
int count=0;
char[] arrayOne=wordOne.toCharArray();
char [] arrayTwo=wordTwo.toCharArray();
for(int i=0;i<=((arrayOne.length)-1);i++)
{
if(arrayTwo[0]==arrayOne[i]&&arrayTwo[1]==arrayOne[i+1])
count+=1;
}
System.out.println("Pattern found "+count+" times.");
This will suits your need but using For loop.

Categories