Alternate Solution for maxBlock from CodingBat - java
Solving this problem from codingBat
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.
maxBlock("hoopla") → 2
maxBlock("abbCCCddBBBxx") → 3
maxBlock("") → 0
I was trying to solve it using one for loop as below:
public int maxBlock(String str) {
int maxCounter=1;
int counter=1;
if(str.length()==0)
{
return 0;
}
for(int i=0;i<str.length()-1;i++)
{
if(str.substring(i,i+1).equals(str.substring(i+1,i+2)))
{
counter++;
}
if(counter>maxCounter)
{
maxCounter=counter;
counter=0;
}
}
return maxCounter;
}
It beats all the cases apart from one. Can anybody show a solution with one for loop?
Sorry for mentioning late but you can't use REGEX or anything from collections framework.
I think you get it wrong in certain edge cases:
public int yourMaxBlock(String str) {
int maxCounter = 1;
int counter = 1;
if (str.length() == 0) {
return 0;
}
for (int i = 0; i < str.length() - 1; i++) {
if (str.substring(i, i + 1).equals(str.substring(i + 1, i + 2))) {
counter++;
}
if (counter > maxCounter) {
maxCounter = counter;
counter = 0;
}
}
return maxCounter;
}
public int myMaxBlock(String str) {
int maxCounter = 1;
int counter = 1;
if (str.isEmpty()) {
return 0;
}
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i - 1) == str.charAt(i)) {
if (++counter > maxCounter) {
maxCounter = counter;
}
} else {
counter = 1;
}
}
return maxCounter;
}
public void test() {
String[] tests = new String[]{
"", "+", "++", "+++,++,++,+", "+,++,+++,++,", "+,++,+++,++++", "+++++,++,+++,++++"
};
for (String s : tests) {
int myMax = myMaxBlock(s);
int yourMax = yourMaxBlock(s);
System.out.println("myMaxBlock(" + s + ") = " + myMax + (myMax != yourMax ? " WRONG! you have " + yourMax : ""));
}
}
prints
myMaxBlock() = 0
myMaxBlock(+) = 1
myMaxBlock(++) = 2
myMaxBlock(+++,++,++,+) = 3
myMaxBlock(+,++,+++,++,) = 3
myMaxBlock(+,++,+++,++++) = 4 WRONG! you have 3
myMaxBlock(+++++,++,+++,++++) = 5 WRONG! you have 4
You can use a Pattern matcher "(.)(\\1)*" that look for repeated char in the String , Here is the code :
public int maxBlock(String str) {
Pattern pattern = Pattern.compile("(.)(\\1)*");
Matcher matcher = pattern.matcher(str);
int max = 0;
while (matcher.find()) {
max = Math.max(max, matcher.group().length());
}
return max;
}
I'm a little late to the party, but here's my CodingBat solution:
public int maxBlock(String str) {
int max = 0;
int count = 1;
char o = ' ';
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c == o) {
count++;
if (count > max) { max = count; }
} else {
count = 1;
if (count > max) { max = count; }
}
o = c;
}
return max;
}
Here's a solution based loosely on yours. Note the use of charAt for a neater looking code example.
This starts at the second character of the string and looks backwards to see if we are still encountering the same character. If so, the counter increases. When we finish a string of identical chars, we compare against the max length found thus far and update if necessary.
public static int maxBlock(String str) {
int maxCounter = 1;
int counter = 1;
if (str.length() == 0) {
return 0;
}
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i - 1) == str.charAt(i)) {
counter++;
} else {
// end of a run
if (counter > maxCounter) {
maxCounter = counter;
}
counter = 1;
}
}
return Math.max(maxCounter, counter);
}
Just use one for loop. I think here is another way.
public int maxBlock(String str) {
int len = str.length();
int temp=(len>0)?1:0;
int r =0;
for(int i=1; i<len; i++){
if(str.charAt(i) == str.charAt(i-1)){
temp++;
}
else{
r = (temp>r)?temp:r;
temp=1;
}
}
r = (temp>r)?temp:r;
return r;
}
public int maxBlock(String str) {
int max = 0;
for(int i = 0 ; i < str.length() ; i ++ ) {
char compareChar = str.charAt(i);
int count = 0;
while (i + 1 < str.length()
&& compareChar == str.charAt(i+1)) {
i++;
count ++;
}
if (max < count + 1) {
max = count + 1;
}
}
return max;
}
Here's my solution. It's simpler than you think.
public int maxBlock(String str)
{
//create a counter to return
int counter = 0;
//create a temporary variable to store a running total.
int temp = 1;
//Start on the first character and test to see if the second
//character equals the first.
for (int i = 1; i < str.length(); i++)
{
//If it does, we increment the temp variable.
if (str.charAt(i) == str.charAt(i-1))
{
temp++;
}
//If it doesn't, we wipe the temp variable and start from one.
else
{
temp = 1;
}
//If the temporary variable exceeds the counter amount, we make
//the counter variable equal to the temp variable.
if (temp > counter)
{
counter = temp;
}
}
//Return the counter.
return counter;
}
public int maxBlock(String str) {
int maxLength = 0;
Map<String,Integer> map = new HashMap<String,Integer>();
for(int i = 0; i< str.length(); i++){
String key = str.substring(i,i+1);
if(i!=0 && str.charAt(i) == str.charAt(i-1) && map.containsKey(key)){
map.put(key, map.get(key)+1);
}
else{
map.put(key,1);
}
}
for(Map.Entry<String,Integer> entry : map.entrySet()){
if(maxLength <entry.getValue()){
maxLength = entry.getValue();
}
}
return maxLength;
}
public int maxBlock(String str) {
int count = 0;
int i = 0;
int maxcount = 0;
if (str.length() == 0) return 0;
while (i < str.length() - 1) {
if (str.charAt(i) == str.charAt(i + 1)) {
count++;
if (count > maxcount) {
maxcount = count;
}
} else count = 0;
i++;
}
return maxcount + 1;
}
public int maxBlock(String str) {
int tcount = 0;
if (str.length() < 1) {
return 0;
}
for (int i = 0; i < str.length(); i++) {
int count = 0;
for (int j = i; j < str.length(); j++) {
if (str.charAt(i) == str.charAt(j)) {
count++;
} else
break;
}
if (count > tcount) {
tcount = count;
}
i += count - 1;
}
return tcount;
}
this is easier it totally works.
int i = 0;
int j = 0;
while(i < inner.length && j < outer.length) {
if(inner[i] > outer[j]) {
j++;
} else if(inner[i] < outer[j]) {
return false;
} else {
i++;
}
}
if(i != inner.length)
return false;
return true;
}
Here My code for this
public int maxBlock(String str) {
int count = 1;
for(int i=0;i<str.length()-1;i++){
int count2 = 0;
if(str.substring(i,i+1).equals(str.substring(i+1,i+2) )){
for(int j = i ; j < str.length();j++){
if(str.substring(i,i+1).equals(str.substring(j,j+1))){
++count2;
}
else{
break;
}
}
}
if(count2 > count){
count = count2;
}
}
if(str.isEmpty())return 0;
return count;
}
Related
boyer moore algorithm : to make it more efficient with java
According to work mates, the following implementation the boyer moore algorithm is not that very efficient. I don't seem to know what i'm doing wrong to not get it to be of good quality result. I have tested it and it works very well, the only thing I need to do is to get work efficiently. Can I get any help with this one? this is the code implemantation in .java int findLocation(String needle, String haystack) { if (needle == null || haystack == null || needle.length() > haystack.length()) { return -1; } char[] nNeedle = needle.toCharArray(); char[] hHaystack = haystack.toCharArray(); int[] good_shift = new int[nNeedle.length]; for (int i = 0; i < nNeedle.length; i++) { good_shift[i] = goodshift(nNeedle, i); } int[] bad_shift = new int[MAX_CHARACTERS]; for (int i = 0; i < MAX_CHARACTERS; i++) { bad_shift[i] = nNeedle.length; } int offset = 0; int scan = 0; int last = nNeedle.length - 1; int maxoffset = hHaystack.length - nNeedle.length; for (int i = 0; i < last; i++) { bad_shift[nNeedle[i]] = last - 1; } while (offset <= maxoffset) { for (scan = last; nNeedle[scan] == hHaystack[scan + offset]; scan--) { if (scan == 0) { return offset; } } offset += Math.max(bad_shift[hHaystack[offset + last]], good_shift[last - scan]); } return -1; } int goodshift(char[] needle, int matches) { if (matches >= needle.length || matches < 0) { return -1; } if (matches == 0) { return 1; } int max = needle.length - 1; int offset = max; int last = matches - 1; while (offset >= 1) { --offset; for (int i = 0; (offset - i >= 0) && needle[(max - i)] == needle[(offset - i)]; i++) { if ((offset - i) == 0) { return max - offset; } if (i == last) { if (needle[(max - matches)] != needle[(offset - matches)]) { return max - offset; } else { break; } } } } return needle.length; }
How can I modify the boyer moore algorithm so that it runs in 0(n+m) time?
So I'm using the Boyer-Moore function and trying to integrate the failure function from the KMP and I don't know how to do that per se. I added the calling method to the failure function but I don't know how to make use of it. The two methods are given below. public static int findBoyerMoore(char[] text, char[] pattern) { int n = text.length; int m = pattern.length; int[] fail = computeFailKMP(pattern); ---> I did this but how can I use fail? if(m == 0){ return 0; } Map<Character, Integer> last = new HashMap<>(); for(int i = 0; i< n; i++) { last.put(text[i], -1); } for(int k = 0; k < m; k++) { last.put(pattern[k], k); } int i = m - 1; int k = m - 1; while(i < n) { if(text[i] == pattern[k]) { if(k == 0) { return i; } i--; k--; } else { i+= m - Math.min(k, 1+ last.get(text[i])); k = m-1; } } return -1; } public static int[] computeFailKMP(char[] pattern) { int m = pattern.length; int[] fail = new int[m]; int j = 0; int k = 0; while(j < m) { if(pattern[j] == pattern[k]) { fail[j] = k + 1; j++; k++; } else if(k > 0) { k = fail[k - 1]; } else { j++; } } return fail; }
Searching for a sum in an array
I have a method which counts how many sums of 3 elements,which are equal to 0, does the array contains. I need help finding the way to stop counting the same triplets in the loop. For instance, 1 + 3 - 4 = 0, but also 3 - 4 +1 = 0.Here is the method: private static int counter(int A[]) { int sum; int e = A.length; int count = 0; for (int i=0; i<e; i++) { for (int j=i+1; j<e; j++) { sum=A[i]+A[j]; if(binarySearch(A,sum)) { count++; } } } return count; edit: I have to use the Binary Search (the array is sorted). Here is the binarySearch code: private static boolean binarySearch(int A[],int y) { y=-y; int max = A.length-1; int min = 0; int mid; while (max>=min) { mid = (max+min)/2; if (y==A[mid]) { return true; } if (y<A[mid]) { max=mid-1; } else { min=mid+1; } } return false;
You can avoid counting different triplets by making one assumption that we need to look for the triplets (x,y,z) with x < y < z and A[x] + A[y] + A[z] == 0. So what you need to do is to modify the binarySearch function to return the number of index that greater than y and has A[z] == -(A[x] + A[y]) private static int binarySearch(int A[],int y, int index) { y=-y; int max = A.length-1; int min = index + 1; int mid; int start = A.length; int end = 0; while (max>=min) { mid = (max+min)/2; if (y==A[mid]) { start = Math.min(start, mid); max = mid - 1; } else if (y<A[mid]) { max=mid-1; } else { min=mid+1; } } int max = A.length - 1; int min = index + 1; while (max>=min) { mid = (max+min)/2; if (y==A[mid]) { end = Math.max(end, mid); min= mid + 1; } else if (y<A[mid]) { max=mid-1; } else { min=mid+1; } } if(start <= end) return end - start + 1; return 0; } So the new function binarySearch will return the total number of index that greater than index and has value equals to y. So the rest of the job is to count the answer private static int counter(int A[]) { int sum; int e = A.length; int count = 0; for (int i=0; i<e; i++) { for (int j=i+1; j<e; j++) { sum=A[i]+A[j]; count += binarySearch(A,sum, j); } } return count; } Notice how I used two binary search to find the starting and the ending index of all values greater than y!
private static int counter(int A[]) { int e = A.length; int count = 0; for (int i = 0; i < e; i++) { for (int j = 1; (j < e - 1) && (i != j); j++) { for (int k = 2; (k < e - 2) && (j != k); k++) { if (A[i] + A[j] + A[k] == 0) { count++; } } } } return count; }
private static int counter(int ints[]) { int count = 0; for (int i = 0; i < ints.length; i++) { for (int j = 0; j < ints.length; j++) { if (i == j) { // cannot sum with itself. continue; } for (int k = 0; k < ints.length; k++) { if (k == j) { // cannot sum with itself. continue; } if ((ints[i] + ints[j] + ints[k]) == 0) { count++; } } } } return count; }
To solve problem with binary search Your code was almost correct. all you needed to do was just to replace if (sum == binarySearch(A,sum)) { with this if (binarySearch(A,sum)) { I am assuming that your binarySearch(A, sum) method will return true if it will found sum in A array else false private static int counter(int A[]) { int sum; int e = A.length; int count = 0; for (int i=0; i<e; i++) { for (int j=i+1; j<e; j++) { sum=A[i]+A[j]; if (binarySearch(A,sum)) { count++; } } } return count; }
Here is my solution assuming the array is sorted and there are no repeated elements, I used the binary search function you provided. Could the input array contain repeated elements? Could you provide some test cases? In order to not counting the same triplets in the loop, we should have a way of inspecting repeated elements, the main idea that I used here is to have a list of int[] arrays saving the sorted integers of {A[i],A[j],-sum}.Then in each iteration I compare new A[i] and A[j] to the records in the list, thus eliminating repeated ones. private static int counter(int A[]){ int sum; int e = A.length; int count = 0; List<int[]> elements = new ArrayList<>(); boolean mark = false; for (int i=0; i<e; i++) { for (int j=i+1; j<e; j++) { sum=A[i]+A[j]; if (-sum == binarySearch(A,sum)){ int[] sort = {A[i],A[j],-sum}; if(-sum == A[i] || -sum == A[j]){ continue; }else{ Arrays.sort(sort); //System.out.println("sort" + sort[0] + " " + sort[1]+ " " + sort[2]); for (int[] element : elements) { if((element[0] == sort[0] && element[1] == sort[1]) && element[2] == sort[2]) mark = true; } if(mark){ mark = false; continue; }else{ count++; elements.add(sort); //System.out.println("Else sort" + sort[0] + " " + sort[1]); } } } } } return count; }
you can use a assisted Array,stored the flag that indicate if the element is used; Here is the code: private static int counter(int A[]) { int sum; int e = A.length; int count = 0; // assisted flag array List<Boolean> flagList = new ArrayList<Boolean>(e); for (int k = 0; k < e; k++) { flagList.add(k, false);// initialization } for (int i=0; i<e; i++) { for (int j=i+1; j<e; j++) { sum=A[i]+A[j]; // if element used, no count if(binarySearch(A,sum)&& !flagList.get(i)&& !flagList.get(j)) { count++; flagList.set(i, true); flagList.set(j, true); } } } return count;
How to return to beginning of while loop java
How to break out of forloop and return to beginning of while loop. My function should return 111221 when I input 1211 since there is one 1, one 2, and two 1's. If anyone has any ideas, I'd really appreciate it. public static String occurence(String input) { int s = 0; String out = ""; int count = 0; while(s < input.length()) { int num = getInt(input, s); for(int r = s; r < input.length(); r++) { if(num == getInt(input, r)) { count++; } else { System.out.println(count); out += count; out += num; s += count; count = 0; // Jump to start of while loop } } } return out; }
Use the break statement public static String occurence(String input){ int s = 0; String out = ""; int count = 0; while(s<input.length()){ //System.out.println(s); int num = getInt(input, s); for(int r = s; r<input.length(); r++){ if(num == getInt(input, r)){ count++; }else{ System.out.println(count); out+=count; out+=num; s+=count; count = 0; break; } } } return out; }
Sorting an array of String objects on J2ME platform
What is the best(fastest) way to sort an array of Strings (using Java 1.3).
You can use this code for sort the string values, public Vector sort(String[] e) { Vector v = new Vector(); for(int count = 0; count < e.length; count++) { String s = e[count]; int i = 0; for (i = 0; i < v.size(); i++) { int c = s.compareTo((String) v.elementAt(i)); if (c < 0) { v.insertElementAt(s, i); break; } else if (c == 0) { break; } } if (i >= v.size()) { v.addElement(s); } } return v; } Also see this sample code for using bubble sort, static void bubbleSort(String[] p_array) throws Exception { boolean anyCellSorted; int length = p_array.length; String tmp; for (int i = length; --i >= 0;) { anyCellSorted = false; for (int j = 0; j < i; j++) { if (p_array[j].compareTo(p_array[j + 1]) > 0) { tmp = p_array[j]; p_array[j] = p_array[j + 1]; p_array[j + 1] = tmp; anyCellSorted = true; } } if (anyCellSorted == false) { return; } } }
Use java.util.Arrays.sort. If it's not possible for some reason due to limitations of the platform, you can get ideas from its source.