Am I comparing strings lexicographically correctly? - java

I am creating a method compareTo(AltString altStr2) that sorts strings by their length (shortest to longest).
However, I would like to go the extra mile and check for strings that are of the same length. In that case, I figure it is best to sort the strings lexicographically, so that they are sorted in the same way they would appear in the dictionary. So far my code is below.
public class AltString {
String internalStr;
public AltString(String str) {
internalStr = str;
}
public String toString() {
return internalStr;
}
public int compareTo(AltString altStr2) {
if (this.internalStr.length() < altStr2.internalStr.length()) {
return -1;
} else if (this.internalStr.length() > altStr2.internalStr.length()) {
return 1;
} else {
int idx = 0;
while (this.internalStr.charAt(idx) != altStr2.internalStr.charAt(idx)) {
if (this.internalStr.charAt(idx) < altStr2.internalStr.charAt(idx)) {
return -1;
}else if (this.internalStr.charAt(idx) > altStr2.internalStr.charAt(idx)) {
return 1;
} else {
idx += 1;
public static void main(String[] args) {
// some test code for the AltString class
String [] list = {"fortran", "java", "perl", "python", "php", "javascrip", "c", "c++", "c#", "ruby"};
AltString [] alist = new AltString[list.length];
for (int i=0; i<alist.length; i++) {
alist[i] = new AltString(list[i]);
}
Arrays.sort(list);
Arrays.sort(alist);
System.out.println("String sort:");
for (int i=0; i<list.length; i++) {
System.out.println(list[i]);
}
System.out.println("\nAltString sort:");
for (int i=0; i<alist.length; i++) {
System.out.println(alist[i]);
}
}
The part I am must stuck on is comparing the strings lexicographically. Currently, I have my code setup so that I enter a while-loop and compare each char.
My question is, is this the most efficient way to do this, or is there a better way to compare each string lexicographically in the cases where the strings are the same length?

Following the suggestions of Tunaki and JB Nizet, you can use Integer.compare and String.compareTo. Using String.compareTo does not count as recursion. Recursion is when you call a method from itself, but String.compareTo is a different method from AltString.compareTo.
public int compareTo(AltString altStr2) {
int temp = Integer.compare(this.internalStr.length(), altStr2.internalStr.length());
return temp != 0 ? temp : this.internalStr.compareTo(altStr2.internalStr);
}

Related

Getting distinct subsequences of a string equal to a particular string via recursion

Code logic
In order to find all subsequences of String s that are equal to String t, I made a recursive method getSub() to get all the subsequences of input string s and added it to the list. Now I loop through the list (in numDistinct method) and try to see all those subsequences in the list that matches the string t. In case there is a match count should be incremented and later returned.
BUT
Question
In the following code count never increases, which means the if condition (in numDistinct method) does not work as it was intended. Why t which is a string and list.get(i) which should also return a string doesn't seem to work with equals method?
public static int numDistinct(String s, String t) {
int count = 0;
ArrayList<String> list = new ArrayList<>();
getSub(s, list);
StdOut.println(list);
for (int i = 0; i < list.size(); i++) {
if (t.equals(list.get(i))) {
count++;
}
}
return count;
}
private static int getSub(String s, ArrayList<String> list) {
if (s.length() == 0) {
list.add(" ");
return 1;
}
int smallOutput = getSub(s.substring(1), list);
char[] cha = s.toCharArray();
for (int i = 0; i < smallOutput; i++) {
list.add(cha[0] + list.get(i));
}
return 2 * smallOutput;
}
public static void main(String[] args) {
String s = "rabbbit";
String t = "rabbit";
StdOut.println(numDistinct(s, t));
}
The way you are creating the strings in the list ensures there is a space character at the end of each string. As such, none of them are equal to t.
if (s.length() == 0) {
list.add(""); // remove the space from this line
return 1;
}

How to search the largest string in an array of strings

I need to find the largest string from an array of strings and also want to make sure that the string which comes out should include only those chars which are defined in a separate string.
For eg: if an array of strings contains {"ABCAD","ABC","ABCFHG","AB"}
and another string S have chars "ABCD".
Then the largest string return here should be ABCAD as it contains only the characters defined in S.
public String findstring(String a, String[] arr)
{
String s="";
for(i=0; i<arr.length; i++)
{
//int m=0;
if(arr[i].length() > s.length())
{
s = arr[i];
}
}
for(j=0; j<s.length(); j++)
{
int m=0;
for(k=0; k<a.length(); k++)
{
if(m>0)
{
break;
}
if((s.charAt(j)==a.charAt(k)))
{
m++;
}
else
{
continue;
}
}
if(m==0)
{
List<String> list = new ArrayList<String>(Arrays.asList(arr));
list.remove(s);
arr = list.toArray(new String[0]);
findstring("ABCD", arr);
}
}
return s;
}
}
I am not receiving any error and getting the largest string as ABCFABCD whereas F needs to be excluded and largest string should be ABCAA.
Its skipping all the checks, don't know why?
You can do it in better way using Regex:
public String findstring(final String a, final String[] arr) {
String s = "";
// Created pattern of the characters available in the String
final Pattern p = Pattern.compile("^[" + a + "]*$");
for (int i = 0; i < arr.length; i++) {
if (p.matcher(arr[i]).matches()) {
if ("".equals(s)) {
s = arr[i];
} else if (arr[i].length() > s.length()) {
s = arr[i];
}
}
}
return s;
}
You make recursive call but just ignore the returned value.
Try add return on recursive findstring.
arr = list.toArray(new String[0]);
return findstring("ABCD", arr);
If you want to have the luxury of New & Much Better Java Powers with some elegant, readable and less lines of code... you can have a look at below snippet:
public static void main(String args[]) {
final String allowedChars = "ABCD";
final char[] chars = allowedChars.toCharArray();
String result = Stream.of("ABCAD","ABC","ABCFHG","AB")
.filter(s ->{
for(char c: chars){
if(!s.contains(c+""))
return false;
}
return true;
})
.max(Comparator.comparingInt(String::length))
.orElse("No Such Value Found");
System.out.println("Longes Valid String : " + result);
}
Explanation:
The code makes a Stream of String from arrays and filter only valid strings (Strings which are not containing the allowed characters will simply be removed from the further processing) and remaining Stream will be compared for the length (using Comparator), and finally, longest valid String will be returned.
There may be a case where all the strings in array/Stream would be invalid, in such case, the code will return the Message "No Such Value Found" as String, however you can throw an exception, or you can return some own value for your custom logic, or you can return null, etc.
I've intentionally kept the String message and gave you the hint about learning other methods present in Java Stream so that you can explore more.
Keep Coding... and feel the Power of New JAVA. :)

How to print the string without duplicate?

I tried to print the string without duplicate but i not getting the proper output and here I exposed my code snippets.
class Duplicatestring
{
public static void main(String [] args)
{
String word = "";
String[] ip ={"mani" ," manivannan","raghv ","mani"};
for(int i =0; i<ip.length; i++)
{
for(int j = i+1; j<=ip.length; j++)
{
if(ip[i].equals(ip[j])){
word = word+ip[i];
}
}
System.out.println(word);
}
}
}
And one more thing is I don't want use the collections that is my task and pleas give any proper solution for this.
Example:
Input -> {mani, manivanna,raghv, mani};
output -> {mani, manivanna,raghv}
If you don't want to use collections then I assume it's a homework, so I don't want to provide you a full solution, but I'll guide you.
You can have a helper array of the size of the original array. Now you write two nested loops and for each word, if you find a duplicate, you mark the helper array with 1.
After this procedure you'll have something like this in the helper array:
[0,0,0,1]
Now you iterate on the arrays in parallel and print the element only if the corresponding index in the helper array is 0.
Solution is O(n2).
Your loop is incorrect.
To solve the problem, you can use a Set to eliminate duplicated words.
If the problem must be solved by O(n^2) loops, the following code will work:
public class Duplicatestring {
public static void main(String[] args) {
String[] ip = { "mani", " manivannan", "raghv ", "mani" };
for (int i = 0; i < ip.length; i++) {
boolean duplicated = false;
//search back to check if a same word already exists
for (int j = i - 1; j >= 0; j--) {
if(ip[i].equals(ip[j])) {
duplicated = true;
break;
}
}
if(!duplicated) {
System.out.println(ip[i]);
}
}
}
}
if you want to remove the duplicate from the array call the below method and pass the array has the duplicate values.. it will return you the array with non-duplicate values..
call method here
ip = removeDuplicates(ip);
public static int[] removeDuplicates(int[] arr){
//dest array index
int destination = 0;
//source array index
int source = 0;
int currentValue = arr[0];
int[] whitelist = new int[arr.length];
whitelist[destination] = currentValue;
while(source < arr.length){
if(currentValue == arr[source]){
source++;
} else {
currentValue = arr[source];
destination++;
source++;
whitelist[destination] = currentValue;
}
}
int[] returnList = new int[++destination];
for(int i = 0; i < destination; i++){
returnList[i] = whitelist[i];
}
return returnList;
}
it will return you the non duplicates values array..!!
u may try this:
public class HelloWorld{
public static void main(String []args){
String[] names = {"john", "adam", "will", "lee", "john", "seon", "lee"};
String s;
for (int i = 0; names.length > i; i ++) {
s = names[i];
if (!isDuplicate(s, i, names)) {
System.out.println(s);
}
}
}
private static boolean isDuplicate(String item, int j, String[] items) {
boolean duplicate = Boolean.FALSE;
for (int i = 0; j > i; i++) {
if (items[i].equals(item)) {
duplicate = Boolean.TRUE;
break;
}
}
return duplicate;
}
}
output
john
adam
will
lee
seon
if string order does not matter for you, you can also use the TreeSet.. check the below code.. simple and sweet.
import java.util.Arrays;
import java.util.List;
import java.util.TreeSet;
public class MyArrayDuplicates {
public static void main(String a[]){
String[] strArr = {"one","two","three","four","four","five"};
//convert string array to list
List<String> tmpList = Arrays.asList(strArr);
//create a treeset with the list, which eliminates duplicates
TreeSet<String> unique = new TreeSet<String>(tmpList);
System.out.println(unique);
System.out.println();
Iterator<Integer> iterator = unique.iterator();
// Displaying the Tree set data
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
}
}
it will print as -
[five, four, one, three, two]
five
four
one
three
two

How to sorting two string arrays

I have two arrays:
arrayA = {"b","c","a"}
arrayB = {"99","11","22"}
How do I sort them together so that arrayA = {"a","b","c"} and arrayB = {"22","99","11"}?
I have made one alphanumeric sorting programm Check it out.
import java.util.Arrays;
import java.util.Comparator;
public class AlphanumericSorting implements Comparator {
public int compare(Object firstObjToCompare, Object secondObjToCompare) {
String firstString = firstObjToCompare.toString();
String secondString = secondObjToCompare.toString();
if (secondString == null || firstString == null) {
return 0;
}
int lengthFirstStr = firstString.length();
int lengthSecondStr = secondString.length();
int index1 = 0;
int index2 = 0;
while (index1 < lengthFirstStr && index2 < lengthSecondStr) {
char ch1 = firstString.charAt(index1);
char ch2 = secondString.charAt(index2);
char[] space1 = new char[lengthFirstStr];
char[] space2 = new char[lengthSecondStr];
int loc1 = 0;
int loc2 = 0;
do {
space1[loc1++] = ch1;
index1++;
if (index1 < lengthFirstStr) {
ch1 = firstString.charAt(index1);
} else {
break;
}
} while (Character.isDigit(ch1) == Character.isDigit(space1[0]));
do {
space2[loc2++] = ch2;
index2++;
if (index2 < lengthSecondStr) {
ch2 = secondString.charAt(index2);
} else {
break;
}
} while (Character.isDigit(ch2) == Character.isDigit(space2[0]));
String str1 = new String(space1);
String str2 = new String(space2);
int result;
if (Character.isDigit(space1[0]) && Character.isDigit(space2[0])) {
Integer firstNumberToCompare = new Integer(Integer
.parseInt(str1.trim()));
Integer secondNumberToCompare = new Integer(Integer
.parseInt(str2.trim()));
result = firstNumberToCompare.compareTo(secondNumberToCompare);
} else {
result = str1.compareTo(str2);
}
if (result != 0) {
return result;
}
}
return lengthFirstStr - lengthSecondStr;
}
public static void main(String[] args) {
String[] alphaNumericStringArray = new String[] { "NUM10071",
"NUM9999", "9997", "9998", "9996", "9996F" };
Arrays.sort(alphaNumericStringArray, new AlphanumericSorting());
for (int i = 0; i < alphaNumericStringArray.length; i++) {
System.out.println(alphaNumericStringArray[i]);
}
}
}
Here is the output:
9996
9996F
9997
9998
NUM9999
NUM10071
Use Arrays.sort(arrayB). You can even supply your custom Comparator to affect the sorting.
This link will help you Try array.sort(Arg);
http://www.leepoint.net/notes-java/data/arrays/70sorting.html
If you will be using the same letters and only 1 digit from 0 to 9, then, you can sort it in the same manner you have sorted the first array. If you intend to throw in more letters with more numbers, you will have to implement your own custom comparator (assuming the default behaviour does not suit you).
The answer to the question as written seems so obvious that I think we are not understanding what you are really asking.
I'm guessing that what you are really asking is how to sort one array, and reorder the second array based on how the sort reordered the first array. (Your example is poorly chosen to illustrate this ... but it does in fact doing this.)
Assuming that's what you mean, the simplest way to do this is to turn the two arrays into a single array of pairs, sort the pairs based on the first field, and then use the sorted pair list to repopulate the original arrays.
The (possible) snag is that the total ordering of the second array is indeterminate if the sort is not stable. (Or to put it another way, if there are duplicates in arrayA, then the relative order of the corresponding arrayB elements cannot be predicted.) There are ways to deal with this.
you can use
Arrays.sort(arrayB);
Output is
C1
C2
C3
arrayB = {"22","99","11"}
Arrays.sort(arrayB);
Output:
11
22
99

How to remove null from an array in java

I've written a method to remove null-values from an array i need in a program.
The method, however, doesn't seem to work, the null values won't go away. This is my code so far.
public void removeNull(String[] a)
{
for(int i=0; i<a.length; i++)
{
if(a[i] == null)
{
fillArray(a, i);
}
}
}
public void fillArray(String[] a, int i)
{
String[] a2 = new String[a.length-1];
for(int j=0; j<a2.length; j++)
{
if(j<i)
{
a2[j]=a[j];
}
else if(j>i)
{
a2[j]=a[j+1];
}
}
a=a2;
}
Thanks in advance!
I would advocate doing it the simple way unless performance is really a problem:
public String[] removeNull(String[] a) {
ArrayList<String> removedNull = new ArrayList<String>();
for (String str : a)
if (str != null)
removedNull.add(str);
return removedNull.toArray(new String[0]);
}
Streams API version of the solution:
SomeClass[] array = new SomeClass[N];
...
array = Arrays.stream(array).filter(Objects::nonNull).toArray(SomeClass[]::new);
(I post this down to maybe get some thoughts on applicability, relative performance etc)
hi everyone first of all i want to appologize for my english im learning at this moment and this is my first post so i want to try to put my solution about the problem here it is
String[] removeNulls(String[] nullsArray) {
int countNulls = 0;
for (int i = 0; i < nullsArray.length; i++) { // count nulls in array
if (nullsArray[i] == null) {
countNulls++;
}
}
// creating new array with new length (length of first array - counted nulls)
String[] nullsRemoved = new String[nullsArray.length - countNulls];
for (int i = 0, j = 0; i < nullsArray.length; i++) {
if (nullsArray[i] != null) {
nullsRemoved[j] = nullsArray[i];
j++;
}
}
return nullsRemoved;
}
You can't change the reference to a variable in a method and expect it to be reflected in the calling method.
You'll instead have to return the new array.
public String[] removeNull(String[] a)
{
for(int i=0; i<a.length; i++)
{
if(a[i] == null)
{
a = fillArray(a, i);
}
}
return a;
}
public String[] fillArray(String[] a, int i)
{
String[] a2 = new String[a.length-1];
for(int j=0; j<a2.length; j++)
{
if(j<i)
{
a2[j]=a[j];
}
else if(j>i)
{
a2[j]=a[j+1];
}
}
return a2;
}
This way would be faster:
private static String[] removeNulls(String[] strs) {
int i = 0;
int j = strs.length - 1;
while (i <= j) {
if (strs[j] == null) {
--j;
} else if (strs[i] != null) {
++i;
} else {
strs[i] = strs[j];
strs[j] = null;
++i; --j;
}
}
return Arrays.copyOfRange(strs, 0, i);
}
I can see two errors in your code:
Your method fillArray doesn't cover the case i == j
Your assignation a = a2; doesn't have the effect you think it might have. Arguments are passed by value in Java, and your assignment does NOT change the value of a in your first method. Try returning an instance to a2 in fillArray, and assign this value to a in removeNull.
A couple of things:
Don't you wantString[] a2 = new String[a.length-1];` to be
String[] a2 = new String[a.length];
Won't making it length - 1 make it too short?
You need a case for i == j in your code. This is why the nulls aren't getting updated.
What problem are you trying to solve with the second function? It seems complicated given what I thought your problem was.
Try this (I didn't test it):
public String[] removeNull(String[] a) {
String[] tmp = new String[a.length];
int counter = 0;
for (String s : a) {
if (s != null) {
tmp[counter++] = s;
}
}
String[] ret = new String[counter];
System.arraycopy(tmp, 0, ret, 0, counter);
return ret;
}
This way you can remove nulls in one cycle, but it will not resize array:
public static void removeNull(String[] a) {
int nullCount = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] == null) {
nullCount++;
} else {
a[i-nullCount] = a[i];
}
}
}
This one creates new array, but includes two cycles:
public static String[] removeNull(String[] a) {
int nullCount = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] == null) nullCount++;
}
String[] b = new String[a.length-nullCount];
int j = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] != null) b[j++] = a[i];
}
return b;
}
You can think on optimizing that code using System.arraycopy. I hope the code works.
When removing values in an array, the size changes so you can't keep the same array (you could push the nulls at the end).
The structure close to an array that has a auto-adjustable size is an ArrayList. One option would be :
String[] inputs;
List<String> items = new ArrayList<String>(inputs.length);
for(String input : inputs) {
if (input != null) {
items.add(input);
}
}
String[] outputs = items.toArray(new String[items.size()]);
Performance might be a bit less than working directly with arrays, but because an array has a fixed size, you would need two loops with arrays :
one to count the number of non-null values
after building the array, the same loop to copy the values.
This might not have an ideal performance either, and it is really much more complex to get it right...
Another approach would be to move the nulls at the end, then create a shorter array that wouldn't include the nulls. The idea would be :
String[] strings;
int writeIndex = 0;
int max = strings.length;
for(int readIndex = 0; readIndex < max; readIndex++) {
String read = strings[readIndex];
if (read != null) {
strings[writeIndex++] = read;
}
}
String[] outputs = new String[writeIndex];
System.arraycopy(strings, 0, ouputs, 0, writeIndex);
Well, more people said it before... but I also want to emphasize this solution:
You can use some type of Collection, like ArrayList or List and add only the not null elements. Finally you must return the new String[] formed by the Collection.
Here an example where you can check the correctness:
import java.util.ArrayList;
public class NullRemove {
public static String[] removeNull(String[] a) {
ArrayList<String> aux = new ArrayList<String>();
for (String elem : a) {
if (elem != null) {
aux.add(elem);
}
}
return (String[]) aux.toArray(new String[aux.size()]);
}
public static void main(String[] args) {
String[] init = new String[]{"aaa", null, "bbb", "ccc", null, "ddd",
"eee", "fff", null};
String[] result = NullRemove.removeNull(init);
System.out.println("Start Check result");
for (String elem : result) {
if (elem == null) System.out.println("NULL element");
}
System.out.println("End Check result");
}
}
The for with the code don't print anything cause there is any null element :)
Regards!
You have two options:
Create new array that length is same as the input, then assign to it not null values and add the substract it to the count of not null elememts .
Example in 0xJoKe answer.
If You need to work only sutch array you could create an adapter for it.
public class NullProofIterable<T> implements Iterable<T>{
private final T[] array;
public NullProofIterable(T[] array){
this.array = array;
}
#Override
public Iterator<T> iterator() {
return new NullProofIterator<T>(this.array);
}
private static class NullProofIterator<T> implements Iterator<T> {
private final T[] array;
private final int index = 0;
private NullProofIterator(T[] array) {
this.array = array;
}
#Override
public boolean hasNext() {
return this.index < this.array.length;
}
#Override
public T next() {
return this.array[this.index];
}
#Override
public void remove() {
throw new RuntimeException("Remove not allowed in this iterator");
}
}
}
Then in source code, only thing you have to do is:
for(String str : new NullProofIterable<String>(strArray)) {
//Perform action on not null string
}
The second option is very fancy usage of != null condition bu it might be helful when a method need to return some data.

Categories

Resources