mergeTwo CodingBat puzzle in Java - java

I am trying to solve this CodingBat problem:
Start with two arrays of strings, A and B, each with its elements in alphabetical order and without duplicates. Return a new array containing the first N elements from the two arrays. The result array should be in alphabetical order and without duplicates. A and B will both have a length which is N or more. The best "linear" solution makes a single pass over A and B, taking advantage of the fact that they are in alphabetical order, copying elements directly to the new array.
mergeTwo({"a", "c", "z"}, {"b", "f", "z"}, 3) → {"a", "b", "c"}
mergeTwo({"a", "c", "z"}, {"c", "f", "z"}, 3) → {"a", "c", "f"}
mergeTwo({"f", "g", "z"}, {"c", "f", "g"}, 3) → {"c", "f", "g"}
Attempt:
public String[] mergeTwo(String[] a, String[] b, int n) {
String[] op = new String[a.length + b.length];
for (int i = 0; i < a.length; i++) {
op[i] = a[i];
}
int j = 0;
for (int i = 0; i < op.length; i++) {
if (op[i] == null) {
j = i;
break;
}
}
for (int i = 0; i < b.length; i++) {
op[j] = b[i];
j++;
}
Arrays.sort(op);
ArrayList<String> help = new ArrayList<String>();
for (int i = 0; i < op.length - 1; i++) {
if (op[i] != op[i + 1]) {
help.add(op[i]);
}
}
String[] res = new String[help.size()];
for (int i = 0; i < help.size(); i++) {
res[i] = help.get(i);
}
String[] op2 = new String[n];
for (int i = 0; i < n; i++) {
op2[i] = res[i];
}
return op2;
}
So the problem is that all the tests pass except one:
Why is that?

This is the line that has the problem:
if (op[i] != op[i + 1]) {
You are looking for a pattern where the lsst of several identical strings doesn't match the next string.
In the failing case, there is no "next string" because there are exactly 3 unique strings.
One way to deal with that is to look for a pattern where this string is different than the last string but you don't really check the array for the last string (since the 1st array element has no last string). You use a variable, say last, to store the last string and transfer only when this element isn't equal to last.
Try this ...
String last = "";
for (int i = 0; i < op.length - 1; i++) {
if (!op[i].equals(last)) {
help.add(op[i]);
}
last = op[i];
}
Also note that in Java strings are compared with the equals() method.

With Java8 it can be done with few simple rows of code:
public String[] mergeTwo(String[] a, String[] b, int n)
{
Set<String> set = new HashSet();
set.addAll(Arrays.asList(a));
set.addAll(Arrays.asList(b));
List<String> list = new ArrayList(set);
return list.subList(0, n).toArray(new String[n]);
}

Another solution:
public String[] mergeTwo(String[] a, String[] b, int n) {
String[] arr = new String[n];
int aI = 0;
int bI = 0;
for(int i = 0; i < n; i++) {
if(a[aI].compareTo(b[bI]) < 0) {
arr[i] = a[aI];
aI++;
} else if(a[aI].compareTo(b[bI]) > 0) {
arr[i] = b[bI];
bI++;
} else {
arr[i] = a[aI];
aI++;
bI++;
}
}
return arr;
}

Related

how to get String array containing distinct characters?

i have a String "iye" and i want make it distinct and also i have a array ["hi", "bye", "bebe"] and i want to make each element of the array and get the distinct characters only so my array would be like this ["hi", "bye", "be"] an then at last i want to take each element from that distinct array and count how many characters of distinctArray[i] are present in the distinct String "iye" and i will store that count for each element of distinct array in same order respectively to the elements of distinct array for e.g
sample input = "iyee" and ["hi", "bye", "bebe"]
sample ouput = [1, 2, 1]
below is my solution not working for larger inputs
static int[] mathProfessor(String B,String[] a){
List<String> distinct = new ArrayList<String>();
int[] arr = new int[a.length];
// store each value of names array as distinct value
for (int i = 0; i < a.length; i++) {
StringBuilder str = new StringBuilder();
a[i].chars().distinct().forEach(c -> str.append((char) c));
distinct.add(str.toString());
}
// System.out.println("distinct list: " + distinct.toString());
// store the count
int count = 0;
for (int i = 0; i < distinct.size(); i++) {
String s = distinct.get(i);
for (int j = 0; j < B.length(); j++) {
if (s.contains(Character.toString(B.charAt(j))))
count++;
}
arr[i] = count;
count = 0;
}
return arr;
}
static int[] mathProfessor(String b, String[] a) {
b = dist(b);
int count = 0;
String[] arr = new String[a.length];
int[] countArr = new int[a.length];
for (int i = 0; i < a.length; i++) {
arr[i] = dist(a[i]);
}
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < b.length(); j++) {
if (arr[i].contains(Character.toString(b.charAt(j))))
count++;
}
countArr[i] = count;
count = 0;
}
//System.out.println(Arrays.toString(countArr));
return countArr;
}
public static String dist(String s) {
StringBuilder sb = new StringBuilder();
Set<Character> set = new HashSet<Character>();
for (int i = 0; i < s.length(); i++) {
if (set.add(s.charAt(i)) == true)
sb.append(s.charAt(i));
}
return sb.toString();
}
Using Java 8+ Streams:
static int[] mathProfessor(String b, String[] a) {
var distinctB = dist(b);
System.out.println(distinctB);
var result = new int[a.length];
for(int i=0, j=a.length; i < j; i++) {
result[i] = (int) Arrays.stream(dist(a[i]).split("")).filter(distinctB::contains).count();
}
return result;
}
public static String dist(String s) {
Set<String> set = new HashSet<>();
set.addAll(Arrays.asList(s.split("")));
return String.join("", set);
}

