Problem in my solution "Repeated string match" - java

I have to tell the minimum number of times string A needs to be repeated so that string B becomes a substring of A.
My answer is wrong for some test cases like
A = "abc"
B = "cabcabca"
My output is coming 3..it should be 4.
My code is-
class Solution {
public int repeatedStringMatch(String A, String B) {
int count = 0;
while (A.length() <= 1000) {
if (A.indexOf(B) != -1)
return (count + 1);
else
A = A + A;
count++;
}
return -1;
}
}

The problem is because of A=A+A; as it makes A as abcabc after the first iteration, abcabcabcabc after the second iteration, abcabcabcabcabcabcabcabc after the third iteration and so on i.e. instead of getting appended, the string is getting doubled in each iteration.
It is like you have been given a task to add 2 to itself in each iteration i.e. after the first iteration, it should become 2 + 2 = 4, after the second iteration, it should become 4 + 2 = 6, after the third iteration it should become 6 + 2 = 8 and so on.
Whereas the way you have done, it will become 2 + 2 = 4 after the first iteration, 4 + 4 = 8 after the second iteration, 8 + 8 = 16 after the third iteration and so on.
As a side note, you should avoid using string concatenation in a loop. You should also follow Java naming convention e.g. the variable name A should be a.
Do it as follows:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(repeatedStringMatch("abc", "cabcabca"));
}
static int repeatedStringMatch(String a, String b) {
int count = 1;
StringBuilder sb = new StringBuilder(a);
while (sb.length() <= 1000) {
if (sb.indexOf(b) != -1) {
return count;
} else {
sb.append(a);
count++;
}
}
return -1;
}
}
Output:
4

Related

Find the smallest binary number without continous 1

So here is the thing.
I have to write code to show a binary number X's next smallest "code-X number" which is bigger than binary number X.
code-X number is a binary number which have no continuously 1. For example: 1100 is not a code X number because it has 11, and 1001001001 is a code-X number
Here is my code
String a = "11001110101010";
String b = "";
int d = 0;
for(int i = a.length()-1; i>0;i--){
if(a.charAt(i) == '1' && a.charAt(i-1)=='1'){
while(a.charAt(i)=='1'){
b = b + '0';
if(i!=0){i--;}
d++;
}
}
b = b + a.charAt(i);
}
StringBuffer c = new StringBuffer(b);
System.out.println(c.reverse());
I plan on copy the binary string to string b, replace every '1' which next i is '1' into '0' and insert an '1'
like:
1100 ---> 10000
but i have no idea how to do it :)
May you help me some how? Thanks
Try this. This handles arbitrary length bit strings. The algorithm is as follows.
Needed to conditionally modify last two bits to force a change if the number is not a codeEx number. This ensures it will be higher. Thanks to John Mitchell for this observation.
Starting from the left, find the first group of 1's. e.g 0110
If not at the beginning replace it with 100 to get 1000
Otherwise, insert 1 at the beginning.
In all cases, replace everything to the right of the grouping with 0's.
String x = "10000101000000000001000001000000001111000000000000110000000000011011";
System.out.println(x.length());
String result = codeX(x);
System.out.println(x);
System.out.println(result);
public static String codeX(String bitStr) {
StringBuilder sb = new StringBuilder(bitStr);
int i = 0;
int len = sb.length();
// Make adjust to ensure new number is larger than
// original. If the word ends in 00 or 10, then adding one will
// increase the value in all cases. If it ends in 01
// then replacing with 10 will do the same. Once done
// the algorithm takes over to find the next CodeX number.
if (s.equals("01")) {
sb.replace(len - 2, len, "10");
} else {
sb.replace(len- 1, len, "1");
}
while ((i = sb.indexOf("11")) >= 0) {
sb.replace(i, len, "0".repeat(len - i));
if (i != 0) {
sb.replace(i - 1, i + 2, "100");
} else {
sb.insert(i, "1");
}
}
String str = sb.toString();
i = str.indexOf("1");
return i >= 0 ? str.substring(i) : str;
}
Prints
10000101000000000001000001000000001111000000000000110000000000011011
10000101000000000001000001000000010000000000000000000000000000000000
Using raw binary you can use the following.
public static void main(String[] args) {
long l = 0b1000010100000000010000010000000011110000000000110000000000011011L;
System.out.println(
Long.toBinaryString(nextX(l)));
}
public static long nextX(long l) {
long l2 = l >>> 1;
long next = Long.highestOneBit(l & l2);
long cutoff = next << 1;
long mask = ~(cutoff - 1);
return (l & mask) | cutoff;
}
prints
1000010100000000010000010000000010000000000000000000000000000000
EDIT: Based on #WJS correct way to find the smallest value just larger.
This is a slight expansion WJS' 99% correct answer.
There is just one thing missing, the number is not incremented if there are no consecutive 1's in the original X string.
This modification to the main method handles that.
Edit; Added an else {}. Starting from the end of the string, all digits should be inverted until a 0 is found. Then we change it to a 1 and break before passing the resulting string to WJS' codeX function.
(codeX version does not include sb.replace(len-2,len,"11");)
public static void main(String[] args) {
String x = "10100";
StringBuilder sb = new StringBuilder(x);
if (!x.contains("11")) {
for (int i = sb.length()-1; i >= 0; i--) {
if (sb.charAt(i) == '0') {
sb.setCharAt(i, '1');
break;
} else {
sb.setCharAt(i, '0');
}
}
}
String result = codeX(sb.toString());
System.out.println(x);
System.out.println(result);
}

