0

I need to write a method to return the index array of a character in a string in Java. Is the following good (correctness, efficiency, as short code as possible) enough?

int[] charIndexArray(String s, char c) {
    int start = 0;
    List<Integer> list = new ArrayList<Integer>();
    while ((start = s.indexOf(c, start)) != -1) {
        list.add(start);
        start++;
    }
    int arr[] = new int[list.size()];
    for (int i = 0; i < ret.length; i++)
        arr[i] = list.get(i);
    return arr;
}
2

3 Answers 3

1

You can replace the code at the end that copies it to an array with a call to the toArray() method. Other than that, looks pretty good.

Sign up to request clarification or add additional context in comments.

6 Comments

Could I get a reason for the -1?
That's a pretty crappy reason for a -1. Down votes are for inaccurate information, not to show disagreement.
Here's an objection: the toArray() method would return an Object[], and even toArray(T[]) will return an object array of some kind, which has additional overhead compared to an int[].
@LouisWasserman - good point. I'm not a huge Java coder. I forget that you have to box and unbox so much in Java (granted, C# does it, just automatically, without the coder having to worry about it).
if so, why you still haven't removed your answer. :)
|
1

Instead of:

while ((start = s.indexOf(c, start)) != -1) {
    list.add(start);
    start++;
}

consider:

for (int i = 0; i < s.length(); i++) {
    if (s.charAt(i) == c) {
      list.add(i);
    }
 }

because the indexOf causes the creation of a whole other loop to search for the next instance of your character.

You code is quietly doing:

while (start != -1) {
    start = -1;
    for ( int i=start;i<s.length();i++){
      if ( charAt(i) == c ) {
        start = i;
        break;
      }
    }
    if ( start != -1 ) { 
    list.add(start);
    start++;
  }
}

Which does not seem more efficient. But it turns out that after spending way too much time on this:

static int[] charIndexArrayByBits(String s, char c) {
    int start = 0;
    int[] list = new int[s.length()];
    int count = -1;
    while ((start = s.indexOf(c, start)) != -1) {
      list[++count] = start;
      start++;
    }
    return Arrays.copyOf(list, count);
  }

is faster. But I would not consider it more efficient in the general case because you are allocating an int array which would be larger space wise.

3 Comments

but the overall iteration length is the same, i believe, in both cases, of course, if one can safely assume Java String is random-accessible sequence container.
Do not forget about the boxing invoved.
right, my original solution still loop over the string once! The only place where it can be made "more" (no matter how small) efficiently is to remove the boxing/unboxing part, correct?
0

The code do not look good.

You use two loop instead of one.

Try to use methods.

charAt(int pos) for string and Arrays.copy

The OP shold not read more ;p

The first is the location this kind of method should be placed in some util class and be static IMHO.

public class CharSequenceUtil {

    private static int[] EMPTY_INT_ARRAY = new int[0];

    /**
    * Method search the position of given character in char sequence.
    *
    * @param CharSequence seq - Sequence of char that will be investigate 
    * @param char c - Character that is analysed.
    *
    * @return int array with positions of char c in CharSequence instanace
    * @throws NullPointerException if seq is null.
    */
    public static int[] charIndexArray(CharSequence seq, char c) {

      if(seq == null) {
        throw new NullPointerExcetion("The seq must not be null");
      }

      if(seq.length() == 0) {
        return EMPTY_INT_ARRAY;
      }

      int[] positions = new int[seq.lenth()];
      int stor = -1; 

      for(int pos = 0; pos < seq.length(); seq++) {
         if(c == seq.charAt(pos)) {
          positions[++stor] = pos;
         }
      }

      if(stor == -1) {
        return EMPTY_INT_ARRAY;
      }

      return Arrays.copyOf(positions, stor);
    }
}

4 Comments

how so about two loops? i only see one iteration over the string.
@QiangLi, in the indexOf you have another loop and additioanl you call a method that is not really designed for this usage. It should be used when you are insterted in position and you do not want to write the whole code.
I think that this is the more faster way. I don't know if System.arrayCopy is more faster because is native method.
The copyOf, call System.arrayCopy, so that is the gain.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.