Opening the reading…
Opening the reading…
DSA FUNDAMENTALS › STRING BASICS
Take the string "cabbd". Instead of searching the string again for each possible character, create a frequency table and increase one entry during a single traversal. The first character, 'c', raises the count for 'c' to 1. Then 'a' raises 'a' to 1, each 'b' raises 'b' again, and 'd' raises 'd' to 1.
string s = "cabbd";
int freq[128] = {0};
for (char ch : s) {
freq[(unsigned char) ch]++;
}| CHARACTER | ASCII VALUE | COUNT |
|---|---|---|
| 'a' | 97 | 1 |
| 'b' | 98 | 2 |
| 'c' | 99 | 1 |
| 'd' | 100 | 1 |
The completed table now records every occurrence: 'a', 'c', and 'd' each occur once, while 'b' occurs twice. You can select the maximum and minimum by scanning these counts. No character needs to be counted again, because the table already contains all the evidence.
After traversing "cabbd", which counts belong to 'a', 'b', 'c', and 'd' in that order?
Checkpoints are not graded. They are here so you catch yourself before the quiz does — stuck, ask the tutor on the right.
A fixed frequency table contains entries for characters that never appeared. For example, 'e' has count 0 after reading "cabbd". That zero says 'e' is absent, not that 'e' is the least frequent character occurring in the string. The minimum must be chosen only from entries whose count is greater than 0.
Among the occurring characters, the valid minimum count is 1. The characters 'a', 'c', and 'd' all have that count. The zero at 'e' cannot compete, because the task asks for a character that occurs in the string. Excluding zero counts leaves 'a', 'c', and 'd' as the minimum-frequency candidates.
Scan ASCII values from smallest to largest. For "cabbd", that means 'a' is considered before 'b', then 'c', then 'd'. Update the maximum only when the new count is strictly larger. Update the minimum only when the count is positive and strictly smaller. A tie does not update either answer, so the first character in ASCII order keeps the result.
int maxCount = 0;
int minCount = s.length() + 1;
char maxChar = 0;
char minChar = 0;
for (int code = 0; code < 128; code++) {
if (freq[code] > maxCount) {
maxCount = freq[code];
maxChar = (char) code;
}
if (freq[code] > 0 && freq[code] < minCount) {
minCount = freq[code];
minChar = (char) code;
}
}When the scan reaches 'a', its positive count of 1 becomes the minimum. The count for 'b' is 2, so it becomes the maximum. The count for 'c' is 1, but it is not smaller than the current minimum, and 'd' behaves the same way. The final answers are 'b' with count 2 and 'a' with count 1.
Repair the condition so the minimum accepts only occurring characters and keeps the earlier ASCII character when counts tie.
if (freq[code] < minCount) {
minCount = freq[code];
minChar = (char) code;
}Checkpoints are not graded. They are here so you catch yourself before the quiz does — stuck, ask the tutor on the right.
The first traversal reads the 5 characters in "cabbd" and builds the table. The second traversal checks the 128 possible ASCII entries to select the answers. The total time is O(n + 128), where n is the string length, and the table uses O(128) space. Since 128 is fixed for ASCII input, this is commonly described as O(n) time and O(1) extra space.
This method assumes every input character belongs to the ASCII range from 0 through 127. In C++, use an array with 128 entries and use the character's ASCII value as its index. In Java, the same idea fits an int array of length 128. The indexing language changes, but the two traversals and the tie rule stay the same.
| STEP | WORK | COST |
|---|---|---|
| Build counts | Read each character in "cabbd" once | O(n) |
| Choose answers | Scan 128 ASCII entries | O(128) |
| Stored data | One count for each ASCII value | O(128) |