Find max rating(number) in an array where we cannot skip over 1 or more consecutive number in array

we have an array of ratings, we have to find the max rating in such a away that we cannot skip 1 or more consecutive rating in an arrray
Example-1: {9,-1,-3,-4,-5} output = 9 + -1 + -4 = 4
Explanation: I took 9 the we have to took -1 or -3 we cannot jump to -4 directly as we cannot skip 1 or more consecutive number.
Example-2: {-1,-2,-3,-4,-5} output = -2 + -4 = -6
Example-3: {-3,2,-4,-1,-2,5} output = 2 + -1 + 5 = 6
Example-4: {9,-1,-3,4,5} output = 9 + -1 + 4 + 5 = 17
I tried below code but it is working in case of example: 2,3,4 but not for example 1 similarly failing for other scenario.
static int maximizeRatings(int[] ratings) {
int current = 0;
boolean result = false;
for(int j=0; j<ratings.length;j++){
if(ratings[j]<0){
result = true;
}else{
result = false;
}
}
if(result){
return allnegatine(ratings);
}
for(int i=0; i<ratings.length;i++){
if(i == ratings.length-1){
if(ratings[i] > 0)
current += ratings[i];
}else{
if(ratings[i] >0 && ratings[i+1]>0){
current = ratings[i]+ratings[i+1];
i++;
}
if(ratings[i] > ratings[i+1]){
current += ratings[i];
}else{
current += ratings[i+1];
i++;
}
}
}
return current;
}
private static int allnegatine(int[] ratings) {
int current =0;
for(int i=0; i<ratings.length;i++){
if(ratings.length%2==0){
if(i%2 == 0)
current += ratings[i];
}else{
if(i%2!=0)
current += ratings[i];
}
}
return current;
}
not getting excepted out for some scenarios like example 1 I am getting -6 instead of 4, I am trying to get proper code which will pass all scenarios. Thank you
This is a dynamic programming problem.
Let dp[i] be the max ratings which can be achieved considering only the part of the array that starts at zero, ends at i, and includes ratings[i].
dp[0]=ratings[0]
dp[1]=max(ratings[1],ratings[0]+ratings[1])
dp[i]=max(dp[i-1],dp[i-2])+ratings[i]
Answer: max(dp[n-1],dp[n-2]) where n is the size of the ratings array.
Also you can chose to do away with dp array and maintain 2 variables for dp[i-1] and dp[i-2].
this is typical recursion problem (as long as the input array is reasonably long). You should go thru items and try all possible combinations and then pick the best one.
Because it looks like typical school work I am not sure if I should paste my solution. You should figure it out yourself or at least understand what's going on to be able to implement it yourself next time.
public class RatingService {
public int calculate(List<Integer> input) {
return recursion(input, true, 0);
}
private int recursion(List<Integer> sublist, boolean canSkip, int sum) {
if (sublist.isEmpty()) {
return sum;
}
int skippedSum = Integer.MIN_VALUE;
int notSkippedSum;
Integer integer = sublist.get(0);
if (canSkip) {
skippedSum = recursion(sublist.subList(1, sublist.size()), false, sum);
}
notSkippedSum = recursion(sublist.subList(1, sublist.size()), true, integer + sum);
return skippedSum > notSkippedSum ? skippedSum : notSkippedSum;
}
}
I think you are doing the mistake while checking for all negative numbers in for loop. If the last element in the array is negative then the 'result' variable will be true means that all array is negative but actually its not.
You have to replace the for loop by :
for(int j=0;j<ratings.length;j++){
if(ratings[j]<0){
result=true;
}
else{
result = false;
break;
}
}
It will break the for loop at the index where it founds any positive number i-e: all elements of array are not negative.

