Implementing String Algorithms
Why this matters
Imagine you're building a feature for a new social media app. Your friend, Maya, suggests a tool that analyzes a user's posts to find their most-used words. Or think about the last time you used a search function—typing "Knicks" into a sports news site and instantly getting every article about the team. How does the computer do that? It doesn't just "know."
Someone had to write a precise set of instructions—an algorithm—to teach the computer how to scan through all that text, identify the word "Knicks," and count every time it appears. These aren't magic tricks; they're string algorithms. Today, we're going to pull back the curtain and learn how to write these powerful instructions ourselves. We'll start with the basics: finding things, counting things, and even reversing things.
Concept overview
flowchart TD
A[Start: countAn(str)] --> B{Initialize count = 0};
B --> C{Loop for i from 0 to str.length() - 2};
C --> D{Get substring from i to i + 2};
D --> E{Does substring equal "an"?};
E -- Yes --> F[Increment count];
F --> G;
E -- No --> G[Continue to next i];
G --> C;
C -- Loop Finished --> H[Return count];
H --> I[End];
Core explanation
Hello there! I'm Saavi, and I'm excited to dive into one of my favorite topics: string algorithms. It sounds complicated, but I promise it's just about giving the computer smart instructions for handling text.
Think of a String in Java as a train. Each car on the train holds exactly one character. The string "Boston" is a train with 6 cars: B, o, s, t, o, n. An algorithm is our plan for inspecting this train. Most of our plans will involve a for loop, which is like walking from the engine to the caboose, one car at a time.
The Basic Toolkit
To work with strings, we need a few key methods you've already seen:
str.length(): Tells you how many characters (cars) are in the string (train).str.charAt(i): Gets the character at a specific indexi.str.substring(i, j): Gets a new string that's a piece of the original, from indexiup to (but not including) indexj.+(Concatenation): Lets you join strings together to build a new one.
With just these tools and a for loop, you can accomplish almost anything.
Standard Algorithm 1: Finding if Substrings Have a Property
Let's say we want to know if a password contains at least one number. The "property" we're looking for is "is a digit." We can write an algorithm for this.
The plan:
- Go through the string, character by character.
- At each character, ask: "Is this a digit?"
- If you find one, you're done! The answer is
true. You can stop looking. - If you get to the end of the string and haven't found any digits, the answer is
false.
Here’s how that looks in code:
public boolean hasNumber(String str) {
// Loop through each character of the string
for (int i = 0; i < str.length(); i++) {
// Get the character at the current index
char current = str.charAt(i);
// Check if it has the property (is a digit)
if (Character.isDigit(current)) {
return true; // Found one! We can stop and return immediately.
}
}
// If the loop finishes without finding a digit, we know there are none.
return false;
}
This pattern—looping through, checking a condition, and returning true early—is incredibly common and efficient.
Standard Algorithm 2: Counting Substrings with Criteria
Now, let's level up. Instead of just finding if something exists, let's count how many times it appears. Let's try to count how many times the substring "an" appears in the word "banana".
Our eyes can see it: banana -> an is at index 1. banana -> an is at index 3. The answer is 2. How do we teach a computer to do this?
The plan:
- Create a
countervariable, initialized to0. - Loop through the string, but not all the way to the end. We need to grab two characters at a time (
"an"is length 2), so we must stop early enough to not go out of bounds. - In each iteration, grab a substring of length 2.
- Check if that substring
.equals("an"). - If it does, increment your
counter. - After the loop finishes, return the
counter.
public int countAn(String str) {
int count = 0;
// The loop must stop so that the substring call is valid.
// str.substring(i, i + 2) needs i + 2 to be <= str.length().
// So, i must be < str.length() - 1.
for (int i = 0; i < str.length() - 1; i++) {
String twoChars = str.substring(i, i + 2);
if (twoChars.equals("an")) {
count++;
}
}
return count;
}
Standard Algorithm 3: Creating a Reversed String
This is a classic problem you'll definitely see. How do you take a string like "Priya" and turn it into "ayirP"?
You can't change the original string (remember, strings are immutable!). You have to build a new one.
The plan:
- Create an empty string to hold our result, like
String reversed = "";. - Loop through the original string, but start at the end and go backwards.
- In each step of the loop, grab the character at the current index.
- Add that character to the end of your
reversedstring. - After the loop is done,
reversedwill hold the complete, reversed string.
public String reverseString(String str) {
String result = "";
// Start at the last character's index: length() - 1
// Keep going as long as i is 0 or more
// Decrement i each time
for (int i = str.length() - 1; i >= 0; i--) {
char c = str.charAt(i);
result = result + c; // Or result += c;
}
return result;
}
Look closely at that for loop. It’s a bit different. We start i at the last valid index (str.length() - 1), we continue as long as i is greater than or equal to 0, and we decrement i with i--. This backward loop is a fundamental technique you should get comfortable with.
These three patterns form the foundation for almost any string problem you'll face on the AP exam. Master them, and you'll be in great shape.
See it in action
Worked examples
Let's walk through a few problems together. The key is not just to get the right answer, but to understand the process.
Count the Vowels
Problem: Write a method countVowels that takes a String and returns the number of vowels ('a', 'e', 'i', 'o', 'u') it contains. The check should be case-insensitive.
Solution Walkthrough:
- 1The GoalWe need to visit every character and check if it's a vowel. This sounds like a job for a
forloop and a counter. - 2SetupWe'll define the method and initialize a counter variable to zero. We also need to handle both uppercase and lowercase vowels. A good trick is to convert the whole string to lowercase first.
public int countVowels(String str) { int vowelCount = 0; String lowerStr = str.toLowerCase(); // Handle case-insensitivity upfront! - 3The LoopWe'll iterate from the first character (index 0) to the last (
length() - 1).for (int i = 0; i < lowerStr.length(); i++) { // ... what goes in here? } - 4The CheckInside the loop, we get the character at index
i. Then we check if it's one of the five vowels.char c = lowerStr.charAt(i); if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') { vowelCount++; // If it is, increment our counter. }
-
The Return: After the loop finishes,
vowelCountholds our total. We just return it.return vowelCount; } // end of method
Final Code:
public int countVowels(String str) {
int vowelCount = 0;
String lowerStr = str.toLowerCase();
for (int i = 0; i < lowerStr.length(); i++) {
char c = lowerStr.charAt(i);
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
vowelCount++;
}
}
return vowelCount;
}
Remove a Specific Character
Problem: Write a method removeChar that takes a String str and a char ch and returns a new string with all occurrences of ch removed.
Solution Walkthrough:
- 1The GoalWe need to build a new string that contains only the "good" characters from the original. This means we'll loop through the original and only append characters to our new string if they don't match
ch. - 2SetupWe need an empty string to build our result.
public String removeChar(String str, char ch) { String result = ""; - 3The Loop and LogicWe loop through the input string
str. Inside the loop, we grab each character and compare it toch. If it's not the character to be removed, we append it to ourresult.for (int i = 0; i < str.length(); i++) { char current = str.charAt(i); if (current != ch) { result += current; // Append the character if it's not the one to remove } } - 4The ReturnOnce the loop is done,
resulthas our answer.return result; }
Final Code:
public String removeChar(String str, char ch) {
String result = "";
for (int i = 0; i < str.length(); i++) {
char current = str.charAt(i);
if (current != ch) {
result += current;
}
}
return result;
}
Calling removeChar("Atlanta", 'a') would return "Atlnt".
Try it yourself
Ready to try a couple on your own? Think through the plan first, then write the code.
Problem 1: Palindrome Checker
A palindrome is a word that reads the same forwards and backwards, like "racecar" or "level". Write a method isPalindrome(String str) that returns true if the given string is a palindrome and false otherwise. The check should be case-insensitive.
- Hint 1How can you use one of the algorithms we already discussed today to help you?
- Hint 2Once you have a reversed version of the string, what method should you use to compare it to the original? Don't forget to handle uppercase and lowercase letters!
Problem 2: Every Other Letter
Write a method everyOther(String str) that returns a new string made of every other letter starting with the first. For example, calling everyOther("Chicago") should return "Chcao".
- Hint 1You'll need a
forloop, but how should you change the increment step (i++) to skip characters? - Hint 2You'll be building a new string, so start with an empty
String result = "";.
Practice — 8 questions
In simple terms, string algorithms are like recipes for your computer. They give step-by-step instructions for searching, counting, or changing parts of text, like finding a word in a sentence or reversing a name.
public boolean hasNumber(String str) {
// Loop through each character of the string
for (int i = 0; i < str.length(); i++) {
// Get the character at the current index
char current = str.charAt(i);
// Check if it has the property (is a digit)
if (Character.isDigit(current)) {
return true; // Found one! We can stop and return immediately.
}
}
// If the loop finishes without finding a digit, we know there are none.
return false;
}
- 2.10.A: Develop code for standard and original algorithms that involve strings and determine the result of these algorithms.
- 2.10.A.1
- There are standard string algorithms to: • find if one or more substrings have a particular property • determine the number of substrings that meet specific criteria • create a new string with the characters reversed
flowchart TD
A[Start: countAn(str)] --> B{Initialize count = 0};
B --> C{Loop for i from 0 to str.length() - 2};
C --> D{Get substring from i to i + 2};
D --> E{Does substring equal "an"?};
E -- Yes --> F[Increment count];
F --> G;
E -- No --> G[Continue to next i];
G --> C;
C -- Loop Finished --> H[Return count];
H --> I[End];
Read what Saavi narrates
Hello there! I'm Saavi, and welcome to Shrutam.
Ever wonder how your phone's search function can instantly find a contact, or how a word game knows if you've spelled a word correctly? It's not magic... it's algorithms! Specifically, string algorithms. And today, we're going to learn how to write them.
A string algorithm is just a clear, step-by-step process for working with text. We'll use loops to visit each character of a string, check it against some rules, and then build a result based on what we find.
Let's try a simple, practical example. Imagine we need to write a method that counts the vowels in a word. Let's say our word is "Hello World".
First, we need a plan. Our plan is to visit every single character and check if it's a vowel. To do this, we'll need a counter, let's call it vowelCount, and we'll start it at zero.
To handle both 'A' and 'a', a great first step is to convert the whole string to lowercase. So "Hello World" becomes "hello world".
Now, we'll use a for loop to walk through the string, one character at a time. For the first character, 'h', we ask... is it a vowel? No. Move on. Next, 'e'. Is it a vowel? Yes! So we increment our vowelCount to one. Next, 'l'. No. Next, 'l'. No. Next, 'o'. Yes! Increment vowelCount to two. We keep doing this all the way to the end. For "hello world", we'd find the 'o' in "world" too, making our final count three.
After the loop has checked every character, the method returns the final count. That's it! You've just designed a string algorithm.
Now, a common mistake here is forgetting to initialize your counter. If you don't say `vowelCount` starts at zero, Java gets confused. It doesn't know where to start counting from. So always remember to initialize your "collector" variables, whether it's a number for counting or an empty string for building.
These patterns... looping through a string, checking a property, and collecting a result... are the building blocks for so much of programming. You're learning a truly powerful skill. Keep practicing, and you'll be building amazing things in no time.
The last valid index of a string is `length() - 1`. When `i` becomes `str.length()`, calling `str.charAt(i)` or `str.substring(i, ...)` will cause an `IndexOutOfBoundsException`.
Always use `i < str.length()` for a standard forward loop that accesses one character at a time.
`str.substring(0, 3)` gives you characters at indices 0, 1, and 2. It does *not* include the character at index 3. This leads to incorrect substring logic and off-by-one errors.
Remember that the length of the resulting substring is `end - start`. To get a substring of length 1 at index `i`, you use `substring(i, i + 1)`.
In Java, `String` objects are immutable. You cannot change them once they are created. This line of code won't even compile.
To create a modified version of a string, you must build a *new* string and add characters to it, as shown in the `reverseString` and `removeChar` examples.
Using `i = str.length()` as the start, or `i > 0` as the condition. The first causes an immediate crash. The second misses the character at index 0.
A correct backward loop is `for (int i = str.length() - 1; i >= 0; i--)`. Memorize this pattern.
`==` checks if two variables refer to the exact same object in memory. `.equals()` checks if the two strings have the same sequence of characters. In loops, `substring` often creates new objects, so `==` will fail even when the content is identical.
Always use `mySubstring.equals("some text")` to compare string content.