AP® Computer Science A review sheet from Aim for Five (aimforfive.com/csa/units/2/2-10)
Unit 2 · Topic 2.10
2.10 Implementing String Algorithms
String algorithms walk through a string one index at a time and look at its pieces with substring. This topic covers the standard ones: checking for a property, counting matching substrings and building a reversed string, plus the index limits that keep you from running off the end.
Key terms
- string traversal
substring- counting substrings
- reversing a string
Traversing a string
To traverse a string means to visit its characters in order with a loop. The indexes run from 0 to length() - 1, so the standard loop is for (int i = 0; i < str.length(); i++).
The Java Quick Reference has no method that returns a single character, so take a one-letter substring: str.substring(i, i + 1). Compare it with equals, never ==.
Trace your loop on a short word first, writing each index under its letter. A handy trick for "is this letter one of these?" is indexOf: "aeiou".indexOf(letter) >= 0 is true exactly when letter is a lowercase vowel, because indexOf returns -1 when there's no match.
Looking at longer pieces
To look at every piece of length 2, use substring(i, i + 2). The last valid starting index is now length() - 2, because the piece ends at index i + 1. In general, for pieces of length k, the loop condition is i <= str.length() - k.
Get this wrong and the loop asks for characters that don't exist:
String s = "aaab";
for (int i = 0; i < s.length(); i++)
{
System.out.println(s.substring(i, i + 2));
}
For "aaab", this prints aa, aa, ab, and then, when i is 3, substring(3, 5) throws a StringIndexOutOfBoundsException.
Comparing neighbors works the same way. To compare each letter with the one after it, stop at length() - 1 so i + 1 is still valid.
Reversing a string
Strings are immutable, so you build a new one. Either loop backward and add each letter to the end of the result, or loop forward and add each letter to the front:
String word = "stop";
String result = "";
for (int i = 0; i < word.length(); i++)
{
result = word.substring(i, i + 1) + result;
}
System.out.println(result);
Both approaches turn "stop" into "pots". The same idea builds any new string: start with the empty string "" and add pieces in a loop, such as only the letters that aren't spaces.
Returning early
When a method only needs to know whether at least one piece has a property, it can return true the moment it finds one and return false after the loop. Don't put return false in an else inside the loop. That would quit after checking only the first piece.
Worked examples
Try each one yourself first, then open the solution.
- Example 1
Write a method: counting vowels
Write a method
countVowels(String word)that returns the number of lowercase vowels (a, e, i, o, u) inword. One solution:public static int countVowels(String word) { int count = 0; for (int i = 0; i < word.length(); i++) { String letter = word.substring(i, i + 1); if ("aeiou".indexOf(letter) >= 0) { count++; } } return count; }Show the solutionHide the solution
- Step 1: This is the counting pattern from 2.9 applied to a string traversal.
- Step 2: Loop over every index from 0 to
word.length() - 1and take one letter withsubstring(i, i + 1). - Step 3:
"aeiou".indexOf(letter)is 0 to 4 for a vowel and -1 for anything else, so>= 0means "is a vowel". - Step 4: Check:
"banana"has a, a, a, so 3."rhythm"has no vowels, so 0. The empty string""has length 0, so the loop runs zero times and the method returns 0.
Answer: The method above; it returns 3 for
"banana", 0 for"rhythm"and 0 for"". - Example 2
Counting overlapping pieces
What does this code print?
String s = "aaab"; int count = 0; for (int i = 0; i <= s.length() - 2; i++) { if (s.substring(i, i + 2).equals("aa")) { count++; } } System.out.println(count);Show the solutionHide the solution
- Step 1:
s.length()is 4, soiruns from 0 to 2 (i <= 2). - Step 2:
i= 0:substring(0, 2)is"aa", a match.countis 1. - Step 3:
i= 1:substring(1, 3)is"aa", another match, overlapping the first.countis 2. - Step 4:
i= 2:substring(2, 4)is"ab", no match.
Answer: It prints
2. - Step 1:
- Example 3
Write a method: double letters
Write a method
hasDoubleLetter(String str)that returnstrueifstrhas two identical letters next to each other, such as the "ll" in "balloon". One solution:public static boolean hasDoubleLetter(String str) { for (int i = 0; i < str.length() - 1; i++) { if (str.substring(i, i + 1).equals(str.substring(i + 1, i + 2))) { return true; } } return false; }Show the solutionHide the solution
- Step 1: Each letter is compared with the next one, so
istops atstr.length() - 2. The conditioni < str.length() - 1does that, andi + 2never goes past the end. - Step 2: As soon as a pair matches, the answer is known, so
return trueright away. - Step 3: Only after every pair has been checked do you know the answer is
false, so thatreturngoes after the loop. - Step 4: Check:
"balloon"matches at "ll", sotrue."apex"has no pair, sofalse. For"a", the loop condition is0 < 0, so it runs zero times and returnsfalse.
Answer: The method above; it returns
truefor"balloon"andfalsefor"apex"and"a". - Step 1: Each letter is compared with the next one, so
Common mistakes
- Looping to
i < str.length()while usingsubstring(i, i + 2). The last start index for a two-letter piece islength() - 2. - Comparing one-letter strings with
==. Useequals. - Writing
return falseinside the loop in anelse, which stops after the first check. - Forgetting to store the result when building a string.
result + letter;alone does nothing; writeresult += letter;.
On the exam
- Part B of free-response Question 1 needs
Stringmethods. Expect to traverse a string withsubstringandindexOf, and be careful with the loop bounds. - Try your loop on a tiny string, like length 1 or the empty string, to check you won't go out of bounds.
Connected topics
Videos
Check yourself
4 questions on 2.10 Implementing String Algorithms. Pick an answer to see if you got it, and why.
The following method is intended to return a string with the characters of s in reverse order. For example, reverseIt("stop") should return "pots".public static String reverseIt(String s)
{
String r = "";
/* missing code */
return r;
}Which of the following can replace /* missing code */ so that the method works as intended?
Consider the following code segment.String word = "bananas";
int count = 0;
for (int i = 0; i <= word.length() - 3; i++)
{
if (word.substring(i, i + 3).equals("ana"))
{
count++;
}
}
System.out.println(count);What is printed as a result of executing the code segment?
Consider the following code segment.String s = "education";
int vowels = 0;
for (int i = 0; i < s.length(); i++)
{
String letter = s.substring(i, i + 1);
if ("aeiou".indexOf(letter) >= 0)
{
vowels++;
}
}
System.out.println(vowels);What is printed as a result of executing the code segment?
Consider the following code segment.String s = "cat";
String t = "";
for (int i = 0; i <= s.length(); i++)
{
t += s.substring(i, i + 1);
}
System.out.println(t);What is printed as a result of executing the code segment?
0 of 4 answered