Read groups of N adjacent elements from an array

[A, B, C, D, E, F]
I need to get adjacent values from above array.
Adjacent count can vary
say
if adjcnt = 2
Then I should get like this
tuple 1 = A,B
tuple 2 = C,D
tuple 3 = E,F
If adjcnt = 3
tuple 1 = A,B,c
tuple 2 = D,E,F
My code
for (int i = 0; i < arr.length; i++) {
if(i < adjcnt){
if(i==0){
csv = arr[i];
}
else{
csv += ","+arr[i];
}
}
System.out.println("csv---> "+csv);
}
This prints only 2 elements. I need to loop till my arr is empty
Some where my logic is not right.
Please Advice
Change your this code:-
for (int i = 0; i < arr.length; i++) {
if(i < adjcnt){
if(i==0){
csv = arr[i];
}
else{
csv += ","+arr[i];
}
}
System.out.println("csv---> "+csv);
}
to the following
for (int i = 0; i < arr.length; i++) {
if((i % adjcnt) < adjcnt){
if((i % adjcnt)==0){
csv = arr[i];
}
else{
csv += ","+arr[i];
}
}
System.out.println("csv---> "+csv);
}
#include<stdio.h>
int main()
{
int arr[6] = {1,2,3,4,5,6};
int i = 0;
int adjacent = 2;
for(i=0;i<6;i++)
{
if( i% adjacent == 0 ) {
printf("\n");
}
printf("%d",arr[i]);
}
return 0;
}
You can try this way too.
int adjcnt = 3;
String[] arr = {"A", "B", "C", "D", "E", "F"};
for(int i=0; i< arr.length; i= i + adjcnt){
System.out.println(Arrays.toString(Arrays.copyOfRange(arr, i, i+adjcnt)));
//here it will copy your original array between given indexes.
}
out put:
[A, B, C]
[D, E, F]
Unmesha, you can use the following code for your expected output
public class Adjacent {
public static void main(String args[]) {
char[] test = { 'a', 'b', 'c', 'd', 'e', 'f' };
int adjcnt = 3;
StringBuilder csv = new StringBuilder();
int tuplecount = 1;
for (int i = 0; i < test.length; i++) {
if (i % adjcnt == 0 || i == 0) {
if (i != 0)
csv.append("\n");
csv.append("tuple ");
csv.append(tuplecount);
csv.append("=");
csv.append(test[i]);
} else {
csv.append(",");
csv.append(test[i]);
}
}
System.out.println(csv.toString());
}
}
Please update me if this code works out for you

Looping to create a custom String

I am looping to write data to an array of Strings. But what I want is that I create another loop where I will loop through the data of values as much as amount, but I would like to have some guidance on how to do so.
String[] s = new String[20];
String[] values = { "A", "B", "C", "D" };
final int amount = 2;
for (int i = 0; i < s.length; i++) {
s[i] = String.format("%s%04d", values[0], i); //TODO create another loop?
}
System.out.println(Arrays.toString(s));
The preferred output should be:
A0000, A0001, B0002, B0003, C0004, ...
The actual output is:
A0000, A0001, A0002, A0003, A0004, ...
Problem : your looping is wrong.
try this:
public static void main(String[] args) {
int k=0;
String[] s = new String[20];
String[] values = { "A", "B", "C", "D" };
final int amount = 2;
for (int i = 0; i < values.length; i++){
for (int j = 0; j < amount; j++){ //data of values as much as amount
s[k++] = String.format("%s%04d", values[i], k);
}
}
System.out.println(Arrays.toString(Arrays.copyOf(s,k)));
}
output:
[A0001, A0002, B0003, B0004, C0005, C0006, D0007, D0008]
You need to have 2 loops one to loop through the actual values array then another one is the amount (number of times).
Try this
List<String> a = new ArrayList<String>();
String[] values = { "A", "B", "C", "D" };
final int amount = 2;
int incrementVariable = 0;
for (int i = 0; i < values.length; i++){
for(int j = 0; j< amount; j++){
a.add(String.format("%s%04d", values[i], incrementVariable));
incrementVariable +=1;
}
}
System.out.println(a);
}
Output:
[A0000, A0001, B0002, B0003, C0004, C0005, D0006, D0007]
I like while loops better :)
String[] s = new String[10];
String[] values = {"A", "B", "C", "D"};
final int amount = 2;
for (int i = 0; i < values.length; ++i) {
int buffer = 0;
while(buffer <= amount) {
int index = i * amount + buffer;
s[index] = values[i] + String.format("%04d", index);
buffer++;
}
}
System.out.println(Arrays.toString(s));
[A0000, A0001, B0002, B0003, C0004, C0005, D0006, D0007, D0008, null]