bad result of my code

I seem to have a problem, where the output I expect is:
9000 + 200 + 50 + 6
But I get:
90000 + 2000 + 500 + 60
Here is my code:
class Kata
{
public static String expandedForm(int num) {
String s = String.valueOf(num);
StringBuilder result = new StringBuilder();
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == '0') continue;
result.append(s.charAt(i) + makesZero(s.length() - i));
if(i != s.length() - 1) result.append(" + ");
}
return result.toString();
}
public static String makesZero(int num) {
StringBuilder result = new StringBuilder();
for(int i = 0; i < num; i++)
result.append("0");
return result.toString();
}
}
public class Main {
public static void main(String args[]) {
System.out.println(Kata.expandedForm(9256));
}
}
At
result.append(s.charAt(i) + makesZero(s.length() - i));
line you are appending character at position i and length - i zeroes. Lets see what happens for s="9256".
If i=0
s.charAt(i)->s.charAt(0)->'9' (that looks OK)
makesZero(s.length() - i) -> makesZero(4 - 0)) -> makesZero(4) -> "0000".
So as you see you are adding one extra zero because you didn't take into account that while 9 represents thousands, but thousands despite having 4 digits should have 3 zeroes. So you need to reduce one zero with
makesZero(s.length() - i - 1).
BTW builder.append(foo + bar) (when + represents concatenation, not addition) should be written as builder.append(foo).append(bar). Otherwise you are ending with something like
builder.append(new StringBuilder().append(foo).append(bar).toString())
which means you still need to create separate builder for each +.
We are using StringBuilder#append precisely so we could avoid + and such unnecessary object creation.
You're dealing with a classic off-by-one error. This is easily solved, but the larger problem with your approach is that you are solving the problem in an unnatural way, which makes your code more difficult to understand and debug. Determining how many zeroes to add is fundamentally a math problem but you are treating it like a string problem, which reduces the expressiveness of your code.
Here is a suggested rewrite of your expandedForm method that approaches this problem in a different way.
public static String expandedForm(int num) {
if (num == 0)
return "0";
int zeroes = (int) Math.log10(num);
StringBuilder result = new StringBuilder();
while (zeroes >= 0) {
int multiple = (int) Math.pow(10, zeroes);
int digit = num / multiple;
result.append(String.valueOf(digit * multiple));
if (zeroes > 0)
result.append(" + ");
num = num % multiple;
--zeroes;
}
return new String(result);
}
Just start your loop with i = 1 and i <= s. length()

Print 2 closest, smaller Fibonacci numbers

