2

This one is making my head spin. Just when I think I got it, I realize something's not right. I have to use recursion for this assignment. Any hints?

/**
 * Uses recursion to find index of the shortest string.
 * Null strings are treated as infinitely long.
 * Implementation notes:
 * The base case if lo == hi.
 * Use safeStringLength(paths[xxx]) to determine the string length.
 * Invoke recursion to test the remaining paths (lo +1)
 */
static int findShortestString(String[] paths, int lo, int hi) {
    int min=lo;
    if (lo==hi)
        return min;
    if (safeStringLength(paths[lo]) < safeStringLength(paths[lo+1])){
        min=lo;
        return Math.min(min, findShortestString(paths, lo+1, hi));
    }
    else{
        min=lo+1;
        return Math.min(min, findShortestString(paths, lo+1, hi));
    }
}
5
  • 1
    Is this code your doing? Or is it the base that you have to use? Commented Nov 12, 2010 at 2:50
  • I think the approach needs to change completely; passing only hi and lo continuously does not give me any room on the way back up to give a result. Commented Nov 12, 2010 at 2:52
  • Ya thats why Im saying Im stuck..I dunno what to do Commented Nov 12, 2010 at 2:54
  • I edited it with some progress, but its still off Commented Nov 12, 2010 at 3:05
  • Test now my function, it handles all the tasks mentioned in your comment if I got rid of all the typos. Commented Nov 12, 2010 at 3:46

7 Answers 7

4

I think got something here:

static int findShortestString(String[] paths, int lo, int hi) 
{
    if (lo==hi)
        return lo;

    int ShortestIndexSoFar = findShortestString(paths, lo+1, hi);
    if(safeStringLength(paths[ShortestIndexSoFar]) < safeStringLength(paths[lo]))
        return ShortestIndexSoFar;
    else
        return lo;
}  

static int safeStringLength(String str)
{
    if(str == null)
        return Integer.MAX_VALUE;
    return str.length();
}

Explaining why this works:
Here's a sample:

[0] ab
[1] abcd
[2] a
[3] abc
[4] ab

Obviously, index 2 is the shortest one.
Think bottoms up. Read the following starting from the bottom, upwards.
I make it sound like each function is talking to the function above it in the chain.
And each line is lead by the function parameters that were passed.

"[0] ab   (paths, 0, 4): return 2, coz he's shorter than me or anyone before us"
"[1] abcd (paths, 1, 4): return 2, coz he's shorter than me or anyone before us"
"[2] a    (paths, 2, 4): return 2, I'm shorter than anyone before me"
"[3] abc  (paths, 3, 4): return 4, coz he's shorter than me or anyone before us"
"[4] ab   (paths, 4, 4): return 4, I'm the shortest; I don't know any better"

So in the code, you see that exactly happening.
When we define ShortestIndexSoFar, this is where each function will know the shortest of all the paths beyond it.
And right after it is where the function itself checks if its index has a shorter path than the shortest of all the ones below.
Keep trickling the shortest one upward, and the final guy will return the shortest index.

That makes sense?

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

15 Comments

Yes this works..please explain how this works Im not understanding it
A question: What if paths[lo] == null? safeStringLength(paths[lo]) will throw a NullPointerException, right?
@fprime; I added the explanation.
@Lajos and @fprime; the answer I gave is the minimum solution in a perfect world. I leave the rest of the solution to you =) which is the bad possibilities of: not having any data, or passing opposite indices.
this will blow up the stack, given enough input strings.
|
1

Since this is homework, here's a hint to help you learn:

The signature of the findShortestString method suggests that you should be using a binary search. Why would I say that? Why would it be a good idea to do that? All of the other solutions suffer from a practical problem in Java ... what would that be?

To people other than the OP ... PLEASE DON'T GIVE THE ANSWERS AWAY ... e.g. by correcting your answers!

2 Comments

we're not here to discipline people =) They ask questions, we answer; they should discipline themselves if they want. Another possibility is may be the OP failed at turning this on time already but is still interested to know how to solve it. If he just wanted a hint, he wouldn't have come to SO.
@Beemer - if he wanted something more than hints, he shouldn't have come to SO. We SHOULD NOT be doing peoples' homework for them ... no matter what their motivation is in asking for help. However, it is good to see that you didn't give away the answers anyway :-)
0

