I have been going through some codingbat exercises and I came across this problem.
"Given a string, return the length of the largest "block" in the string. A block is a run of adjacent chars that are the same."
Required Output:
maxBlock("hoopla") → 2
maxBlock("abbCCCddBBBxx") → 3
maxBlock("") → 0
My code seems to pass all the test except for the last one "other test". Can someone please review my code and tell me where exactly I could have gone wrong.
Submitted Code:
public int maxBlock(String str) {
int charBlock = 0;
int holder = 1;
if(str.length() == 0){ //If string is empty return 0
charBlock = 0;
} else if(str.length() == 1){ //If string contains only a single char return 1
charBlock = 1;
} else {
for(int i=0; i < str.length()-1; i++){ //loop through each char value
if((str.length() == 2) && (str.charAt(i) != str.charAt(i+1))){
charBlock =1; //return 1 if the length of the string is 2 and non of the two chars match
}
else if((str.length() == 3) && (str.charAt(i) != str.charAt(i+1))){
charBlock = 1; //return 1 if the length of the string is 3 and non of the three chars match
}
else if (str.charAt(i) == str.charAt(i+1)){
holder = holder + 1;
if(holder > charBlock){
charBlock = holder; //update the value of charBlock if a holder is larger current value
}
} else holder = 1;
}
}
return charBlock;
}
Expected Run
maxBlock("hoopla") → 2 2 OK
maxBlock("abbCCCddBBBxx") → 3 3 OK
maxBlock("") → 0 0 OK
maxBlock("xyz") → 1 1 OK
maxBlock("xxyz") → 2 2 OK
maxBlock("xyzz") → 2 2 OK
maxBlock("abbbcbbbxbbbx") → 3 3 OK
maxBlock("XXBBBbbxx") → 3 3 OK
maxBlock("XXBBBBbbxx") → 4 4 OK
maxBlock("XXBBBbbxxXXXX") → 4 4 OK
maxBlock("XX2222BBBbbXX2222") → 4 4 OK
other tests X
This can be more efficient especially with a helper method! Don't overthink the problem, I know its hard. My strategy is get the block for this char and move on to the next one.
public int maxBlock(String str) {
if (str.length() == 0) {
return 0;
}
int biggest = Integer.MIN_VALUE;
for (int a = 0; a < str.length(); a++) {
biggest = Math.max(biggest, (countBlock(str, str.substring(a, a + 1), a));
}
return biggest; //by now we have the biggest
}
public int countBlock(String s, String any, int startIndex) {
int cnt = 1;
for (int a = startIndex + 1; a < s.length(); a++) { //start right after index
if (s.substring(a, a + 1).contains(any)){ //keep going
cnt++;
}
else if (!s.substring(a, a + 1).equals(any)) { //stop here
break;
}
}
return cnt;
}
Your code is good but you are unnecessarily checking the length of the input string.
Here is your code with some improvements.
public int maxBlock(String str) {
int holder = 1;
int charBlock = 0;
for(int i=0; i < str.length()-1; i++){ //loop through each char value
if (str.charAt(i) == str.charAt(i+1)){
holder++;
}else{
holder = 1;
}
if(holder > charBlock){
charBlock = holder; //update the value of charBlock if a holder is larger current value
}
}
return charBlock;
}
Related
I'm trying to solve the staircase problem in java with a method that gets the number of stairs (n) and the maximum step size (maxStep). Somehow it works until step size is > 3 after that I get a Stackoverflow error but I don't know why that is.
public static int climbStairs(int n, int maxStep) {
if (n == 0 || n == 1) {
return 1;
} else if (n == 2) {
return 2;
} else {
int count = 0;
for (int i = 1; i <= maxStep; i++) {
count += climbStairs(n - i, maxStep);
}
return count;
}
}
Try this code hope it will work.
public static int climbStairs2(int n, int maxStep) {
if (n == 0 || n == 1) {
return 1;
} else if (n < maxStep) {
return n;
} else {
int count = 0;
for (int i = 1; i <= maxStep; i++) {
count += climbStairs2(n - i, maxStep);
}
return count;
}
}
You don't check whether the maxstep is smaller than the step count. This means that after a while, the i<=maxstep can be > n, which results in negative n for the next recursion. If it once turns to the negatives, it will recurse infinitely. To fix it, just check for n<=maxstep or n<=0.
Example of your 'bad' code: Try inputs 5,4: it will start the method with n=
5
4
3
-1
-2
Given a String only made of only 2 letters a,b. Now the task is to split this string into exactly 3 groups such that the number of a's in each group must be same. Then find how many such groups are possible.
Example:
Input:
ababab
Possiblities:
ab ab ab
Output:
1 as we can create only 1 such group, with single a in each group
Example:
Input:
ababbabbaaba
Possiblities:
aba bbabba aba
abab babba aba
ababb abba aba
Output:3
as we can create 3 such possible groups with 2 a's in each group.
Now I came across below code that is solving this task.
public static int findGroups(String input) {
int numberOfAs = 0;
for (int i = 0; i < input.length(); i++) {
if (input.charAt(i) == 'a')
numberOfAs++;
}
int n = input.length();
if (numberOfAs == 0) {
return (n - 1) * (n - 2) / 2;
}
if (numberOfAs % 3 != 0)
return 0;
int numberOfAsInAGroup = numberOfAs / 3;
int lastAIn1stGroup = 0; // last occurrence of A in 1st group
int firstAIn2ndGroup = 0; // 1st occurrence of A in 2nd group
int lastAIn2ndGroup = 0; // last occurrence of A in 2nd group
int firstAIn3rdGroup = 0; // 1st occurrence of A in 3rd group
int aCount = 0;
for (int i = 0; i < n; i++) {
if (input.charAt(i) == 'a') {
aCount++;
if (aCount == numberOfAsInAGroup) {
lastAIn1stGroup = i;
} else if (aCount == numberOfAsInAGroup + 1) {
firstAIn2ndGroup = i;
}
if (aCount == 2 * numberOfAsInAGroup) {
lastAIn2ndGroup = i;
} else if (aCount == 2 * numberOfAsInAGroup + 1) {
firstAIn3rdGroup = i;
break;
}
}
}
int betweenSecondAndFirstGroup = firstAIn2ndGroup - lastAIn1stGroup;
int betweenThirdAndSecondGroup = firstAIn3rdGroup - lastAIn2ndGroup;
return betweenSecondAndFirstGroup * betweenThirdAndSecondGroup;
}
This code is working perfectly finw without any errors. But I am trying to understand for past several days what formulas are being used in this code to solve this task.
Part - 1:
if (numberOfAs == 0) {
return (n - 1) * (n - 2) / 2;
}
After searching in google for several hrs I found the explanation here - number-of-ways-of-distributing-n-identical-objects-among-r-groups:
Part - 2:
int betweenSecondAndFirstGroup = firstAIn2ndGroup - lastAIn1stGroup;
int betweenThirdAndSecondGroup = firstAIn3rdGroup - lastAIn2ndGroup;
return betweenSecondAndFirstGroup * betweenThirdAndSecondGroup;
I am not able to understand this part 2 formula, how this is solving the given problem, is there any explanation as mentioned for part 1.
Also just curious to know, is there any alternate version to solve this task without using formulas like this?
It can be done in linear time.
public class Main {
public static int Nth_A_After(String s, int n, int index){
for(int i = index + 1; i < s.length(); i++) {
if(s.charAt(i) == 'a'){
n--;
if(n == 0) return i;
}
}
return -1;
}
public static void main(String[] args) {
String s = "ababab";
int count = 0;
for(int i = 0; i < s.length(); i++) if(s.charAt(i) == 'a') count++;
if(count % 3 != 0) {
System.out.println("Impossible!");
return;
}
int pos = count / 3;
int firstEnd = Nth_A_After(s, pos, -1);
int secondBegin = Nth_A_After(s, 1, firstEnd);
int secondEnd = Nth_A_After(s, pos - 1, secondBegin);
int thirdBegin = Nth_A_After(s, 1, secondEnd);
int leftDif = secondBegin - firstEnd;
int rightDif = thirdBegin - secondEnd;
if(leftDif > 1) leftDif++;
if(rightDif > 1) rightDif++;
System.out.println(leftDif * rightDif);
}
}
I guess there is a problem in your example ababab, since there is more than just one possibility:
1. a ba bab
2. a bab ab
3. ab a bab
4. ab ab ab
The code you're looking at is finding the boundary As of each group, then is counting the number of spaces the dividing line between the groups could go. This depends on the number of Bs separating the groups of As, since these don't affect the count.
The answer is the number of possible dividing lines on the left, times the number on the right.
AA|B|B|AABAA <-- in this example there are 3 on the left
AABBAA|B|AA <-- and 2 on the right
for a total of 6.
AA|BBAA|BAA
AA|BBAAB|AA
AAB|BAA|BAA
AAB|BAAB|AA
AABB|AA|BAA
AABB|AAB|AA
So I just had a lesson on loops and nested loops. My professor said that nested loops can help us do tasks such as knowing if we rolled 2 different matching pairs with 4 dices (4242) I'm a bit confused on how that would work.
So I started to work it out and this is what I was able to create.
public boolean 4matchDice(String dice){
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
}
}
I used boolean as the return as it will tell us whether or not we have 2 different matching pairs.
Thing is, what do I put in the the loops? That's what's confusing me the most.
Here's a solution I came up with, seems to be returning the correct outcome for all the test cases I ran.
public static boolean matchDice(String dice) {
char[] diceArray = dice.toCharArray();
int pairs = 0;
for (int i = 0; i < 4; i++) {
for (int j = i + 1; j < dice.length(); j++) {
if (diceArray[i] == diceArray[j]) {
diceArray[i] = 'X';
diceArray[j] = 'Y';
pairs++;
}
}
}
return (pairs > 1);
}
If you're only comparing two sets with two dice each, this is enough:
public boolean match4Dice(int first, int second, int third, int fourth) {
if ((first == third && second == fourth) || (first == fourth && second == third)) {
return true;
}
return false;
}
But if you're comparing 2 sets with any number of dice, the following algorithm would suit you better.
public boolean matchDice(String firstDiceSet, String secondDiceSet) {
// validate input, string must contain numbers from 1 - 6 only.
// lenghts of strings firstDiceSet & secondDiceSet must be equal
// works for any number of dice in each set.
// The dice only match if all numbers in the firstDiceSet all present in the secondDiceSet also.
// Let us count the matching numbers to check if this true.
int numberOfMatches = 0;
for (int i = 0; i < firstDiceSet.length(); i++) {
for (int j = 0; j < secondDiceSet.length(); j++) {
if (firstDiceSet[i] == secondDiceSet[j]) { // and not used
// increment number of matches
// mark secondDiceSet[j] as used, so that you do not count the same match twice.
// account for cases where firstDiceSet = "33" and the secondDiceSet = "35"
}
}
}
// your dice set match if the following condition is true
return (numberOfMatches == secondDiceSet.length());
}
Hi I just coded up a solution that will take "4242" as an input, although sindhu_sp's method is more practical i believe. I just wanted to show you another example to help your learning of java!
public static boolean fourMatchDice(String dice){
int match = 0;
for (int i = 0; i < dice.length(); i++){
for (int j = i+1; j < dice.length(); j++){
if (dice.toCharArray()[i] == dice.toCharArray()[j]){
System.out.println("does " + dice.toCharArray()[i] + " = " + dice.toCharArray()[j]);
match ++;
}
}
}
if(match == 2) *EDIT* //Change to (match >= 2) if 4 of the same pair is allowed.
return true;
return false;
}
public static void main(String[] args) {
System.out.println(fourMatchDice("4242"));
}
output:
does 4 = 4
does 2 = 2
true
For the PermCheck codility test, I coded one solution (please see below) but it only really solved the example given in the codility test because there are only a few values in the array and small values. I also added code below which scored 100%, which is code I found on the internet. That code looks very different from mine and I couldn't work out how he/she was able to get the answer. Could someone please explain the code step by step and how it results in the answer please.
Codility Test:
PermCheck
Check whether array A is a permutation.
A non-empty zero-indexed array A consisting of N integers is given.
A permutation is a sequence containing each element from 1 to N once, and only once.
For example, array A such that:
A[0] = 4
A[1] = 1
A[2] = 3
A[3] = 2
is a permutation, but array A such that:
A[0] = 4
A[1] = 1
A[2] = 3
is not a permutation, because value 2 is missing.
The goal is to check whether array A is a permutation.
Write a function:
class Solution {
public int solution(int[] A);
}
that, given a zero-indexed array A, returns 1 if array A is a permutation and 0 if it is not.
For example, given array A such that:
A[0] = 4
A[1] = 1
A[2] = 3
A[3] = 2
the function should return 1.
Given array A such that:
A[0] = 4
A[1] = 1
A[2] = 3
the function should return 0.
Assume that:
N is an integer within the range [1..100'000];
Each element of array A is an integer within the range [1..1'000'000'000].
Complexity:
Expected worst-case time complexity is O(N)
Expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
100% Score Solution (found from internet):
public static final int NOT_PERMUTATION = 0;
public static final int PERMUTATION = 1;
// (4,1,3,2) = 1
// (4,1,3) = 0
// (1) = 1
// () = 1
// (2) = 0
public int PermSolution(int[] A) {
// write your code in Java SE 8
int[] mark = new int[A.length + 1];
int counter = 0;
for (int i = 0; i < A.length; ++i) {
int value = A[i];
if(value >= mark.length) {
return NOT_PERMUTATION;
}
if(mark[value] == 0) {
mark[value]=1;
++counter;
} else {
return NOT_PERMUTATION;
}
}
return counter == A.length ? PERMUTATION : NOT_PERMUTATION;
}
My Solution:
public int PermSolution(int[] A)
{
int perm = 1;
Arrays.sort(A);
if (A[0] != 1) return 0;
for (int i = 0; i < A.length; i++)
{
if (A[i] + 1 == A[i + 1])
{
return perm;
}
if (A[i] + 1 != A[i + 1])
{
return 0;
}
}
return perm;
}
Using Arrays.sort() is kind of original, that's not how I would have done it though.
To comment your code, it's probably isn't working because of this : return perm;
Let's say you have this Array which is not a permutation:
A[0] = 4
A[1] = 1
A[2] = 2
One you execute Arrays.sort(A), you'll have this :
A[0] = 1
A[1] = 2
A[2] = 4
Now let's execute your code :
if (A[0] != 1) return 0;
A[0] is indeed equal to 1
Next, for i==0 we have :
if (A[i] + 1 == A[i + 1])
{
return perm;
}
A[i] + 1 is equal 2 and A[i+1] is also equal to 2
the condition being true, you execute a return perm; and thus, you end your execution with a return 1.
Actually, as long as your array contains 1 and 2, this function will always return 1
For it to work, you'll have to check all of the array before actually returning a value.
This should work :
public int PermSolution(int[] A)
{
int perm = 1;
Arrays.sort(A);
if (A[0] != 1) return 0;
for (int i = 0; i < A.length; i++)
{
if (A[i] + 1 != A[i + 1])
{
return 0;
}
}
return perm;
}
To optimize it even further, this should work as well :
public int PermSolution(int[] A)
{
Arrays.sort(A);
for (int i = 0; i < A.length; i++)
{
if (A[i] != i+1)
{
return 0;
}
}
return 1;
}
Why don't we avoid Arrays.sort(A) in order to gain the computation efficiency by below:
public static int PermSolution(int[] A)
{
int len=A.length;
if(len==1)
return A[0]==1 ? 1 : 0;
BitSet set=new BitSet(len+2);
for (int i = 0; i < len; i++)
{
if(A[i]>len || set.get(A[i]))
return 0;
set.set(A[i]);
}
return set.nextClearBit(1)==(len+1) ? 1 : 0;
}
Here is some solution that I have developed. Not sure about constraints, if someone can help to test it against them. Thanks people!
private static int solution(int[] arr) {
int perm=1;
boolean b=false;
Arrays.sort(arr);
int i=0;
while (i<=arr.length) {
if(i < arr.length-2)
b = arr[i+1]-1 == (arr[i]);
if(b) {
System.out.println("if " + i);
i++;
perm=1;
}else {
System.out.println("else " + i);
perm = 0;
break;
}
}
return perm;
}
i have made a java program for following problem statement -
"Dividing a set of numbers in to two sets such that sum of elements in each set must be equal "
input: array of integers
output:
"Yes"-if set can be divided in to two equal sum,
"No" -if can not be divided in to two equal sum,
"Invalid" -if integer array contains any other type of Integers(excepting positive integers)
and i have submitted the code to an online compiler and the code i have written has passed 8 test cases out of 10.i tried hard but i couldnt succeed finding those two test cases which failed . what are those two test-cases which failed ? here's the code -
public class CandidateCode {
public static String partition(int[] arr) {
int sum = getSum(arr);
int half = sum / 2;
int out = 0;
int i = 0;
boolean flag = false;
if (hasZero(arr)) {
return "Invalid";
}
if (sum % 2 != 0) {
return "No";
}
if (arr.length == 2) {
if (arr[0] == arr[1]) {
return "Yes";
}
return "No";
}
else {
while (i < arr.length) {
if (arr[i] < half)
out += arr[i];
if (out == half) {
flag = true;
break;
}
i++;
}
}
if (flag)
return "Yes";
else
return "No";
}
public static int getSum(int[] arr) {
int result = 0;
for (int i = 0; i < arr.length; i++) {
result += arr[i];
}
return result;
}
public static boolean hasZero(int[] arr) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] <= 0) {
return true;
}
}
return false;
}
}
One test case that would fail is an array consisting of:
4 8 4