Search code examples
javalexicographic

Lexicographical order - two char array as parameters, looking for a better solution


I have to write a function that takes 2 char[]s and returns:

  • -1 if the the first word comes before the second in a lexicographical order
  • 0 if they are the same word
  • 1 if it comes after

I'm aware of compareTo() method but this is an assignment, I need to avoid using it. So far, my code is working well, I've done a few tests with different words.

I was wondering if there was another way of doing it, my code doesn't feel optimized, it's long and repetitive:

public static int lexico(char[] word1, char[] word2) {
        int length1 = word1.length;
        int length2 = word2.length;

        if (length1 == length2) {
            for (int i = 0; i < length1; i++) {
                if (word1[i] < word2[i]) {
                    return -1;
                } else if (word1[i] > word2[i]) {
                    return 1;
                } else if (i == length1 - 1) {
                    return 0;
                }
            }
        }

        if (length1 < length2) {
            for (int i = 0; i < length1; i++) {
                if (word1[i] < word2[i]) {
                    return -1;
                } else if (word1[i] > word2[i]) {
                    return 1;
                } else if (i == length1 - 1) {
                    // If I'm here then it means that all of the characters
                    // from 0 to length1-1 are equals
                    // but since length of the first string is shorter than the second,
                    // the first string will be put before the second
                    return -1;
                }

            }
        }

        if (length1 > length2) {
            for (int i = 0; i < length2; i++) {
                if (word1[i] < word2[i]) {
                    return -1;
                } else if (word1[i] > word2[i]) {
                    return 1;
                } else if (i == length1 - 1) {
                    return 1;
                }
            }
        }

        return -999;
    }

public static void main(String[] args) {
    char[] share = { 's', 'h', 'a', 'r', 'e' };
    char[] ship = { 's', 'h', 'i', 'p' };

    System.out.println(lexico(share, ship)); // -1 share is before ship
    System.out.println(lexico(ship, share)); // 1 ship is after share
    System.out.println(lexico(ship, ship)); // 0 same word

}

Solution

  • A couple of notes for you:

    • You only need one loop: From the beginning to the lower of the two lengths. If the arrays are the same up until the lower of the two lengths and their lengths are different, your assignment should tell you what to return (normally it would be -1 if the left array was shorter than the right, 1 otherwise).

    • a < b isn't a valid alphabetic comparison of two characters (what most programmers mean when they say "lexicographic", the "lexico" meaning "pertaining to words"), it's a numeric comparison. Now, String's compareTo claims to use "lexicographic ordering," but it really just uses numeric ordering, so that may be good enough for what you're doing. If you want alphabetic ordering, I can't think of a JDK comparison method that accepts two single chars to compare rather than strings. There may be one I don't know of, or you may have to create one-character strings to do the comparison (with a Collator), which will (for instance) correctly identify that the à in "voilà" should be before any of the other letters in it.