Why my code for prefixAgain is not working? - java

Given a string, consider the prefix string made of the first N chars of the string. Does that prefix string appear somewhere else in the string? Assume that the string is not empty and that N is in the range 1..str.length().
public boolean prefixAgain(String str, int n) {
String res = "";
String res1 = "";
String s = str.substring(0,n);
for ( int i = 0 ; i < n ; i++ ) {
res += str.charAt(i) ;
if (s.equalsIgnoreCase(res)); {
return true;
} else {
return false;
}
}
}

There are many problems with your solution:
Why do you need to loop only till n in the prefixAgain method? You probably need to go till str.length()
Your res variable will again be a prefix of the string and will be of no use.
Why are you having ; after the if?
Using += on Strings in a loop can be very expensive. You should always consider using StringBuilder and it's append method.
The following method does what you want:
public boolean prefixAgain(String str, int n) {
if (str.length() == 1) return false;
String s = str.substring(0, n);
return str.substring(1).contains(s);
}
The main idea is to just search the required prefix in the substring starting from 2nd character (the character at index 1).
Keep it simple. :)

Related

How to use recursion to create a searies of substrings in java

So, the task is to create a string that makes a progression throughout the letters of a string, returning a substring progressively longer.
For example if the input is Book, the answer would be: BBoBooBook . For the input Soup the method would return SSoSouSoup. I want to write it recursively. In my current method I receive no error but at the same time no anwer from the compiler.
public static String stringProgression(String str) {
int index = 1;
String result = "";
if (str.length() == 0) {
return "" ;
} else while (index <= str.length()); {
result = result + stringExplosion(str.substring(0, index));
index++;
}
return result;
}
In your code, you are using two different method names, stringProgression and stringExplosion.
Further, you have a while loop with a semicolon, while (index <= str.length()); which forms an empty loop. Since index doesn’t change in this empty loop, it will be an infinite loop when the condition is fulfilled.
Generally, a while loop contradicts the intent to have a recursive solution.
To find a recursive solution to a problem, you have to find the self-similarity in it. I.e. when you look at the intended result for Book, BBoBooBook, you can recognize that the beginning, BBoBoo is the right result for the string Boo, and BBo is the right result for Bo. So, the original string has to be appended to the result of a recursive evaluation of the substring:
public static String stringProgression(String str) {
if(str.isEmpty()) {
return str;
}
return stringProgression(str.substring(0, str.length() - 1)) + str;
}
An alternative, shorter syntax for the same is:
public static String stringProgression(String str) {
return str.isEmpty()? str: stringProgression(str.substring(0, str.length() - 1)) + str;
}
Check this one:
private static String doStringProgression(String str, String res, int length) {
if(length > str.length()) {
return res;
}
return doStringProgression(str, res + str.substring(0, length), length + 1);
}
And you can call the method with input like in the following example:
public static String stringProgression(String str) {
return doStringProgression(str, "", 1);
}

Substring alternative

So I'm creating a program that will output the first character of a string and then the first character of another string. Then the second character of the first string and the second character of the second string, and so on.
I created what is below, I was just wondering if there is an alternative to this using a loop or something rather than substring
public class Whatever
{
public static void main(String[] args)
{
System.out.println (interleave ("abcdefg", "1234"));
}
public static String interleave(String you, String me)
{
if (you.length() == 0) return me;
else if (me.length() == 0) return you;
return you.substring(0,1) + interleave(me, you.substring(1));
}
}
OUTPUT: a1b2c3d4efg
Well, if you really don't want to use substrings, you can use String's toCharArray() method, then you can use a StringBuilder to append the chars. With this you can loop through each of the array's indices.
Doing so, this would be the outcome:
public static String interleave(String you, String me) {
char[] a = you.toCharArray();
char[] b = me.toCharArray();
StringBuilder out = new StringBuilder();
int maxLength = Math.max(a.length, b.length);
for( int i = 0; i < maxLength; i++ ) {
if( i < a.length ) out.append(a[i]);
if( i < b.length ) out.append(b[i]);
}
return out.toString();
}
Your code is efficient enough as it is, though. This can be an alternative, if you really want to avoid substrings.
This is a loop implementation (not handling null value, just to show the logic):
public static String interleave(String you, String me) {
StringBuilder result = new StringBuilder();
for (int i = 0 ; i < Math.max(you.length(), me.length()) ; i++) {
if (i < you.length()) {
result.append(you.charAt(i)); }
if (i < me.length()) {
result.append(me.charAt(i));
}
}
return result.toString();
}
The solution I am proposing is based on the expected output - In your particular case consider using split method of String since you are interleaving by on character.
So do something like this,
String[] xs = "abcdefg".split("");
String[] ys = "1234".split("");
Now loop over the larger array and ensure interleave ensuring that you perform length checks on the smaller one before accessing.
To implement this as a loop you would have to maintain the position in and keep adding until one finishes then tack the rest on. Any larger sized strings should use a StringBuilder. Something like this (untested):
int i = 0;
String result = "";
while(i <= you.length() && i <= me.length())
{
result += you.charAt(i) + me.charAt(i);
i++;
}
if(i == you.length())
result += me.substring(i);
else
result += you.substring(i);
Improved (in some sense) #BenjaminBoutier answer.
StringBuilder is the most efficient way to concatenate Strings.
public static String interleave(String you, String me) {
StringBuilder result = new StringBuilder();
int min = Math.min(you.length(), me.length());
String longest = you.length() > me.length() ? you : me;
int i = 0;
while (i < min) { // mix characters
result.append(you.charAt(i));
result.append(me.charAt(i));
i++;
}
while (i < longest.length()) { // add the leading characters of longest
result.append(longest.charAt(i));
i++;
}
return result.toString();
}