Exception:java.lang.NullPointerException when comparing two strings of two different string arrays

I'm coding trough codingbat.com/java and ran into an error i don't understand. I got two String arrays and want to compare them. If I just use the arrays all works fine (but the result is not right). To get the right result I programmed a helper function which eliminates all duplicates of an array. I tested the helper function, it returns the array shortened of the duplicates.
I can retrieve the values in the new Arrays with _a[i] etc., and don't get errors, but if i use _a[0].equals(_b[0]) or _a[0].compareTo(_b[0]) I get a NullPointerException (_a[0] == _b[0] works fine...).
If I just use the original arrays a,b the code runs without problems. I don't comprehend why i get a NullpointerException there.
Thanks for any help!
Code:
public int commonTwo(String[] a, String[] b) {
String[] _a = killDuplicate(a);
String[] _b = killDuplicate(b);
int ai=0, bi=0,count=0;
for (int i = 0; ai < _a.length & bi < _b.length; i++){
if ( _a[ai].compareTo(_b[bi]) > 0) { //NullPointerException here, but not if I use a,b
bi++;
} else if ( _a[ai].compareTo(_b[bi]) < 0){ //NullPointerException here, but not if I use a,b
ai++;
} else {
count++;
ai++;
bi++;
}
}
return count;
}
Helper Function:
public String[] killDuplicate(String[] a){
String temp = "";
int counter = 0, counter2 = 0;
for (int i = 0; i < a.length; i++){
if (! a[i].equals(temp)){
temp = a[i];
} else {
a[i] = "";
counter++;
}
}
String[] result = new String[a.length - counter];
for (int i = 0; counter2 < counter; i++){
if (a[i].equals("")) {
counter2++;
}
} else {
result[i-counter2] = a[i];
}
return result;
}
I guess you assume that your array of strings is sorted, otherwise your killDuplicate method wouldn't make sense at all.
The problem with your code is that in the second for loop in killDuplicate method you iterate with condition counter2 < counter which says iterate until all found duplicates are passed. So when you find your last duplicate you exit without filling the rest of the array. Try with example: new String[]{"A", "A", "B", "C"} you'll get [A, null, null].
There are numerous things that can be improved but the simplest modification of your code below. (I've changed only the second for loop)
public String[] killDuplicate(String[] a) {
String temp = "";
int counter = 0, counter2 = 0;
for (int i = 0; i < a.length; i++) {
if (!a[i].equals(temp))
temp = a[i];
else {
a[i] = "";
counter++;
}
}
String[] result = new String[a.length - counter];
for (int i = 0; i < a.length; i++) {
if (a[i].equals("")) continue;
result[counter2] = a[i];
counter2++;
}
return result;
}

Sorting Arrays for int and string

How to sort an int[] array, do i have to use this or can i just use the in built methods by java?
for (int x = 0; x < days.length - 1; w++) {
for (short i = 0; i < days.length - 1; i++) {
if (days[i].(days[i + 1]) > 0) {
days = days[i];
days[i] = days[i + 1];
days[i + 1] = days;
}
}
}
I wrote a snippet to sort a simple string array. Reproduced below:
int length = winners.length;
for(int i=0; i<length-1; i++){
for(int j=0; j<length-i-1; j++){
if(winners[j].compareTo(winners[j+1]) > 0){
//Swap the elements
String temp = winners[j];
winners[j] = winners[j+1];
winners[j+1] = temp;
}
}
}
for(String winner: winners){
System.out.println(winner);
}
This is working correctly.
If you want to ignore case you can use compareToIgnoreCase method.
The simplest way to sort arrays is with Arrays.sort:
String[] array = {"c", "a", "b"};
Arrays.sort(array);
System.out.println(Arrays.toString(array));
output -> [a, b, c]
String[] array = {"2", "1", "3"};
Arrays.sort(array);
System.out.println(Arrays.toString(array));
output -> [1, 2, 3]
The same process will work for an array of ints (or any primitive) too

Categories

Resources