Limit characters by line without splitting word
String s = &quot;Even aside from the rain and wind it hadn't been a happy practice session. Fred and George, who had been spying on the Slytherin team, had seen for themselves the speed of those new Nimbus Two Thousand and Ones. They reported that the Slytherin team was no more than seven greenish blurs, shooting through the air like missiles.&quot;;

s is not a good variable name. My rule is that you're only allowed to use single-character variable names when dealing with dimensions (yes, that also disallows i/j/k for loops, too).

public static void wordWrapper(String s, int limit) {

The naming is off, this is not a &quot;word wrapper&quot; it's a function that does wrap a string by words, so more like wrap or wrapText.

        // Time complexity: O(n) - n size of s
        // Space complexity: O(n) - n number of words in s

I'm not sure that is correct. I could be very well mistaken here because I rarely need to think about complexity limitations at all, but I think it is closer to &quot;O(n + m)&quot;, with &quot;n&quot; being the number of characters (the split), and &quot;m&quot; being the number of words (your loop). Space should be &quot;O(n*2)&quot;, with &quot;n&quot; being the number of characters in the string, as you need to keep each character twice in memory, once in the original, and once in the word string.
However, most JVMs are implementing &quot;substrings&quot;, which means that the array of codepoints is only held one in memory, and if you do a substring, you will receive a new String with the same array but different start/end index.

        int charCount = 0;
        int i = 0;
        String[] words = s.split(&quot; &quot;);
        while (i &lt; words.length) {
            if (charCount + words[i].length() &gt; limit) {
                System.out.println();
                charCount = 0;
            }
            charCount += words[i].length();
            System.out.print(words[i] + &quot; &quot;);
            i++;
        }

This code could be simplified to a for-each loop:
int currentLineLength = 0;

for (String word : text.split(&quot; &quot;)) {
    if ((currentLineLength + word.length()) &gt; maxCharactersPerLine) {
        System.out.println();
        currentLineLength = 0;
    }
    
    System.out.print(word + &quot; &quot;);
    currentLineLength = currentLineLength + word.length();
}

Note that your implementation, and this revised one, has three problems which should be dealt with at some point:

The spaces are not taken into account for the maximum line length.
It prints an extra space at the end of each line.
How a word should be treated that is longer than the maximum line length.



...and just use pointers instead of split(),...

There is no such thing as &quot;a pointer for strings&quot; in Java. Though, you most likely mean, to iterate over the String and keep track of the index, but &quot;pointer&quot; is a heavily prejudiced word, and I would stay clear of it and instead use &quot;index&quot;.

int lastWhitespaceIdx = -1;

Don't shorten names just because you can, it does make the code harder to read in the end of the day.

int lineCount = 0;

The name of this variable is incorrect, it does not count lines, it counts characters on the current line, it should be named accordingly.

while (i &lt; s.length()) {

Not sure why you use a while when a for would be perfect for what you're doing here.

System.out.print(s.charAt(i));

Printing single characters at a time can be quite wasteful, depends on whether the stream supports some sort of buffer or not.

You could use String.indexOf(String) and String.index(String, int) to iterate over the string and simplify your logic. Then use substring to extract the part of the String between the spaces and print that, or print that part character by character.