The fastest method of determining if a string is a palindrome

I need an algorithm that verify with the fastest possible execution time, if a string is a palindrome ( the string can be a proposition with uppercase or lowercase letter, spaces etc.). All of this in Java. I got a sample :
bool isPalindrome(string s) {
int n = s.length();
s = s.toLowerCase();
for (int i = 0; i < (n / 2) + 1; ++i) {
if (s.charAt(i) != s.charAt(n - i - 1)) {
return false;
}
}
return true;
}
I transformed the string in lowercase letter using .toLowerCase() function, but I don't know how much it affects the execution time .
And as well I don't know how to solve the problem with punctuation and spaces between words in a effective way.
I think you can just check for string reverse, not?
StringBuilder sb = new StringBuilder(str);
return str.equals(sb.reverse().toString());
Or, for versions earlier than JDK 1.5:
StringBuffer sb = new StringBuffer(str);
return str.equals(sb.reverse().toString());
This avoids any copying. The functions isBlank and toLowerCase are rather unspecified in your question, so define them the way you want. Just an example:
boolean isBlank(char c) {
return c == ' ' || c == ',';
}
char toLowerCase(char c) {
return Character.toLowerCase(c);
}
Don't worry about the costs of method calls, that's what the JVM excels at.
for (int i = 0, j = s.length() - 1; i < j; ++i, --j) {
while (isBlank(s.charAt(i))) {
i++;
if (i >= j) return true;
}
while (isBlank(s.charAt(j))) {
j--;
if (i >= j) return true;
}
if (toLowerCase(s.charAt(i)) != toLowerCase(s.charAt(j))) return false;
}
return true;
Try to benchmark this... I'm hoping mu solution could be the fastest, but without measuring you never know.
Your solution seems just fine when it comes to effectiveness.
As for your second problem, you can just remove all spaces and dots etc before you start testing:
String stripped = s.toLowerCase().replaceAll("[\\s.,]", "");
int n = stripped.length();
for (int i = 0; i < (n / 2) + 1; ++i) {
if (stripped.charAt(i) != stripped.charAt(n - i - 1)) {
...
Effective is not the same of efficient.
Your answer is effective as long you consider spaces, special characters and so on. Even accents could be problematic.
About efficiency, toLowerCase is O(n) and any regexp parsing will be O(n) also. If you are concerning about that, convert and compare char by char should be the best option.
Here is my try:
public static boolean isPalindrome(String s)
{
int index1 = 0;
int index2 = s.length() -1;
while (index1 < index2)
{
if(s.charAt(index1) != s.charAt(index2))
{
return false;
}
index1 ++;
index2 --;
}
return true;
}
Here's some insight to my way of detecting a palindrome using Java. Feel free to ask question :) Hope I could help in some way....
import java.util.Scanner;
public class Palindrome {
public static void main(String[]args){
if(isReverse()){System.out.println("This is a palindrome.");}
else{System.out.print("This is not a palindrome");}
}
public static boolean isReverse(){
Scanner keyboard = new Scanner(System.in);
System.out.print("Please type something: ");
String line = ((keyboard.nextLine()).toLowerCase()).replaceAll("\\W","");
return (line.equals(new StringBuffer(line).reverse().toString()));
}
}
In normal cases :
StringBuilder sb = new StringBuilder(myString);
String newString=sb.reverse().toString();
return myString.equalsIgnoreCase(newString);
In case of case sensitive use :
StringBuilder sb = new StringBuilder(myString);
String newString=sb.reverse().toString();
return myString.equals(newString);

trouble with CharAt

I am suppose to make a simple program that would take a users input, and put spaces between each single letter. So for example, user enters mall, and it returns M A L L(on same line).
I am trying to make a loop with a if statement in it.But I think I would need CharAt for it, so if the string is greater value then 1, I would declare a variable to everysingle character in the string(that the userinput). Then I would say put spaces between each letter. I am in AP computer science A, and we are practicing loops.Everything underthis, is what I have done so far. And the directions are in the comment above code.And im useing eclipse,java.
/**
* Splits the string str into individual characters: Small becomes S m a l l
*/
public static String split(String str) {
for (int i = 0; str.length() > i; i++) {
if (str.length() > 0) {
char space = str.charAt();
}
}
return str;
}
My solution uses concat to build the str2, and trim to remove last white space.
public static String split(String str) {
String str2 = "";
for(int i=0; i<str.length(); i++) {
str2 = str2.concat(str.charAt(i)+" ");
}
return str2.trim();
}
You don't modify method parameters, you make copies of them.
You don't null-check/empty-check inside the loop, you do it first thing in the method.
The standard in a for loop is i < size, not size > i... meh
/**
* Splits the string str into individual characters: Small becomes S m a l l
*/
public static String split(final String str)
{
String result = "";
// If parameter is null or empty, return an empty string
if (str == null || str.isEmpty())
return result;
// Go through the parameter's characters, and modify the result
for (int i = 0; i < str.length(); i++)
{
// The new result will be the previous result,
// plus the current character at position i,
// plus a white space.
result = result + str.charAt(i) + " ";
}
return result;
}
4. Go pro, use StringBuilder for the result, and static final constants for empty string and space character.
Peace!
Ask yourself a question, where is s coming from?
char space = s.charAt(); ??? s ???
A second question, character at?
public static String split(String str){
for(int i = 0; i < str.length(); i++) {
if (str.length() > 0) {
char space = str.charAt(i)
}
}
return str;
}
#Babanfaraj, this a answer from a newbie like you!!
The code is very easy. The corrected program is-
class fopl
{
public static void main(String str)
{
int n=str.length();
for (int i = 0;i<n; i++)
{
if (n>=0)
{
String space = str.charAt(i)+" ";
System.out.print(space);
}
}
}
}
Happy to help you!

Periodic Strings

I am trying to solve this String manipulation problem, where I need to find the smallest period of a given string.
A string is said to have period k if it can be formed by concatenating one or more repetitions of another string of length k.
For example, the string "abcabcabcabc" has period 3, since it is formed by 4 repetitions of the string "abc". It also has periods 6 (two repetitions of "abcabc") and 12 (one repetition of "abcabcabcabc"). Here's my code :
public static int getPeriod(String str){
int len=str.length();
boolean flag=false;
int i;
for (i=0;i<len;i++){
String s=str.substring(0,i);
String tmp=str;
while(tmp.length()>0){
if(tmp.startsWith(s)){
tmp=tmp.substring(0,i);
flag=true;
}
else {
flag=false;
continue;
}
}
if (flag==true)
break;
}
return i;
}
I am forming a string s by looping through the original string, one character at a time. After, that I am checking if the original string can be completely exhausted by concatenating the string s any number of times, or not.
ERROR:
The method always returns 0.
Why is that so ?
EDIT : My algorithm
Lets consider the input string HoHoHo
First step: s=H
tmp= HoHoHo
tmp= oHoHo (after substringing tmp)
'o' isn't the same as s, so we increase i
Second step:s=Ho
tmp= HoHoHo
tmp= HoHo (after substringing tmp)
tmp= Ho (after substringing tmp)
tmp= "" (after substringing tmp)
Return the value of i, that is 2.
The code inside the while loop isn't correct, it's called during the first invocation of the for loop with i=0 and hence the first assignment to the tmp variable sets it to the empty string, the loop exits and you get 0. The flag assignments and the continue in the else are not correct too.
Try this:
public static int getPeriod(String str) {
int len = str.length();
int i;
for (i = 1; i <= len/2; i++) {
String period = str.substring(0, i);
String tmp = str;
boolean flag = true;
while (flag && tmp.length() > 0) {
if (tmp.startsWith(period)) {
tmp = tmp.substring(i);
} else {
flag = false;
}
}
if (flag == true) {
return i;
}
}
return 0;
}
Notice that the for loop starts from 1 and goes to len/2 because you don't want to check for the zero length period and there can't be periods longer than n/2.
In the first loop iteration, i == 0, so s is "" (empty string), and tmp is also "" after the first iteration over while loop, so tmp also becomes "" and exits all the loops.
Starting with i = 0 will always return true because substring(0,0) will return the "" string and tmp.startsWith("") is always true.
First you should start i from 1, also you should replace continue with break, because continue will continue your while loop but what you want to do is continue the for loop and not the while loop
Here is a version of your code working:
public static int getPeriod(String str){
int len=str.length();
boolean flag=false;
int i;
for (i=1;i<len;i++){
String s=str.substring(0,i);
String tmp=str;
while(tmp.length()>0){
if(tmp.startsWith(s)){
tmp=tmp.substring(i);
flag=true;
}
else {
flag=false;
break;
// Replaced continue with break to exit the while loop and pass
// to the next value in the for loop
}
}
if (flag==true)
break;
}
return i;
}
I know this is an old question. The problem can be solved in linear time using Knuth's Prefix Function.
public static int prefixFunction(final String needle)
{
//This code does not include input validation. Validate the input and return appropriate error message
int[] pf = new int[needle.length()];
for (int i = 1; i < needle.length(); i++)
{
int j = pf[i - 1];
while (j > 0 && needle.charAt(i) != needle.charAt(j)) j--;
if (needle.charAt(i) == needle.charAt(j)) ++j;
pf[i] = j;
}
int n = needle.length(), maxValue = pf[n - 1];
if(maxValue == 0 || n%(n-maxValue) != 0) return -1; //Not periodic
return needle.length() - maxValue;
}

Categories

Resources