I am having a hard time figuring out the solution to this problem. I need to write an iterative (can't use recursion) solution to a problem in which a user inputs a number via scanner (for example, 10) and it prints 2 "previous" Fib numbers.
For the input "10" example, it would be:
5
8
As they're the "biggest" two Fib numbers prior to 10.
If the input is 13, it would print:
8
13
As 13 is a Fib number itself, it prints only 1 number prior, and then itself.
Now I know how to iteratevely find the "n-th" Fib number but I can't get my mind around a solution to run til a given number (rather than the n-th Fib number) and somehow print only the last 2 before it (or, if the given number is a Fib number by itself, count that as one too).
Now I'm aware of the formula that uses the perfect square - but unfortunately, can't use that...
Edit as it made some people confused:
I do not ask for a code, nor do I want anyone to solve this for me. I just genuinely want to understand how to approach such questions.
Edit #2:
Here's a code I wrote:
int a = 0;
int b = 1;
while (a < num) {
int temp = a;
a = a + b;
b = temp;
}
System.out.println(b);
System.out.println(a);
The problem I'm having is that if the num input is indeed a Fib num - it will work as intended, otherwise, it prints 1 prior Fib num and the next one, so for input "10" it prints 8 and 13.
Explanation
You said that you already have a method that computes the n-th Fibonacci number iterative. Since Fibonacci numbers are usually defined based on the last two Fibonacci elements, you should also already have them at hand, see the definition from Wikipedia:
The only thing you need to do is to run your iterative method until you reach the input. And then output the current memorized values for F_(n - 1) and F_(n - 2) (or F_n if equal to input).
Example
Suppose you have a Fibonacci method like (which I grabbed from the first google result)
public static long fib(int n) {
if (n <= 2) {
return (n > 0) ? 1 : 0;
}
long fib1 = 0;
long fib2 = 1;
for (int i = 1; i < n; i++) {
final long newFib = fib1 + fib2;
fib1 = fib2;
fib2 = newFib;
}
return fib2;
}
You need to modify it to accept the input and return both last Fibonacci numbers fib1 and fib2. Replace the loop to n by an infinite loop from which you break once exceeding input:
public static long[] fib(long input) {
// Special cases
if (input == 1) {
return new long[] { 1l, 1l };
}
if (input == 0) {
return new long[] { 0l };
}
if (input < 0) {
return null;
}
// Seed values
long fib1 = 0;
long fib2 = 1;
// Repeat until return
while (true) {
long newFib = fib1 + fib2;
// Reached the end
if (newFib >= input) {
// Push 'newFib' to the results
if (newFib == input) {
fib1 = fib2;
fib2 = newFib;
}
return new long[] { fib1, fib2 };
}
// Prepare next round
fib1 = fib2;
fib2 = newFib;
}
}
The method now returns at [0] the second to nearest Fibonacci and at [1] the nearest Fibonacci number to input.
You can easily adjust your own method likewise using this example.
Usage:
public static void main(String[] args) {
long[] results = fib(20L);
// Prints "8, 13"
System.out.println(results[0] + ", " + results[1]);
results = fib(21L);
// Prints "13, 21"
System.out.println(results[0] + ", " + results[1]);
}
Another example
A different view to the same problem can be obtained by using some kind of nextFib method. Then you can repeatedly pick until exceeding input. Therefore, we build some class like
public class FibonacciCalculator {
private long fib1 = 0;
private long fib2 = 1;
private int n = 0;
public long nextFib() {
// Special cases
if (n <= 2) {
long result = (n > 0) ? 1 : 0;
// Increase the index
n++;
return result;
}
// Compute current and push
long newFib = fib1 + fib2;
fib1 = fib2;
fib2 = newFib;
return newFib;
}
}
And then we just call it until we exceed input, always memorizing the last two values:
public static long[] fib(long input) {
FibonacciCalculator calc = new FibonacciCalculator();
long lastFib = 0L;
long secondToLastFib = 0L;
while (true) {
long curFib = calc.nextFib();
if (curFib > input) {
return new long[] { secondToLastFib, lastFib };
} else if (curFib == input) {
return new long[] { lastFib, curFib };
}
secondToLastFib = lastFib;
lastFib = curFib;
}
}

Recursive and iteration fibonacci

I am trying to make it where it prints the recursive part of the code out the same as it prints out the iteration.
Fibonacci sequence in iteration
1
1
2
3
5
8
13
21
34
The ending of the fibonacci sequence at 9 is 34
Time : 1 . like so , but every time I try a loop to print I get some weird answers, Not really sure what to add to the method.
import java.util.Scanner;
public class fibonacciRecursive {
public static void main(String[] args) {
/*
* Dustin Willingham
* Class: CSCI 1302 Mon-Wed Cartersville
*Lets user enter the last number of a fibonacci sequence
*then it takes the number and runs the fibonacci sequence in recursive and iteration method
*It outputs the answer for both and the time
*/
Scanner in = new Scanner(System.in);
System.out.println("Enter the number you want the Fibonacci sequence to go to:");
int fibNumb = in.nextInt();
//Print and timing for the Fibonacci sequence with the Recursive method
System.out.println("Fibonacci sequence in recursion");
//start of the timer
long start = System.currentTimeMillis();
System.out.println("The ending of the fibonacci sequence at " + fibNumb + " is " + fibonacciRec(fibNumb));
System.out.print("Time : ");
//print out the timer
System.out.println(System.currentTimeMillis() - start);
//Print and timing for the Fibonacci sequence with the Iteration method
System.out.println("\n" + "Fibonacci sequence in iteration");
start = System.currentTimeMillis();
System.out.println("The ending of the fibonacci sequence at " + fibNumb + " is " + fiboacciIte(fibNumb));
System.out.print("Time : ");
System.out.print(System.currentTimeMillis() - start);
in.close();
}
// Recursive method for the Fibonacci sequence
public static int fibonacciRec(int fibNumb) {
if ((fibNumb == 1) || (fibNumb == 0)) {
return fibNumb;
}
int answer = fibonacciRec(fibNumb - 1) + fibonacciRec(fibNumb - 2);
return answer;
}
//Iteration method for the Fibonacci sequence
static int fiboacciIte(int fibNumb) {
int a = 0, b = 1, c = 1;
for (int d = 0; d < fibNumb; d++) {
a = b;
b = c;
System.out.println(a);
c = a + b;
}
return a;
}
}
You could add a separate argument to the recursive function, which gives the highest Fibonacci subscript (fibNumb) reached so far. If the current subscript is greater than this counter, update it and print the current Fibonacci number.
The counter must be passed by reference as the value will need to be updated before recursion unfolds. We can create a custom class for it:
private static class Counter
{
private int value;
public Counter() { value = 0; }
public int getValue() { return value; }
public void increment() { value++; }
}
Pass the same instance to each recursive call and increment along the way:
private static int fibonacciRec_internal(int fibNumb_cur, Counter fibNumb_max) {
int answer = (fibNumb_cur <= 1) ? fibNumb_cur :
fibonacciRec_internal(fibNumb_cur - 1, fibNumb_max) +
fibonacciRec_internal(fibNumb_cur - 2, fibNumb_max);
if (fibNumb_max.getValue() < fibNumb_cur) {
fibNumb_max.increment();
System.out.println(answer);
}
return answer;
}
And finally write a wrapper function to hide this counter class and its usage details:
public static int fibonacciRec(int fibNumb)
{
Counter max = new Counter();
return fibonacciRec_internal(fibNumb, max);
}
Results are as expected:
// fibonacciRec(10);
1
1
2
3
5
8
13
21
34
55
Even better, we could create a wrapper class for all of the above, and use the same object for every fibonacciRec call instead of creating a new one. It's a pretty trivial modification so I'll leave it to you to figure out the what and the how.

Categories