Why not just get the length of each element and sort the returned length to get the ordering? Like this.

int[] intArray = {10, 17, 8, 99, 1}; // length of each element of string array
Arrays.sort(intArray);

2 Comments

Its not an int array, ints a string array
You have to get first the length of each element in the array. Then stored it in an int array then sort.
0

one solution will be like this

public static final int findShortestString(final String[] arr, final int index, final int minIndex) {

    if(index >= arr.length - 1 ) {
        return minIndex;
    }

    if(-1 == safeStringLength(arr[index])) { 
        return index;
    }


    int currentMinIncex = minIndex;

    if(safeStringLength(arr[minIndex]) > safeStringLength(arr[index+1])){
        currentMinIncex = index + 1;
    }


    return findShortestString(arr, index + 1, currentMinIncex);

}



public static final int safeStringLength(final String string) {

    if( null == string) return -1;

    return string.length();

}

Comments

0

A simple solution:

/**
     * Uses recursion to find index of the shortest string.
     * Null strings are treated as infinitely long.
     * Implementation notes:
     * The base case if lo == hi.
     * Use safeStringLength(paths[xxx]) to determine the string length.
     * Invoke recursion to test the remaining paths (lo +1)
     */
static int findShortestString(String[] paths, int lo, int hi) {
    if (lo==hi)
        return lo;
    if (paths[lo] == null)
       return findShortestString(paths, lo+1, hi);
    int bestIndex = findShortestString(paths, lo+1, hi);
       if (safeStringLength[lo] < safeStringLength[bestIndex])
           return lo;
    return bestIndex;
}

Comments

0

Calculating min on the result of running findShortestString isn't meaningful. The best way to start this kind of problem is to consider just a single recursive step, you can do this by considering what happens with an array of only two strings to compare.

What you want to do is check the length of the first string against the length of the second. The real trick, though, is that you want to test the length of the second by calling the function recursively. This is straight forward enough, but requires determining the end-case of your recursion. You did this successfully, it's when lo == hi. That is, when lo == hi the shortest known string is lo (it's the only known string!).

Ok, so back to comparing just two strings. Given that you know that you want to compare the length of two strings stored in paths, you might do something like this (without recursion):

if(safeStringLength(paths[0]) < safeStringLength(paths[1])){
    return 0; // paths[0] is shorter
}else{
    return 1; // paths[1] is shorter
}

But you want to recurse -- and in the recurse step you need to somehow generate that 1 of paths[1]. We already figured out how to do that, when lo == hi, we return lo. Thus the recursion step is "compare the current lowest known string length to the string length of the best known index" -- wait, we have a function for that! it's findShortestString. Thus we can modify what's written above to be slightly more concise, and add in the base case to get:

static int findShortestString(String[] paths, int lo, int hi) {
    // base case, no comparisons, the only known string is the shortest one
    if(lo == hi){
        return lo;
    }

    int bestIndex = findShortestString(paths, lo+1, hi);
    return safeStringLength(paths[lo]) < safeStringLength(paths[bestIndex]) ? 
        lo : bestIndex;
}

Comments

0
static int findShortestString(String[] paths, int lo, int hi)
{  
  if (lo==hi)  
    return lo;  
  int ShortestIndexDown = findShortestString(paths, lo, (hi + lo)/2);
  int ShortestIndexUp = findShortestString(paths, (lo+hi)/2+1, hi);
  return SafeStringLength(paths[ShortestIndexDown]) < SafeStringLength(paths[ShortestIndexUp])?ShortestIndexDown:ShortestIndexUp;
}

static int safeStringLength(String str)
{
  if(str == null)
    return Integer.MAX_VALUE;
  return str.length();
}

4 Comments

Why the +(lo+hi)%2? You can just do +1
@Axn - think about it ... :-)
@Stephen - I thought about it. I still don't get it :(
"+(lo+hi)%2" had no effect, changed to "+1", although it is just an optimization. The important point here is that the maximum stack depth will be Log(N), so a stack overflow is much less probable.

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.