Find the nth term in Look-and-say (Or Count and Say) Sequence. The look-and-say sequence is the sequence of the below integers: 1, 11, 21, 1211, 111221, 312211, 13112221, 1113213211, ...
How is the above sequence generated?
The nth term is generated by reading (n-1)th term.
- The first term is "1"
- Second term is "11", generated by reading first term as "One 1" (There is one 1 in previous term)
- Third term is "21", generated by reading second term as "Two 1"
- Fourth term is "1211", generated by reading third term as "One 2 One 1" and so on
Examples:
Input: n = 3
Output: 21
Explanation: The 3rd term of the sequence is 21
- 1st term: 1
- 2nd term: one 1 -> 11
- 3rd term: two 1s -> 21
Input: n = 4
Output: 1211
Explanation: The 4th term of the sequence is 1211
- 1st term: 1
- 2nd term: one 1 -> 11
- 3rd term: two 1s -> 21
- 4th term: one 2 one 1 -> 1211
Input: n = 1
Output: 1
Explanation: The first term of the sequence is 1
Using Recursive - O(2^n) Time and O(n + 2^n) Space
Idea is to recursively call for n-1 to generate the previous term. Then we build the nth or current term using the (n-1)th or previous term
How to build current term using previous? To generate a term using the previous term, we scan the previous term. While scanning a term, we simply keep track of the count of all consecutive characters. For a sequence of the same characters, we append the count followed by the character to generate the next term.
Step by Step Algorithm:
- Call the function recursively to get the
(n-1)
th term : prev = countAndSay(n - 1)
- Initialize res
= ""
and count = 1.
- Loop through the
prev
string from index 1: - If
prev[i] == prev[i - 1]
, increment count.
Else: append count
and prev[i - 1]
to result and r
eset count = 1
- After the loop, append the count of last character followed by the last character. Note that in the loop, we process previous character, so the last character has to be processed separately.
C++
#include <bits/stdc++.h>
using namespace std;
// Helper function to generate the next term
// in the sequence from the previous one
string nextTerm(string& prev) {
string curr = "";
int count = 1;
for (int i = 1; i < prev.length(); i++) {
// Keep Counting while same
if (prev[i] == prev[i - 1]) {
count++;
// If a different character found, appemd
// the count of previous character along
// with the character itself
} else {
curr += to_string(count) + prev[i - 1];
count = 1;
}
}
// Append the last character's count and the
// last character
curr += to_string(count) + prev.back();
return curr;
}
// Recursive function to return the nth term
string countAndSay(int n) {
// Base case
if (n == 1)
return "1";
// Recursively get the previous term
string prev = countAndSay(n - 1);
// Get the n-th term using (n-1)th
return nextTerm(prev);
}
// Driver code
int main() {
int n = 5;
cout << countAndSay(n) << endl;
return 0;
}
Java
// Helper function to generate the next term
// in the sequence from the previous one
class GfG {
public static String nextTerm(String prev) {
StringBuilder curr = new StringBuilder();
int count = 1;
for (int i = 1; i < prev.length(); i++) {
// Keep Counting while same
if (prev.charAt(i) == prev.charAt(i - 1)) {
count++;
// If a different character found, append
// the count of previous character along
// with the character itself
} else {
curr.append(count).append(prev.charAt(i - 1));
count = 1;
}
}
// Append the last character's count and the
// last character
curr.append(count).append(prev.charAt(prev.length() - 1));
return curr.toString();
}
// Recursive function to return the nth term
public static String countAndSay(int n) {
// Base case
if (n == 1)
return "1";
// Recursively get the previous term
String prev = countAndSay(n - 1);
// Get the n-th term using (n-1)th
return nextTerm(prev);
}
// Driver code
public static void main(String[] args) {
int n = 5;
System.out.println(countAndSay(n));
}
}
Python
# Helper function to generate the next term
# in the sequence from the previous one
def nextTerm(prev):
curr = ""
count = 1
for i in range(1, len(prev)):
# Keep Counting while same
if prev[i] == prev[i - 1]:
count += 1
# If a different character found, append
# the count of previous character along
# with the character itself
else:
curr += str(count) + prev[i - 1]
count = 1
# Append the last character's count and the
# last character
curr += str(count) + prev[-1]
return curr
# Recursive function to return the nth term
def countAndSay(n):
# Base case
if n == 1:
return "1"
# Recursively get the previous term
prev = countAndSay(n - 1)
# Get the n-th term using (n-1)th
return nextTerm(prev)
# Driver code
if __name__ == "__main__":
n = 5
print(countAndSay(n))
C#
using System;
using System.Text;
// Helper function to generate the next term
// in the sequence from the previous one
class GfG {
public static string nextTerm(string prev) {
StringBuilder curr = new StringBuilder();
int count = 1;
for (int i = 1; i < prev.Length; i++) {
// Keep Counting while same
if (prev[i] == prev[i - 1]) {
count++;
// If a different character found, append
// the count of previous character along
// with the character itself
} else {
curr.Append(count).Append(prev[i - 1]);
count = 1;
}
}
// Append the last character's count and the
// last character
curr.Append(count).Append(prev[prev.Length - 1]);
return curr.ToString();
}
// Recursive function to return the nth term
public static string countAndSay(int n) {
// Base case
if (n == 1)
return "1";
// Recursively get the previous term
string prev = countAndSay(n - 1);
// Get the n-th term using (n-1)th
return nextTerm(prev);
}
// Driver code
public static void Main(string[] args) {
int n = 5;
Console.WriteLine(countAndSay(n));
}
}
JavaScript
// Helper function to generate the next term
// in the sequence from the previous one
function nextTerm(prev) {
let curr = "";
let count = 1;
for (let i = 1; i < prev.length; i++) {
// Keep Counting while same
if (prev[i] === prev[i - 1]) {
count++;
} else {
// If a different character found, append
// the count of previous character along
// with the character itself
curr += count.toString() + prev[i - 1];
count = 1;
}
}
// Append the last character's count and the
// last character
curr += count.toString() + prev[prev.length - 1];
return curr;
}
// Recursive function to return the nth term
function countAndSay(n) {
// Base case
if (n === 1) {
return "1";
}
// Recursively get the previous term
const prev = countAndSay(n - 1);
// Get the n-th term using (n-1)th
return nextTerm(prev);
}
// Driver code
const n = 5;
console.log(countAndSay(n));
Why is the time complexity exponential?
The next term can be at-most double the size of previous term. We get double size when all characters are different. So an upper bound on the time complexity would be O(2n). We need this long string also for output and O(n) space for recursion. That is why the space is O(2n + n).
Iterative Solution - O(2^n) Time and O(2^n) Space
Instead of recursively generating the previous term, we build all terms one by one from first term which is "1" to the nth term. To generate the next term, we use the same idea as used in the above recursive solution.
C++
#include <bits/stdc++.h>
using namespace std;
// Iterative function to return the nth term
string countAndSay(int n) {
if (n == 1)
return "1";
string curr = "1";
// Start from the second term, build every term
// terms using the previous term
for (int i = 2; i <= n; i++) {
string next = "";
int cnt = 1;
for (int j = 1; j < curr.length(); j++) {
// If same as previous, then increment
// count
if (curr[j] == curr[j - 1]) {
cnt++;
// If different process the previous
// character and its count and reset
// count for the current character
} else {
next += to_string(cnt) + curr[j - 1];
cnt = 1;
}
}
next += to_string(cnt) + curr.back();
curr = next;
}
return curr;
}
// Driver code
int main() {
int n = 5;
cout << countAndSay(n) << endl;
return 0;
}
Java
// Iterative function to return the nth term
class GfG {
public static String countAndSay(int n) {
if (n == 1) return "1";
String curr = "1";
// Start from the second term, build every term
// terms using the previous term
for (int i = 2; i <= n; i++) {
StringBuilder next = new StringBuilder();
int cnt = 1;
for (int j = 1; j < curr.length(); j++) {
// If same as previous, then increment
// count
if (curr.charAt(j) == curr.charAt(j - 1)) {
cnt++;
// If different process the previous
// character and its count and reset
// count for the current character
} else {
next.append(cnt).append(curr.charAt(j - 1));
cnt = 1;
}
}
next.append(cnt).append(curr.charAt(curr.length() - 1));
curr = next.toString();
}
return curr;
}
// Driver code
public static void main(String[] args) {
int n = 5;
System.out.println(countAndSay(n));
}
}
Python
# Iterative function to return the nth term
def countAndSay(n):
if n == 1:
return "1"
curr = "1"
# Start from the second term, build every term
# terms using the previous term
for i in range(2, n + 1):
nextStr = ""
cnt = 1
for j in range(1, len(curr)):
# If same as previous, then increment
# count
if curr[j] == curr[j - 1]:
cnt += 1
# If different process the previous
# character and its count and reset
# count for the current character
else:
nextStr += str(cnt) + curr[j - 1]
cnt = 1
nextStr += str(cnt) + curr[-1]
curr = nextStr
return curr
# Driver code
if __name__ == "__main__":
n = 5
print(countAndSay(n))
C#
// Iterative function to return the nth term
using System;
class GfG{
public static string countAndSay(int n) {
if (n == 1) return "1";
string curr = "1";
// Start from the second term, build every term
// terms using the previous term
for (int i = 2; i <= n; i++) {
string next = "";
int cnt = 1;
for (int j = 1; j < curr.Length; j++) {
// If same as previous, then increment
// count
if (curr[j] == curr[j - 1]) {
cnt++;
// If different process the previous
// character and its count and reset
// count for the current character
} else {
next += cnt.ToString() + curr[j - 1];
cnt = 1;
}
}
next += cnt.ToString() + curr[curr.Length - 1];
curr = next;
}
return curr;
}
// Driver code
public static void Main() {
int n = 5;
Console.WriteLine(countAndSay(n));
}
}
JavaScript
// Iterative function to return the nth term
function countAndSay(n) {
if (n === 1) return "1";
let curr = "1";
// Start from the second term, build every term
// terms using the previous term
for (let i = 2; i <= n; i++) {
let next = "";
let cnt = 1;
for (let j = 1; j < curr.length; j++) {
// If same as previous, then increment
// count
if (curr[j] === curr[j - 1]) {
cnt++;
// If different process the previous
// character and its count and reset
// count for the current character
} else {
next += cnt.toString() + curr[j - 1];
cnt = 1;
}
}
next += cnt.toString() + curr[curr.length - 1];
curr = next;
}
return curr;
}
// Driver code
const n = 5;
console.log(countAndSay(n));
Similar Reads
Recaman's sequence Given an integer n. Print first n elements of Recamanâs sequence. Recaman's Sequence starts with 0 as the first term. For each next term, calculate previous term - index (if positive and not already in sequence); otherwise, use previous term + index.Examples: Input: n = 6Output: 0, 1, 3, 6, 2, 7Expl
8 min read
Golomb Sequence | Set 2 Given a number N. The task is to find the first N terms of the Golomb Sequence. Golomb sequence is a non-decreasing integer sequence where the n-th term is equal to the number of times n appears in the sequence. Input: N = 11 Output: 1 2 2 3 3 4 4 4 5 5 5 Explanation: The first term is 1. 1 appears
8 min read
What are Subsequences in an Array? Subsequences are a fundamental concept in computer science and programming when working with arrays. A subsequence of an array is a sequence of elements from the array that appear in the same order, but not necessarily consecutively. In this blog post, we'll discuss subsequences, covering their defi
6 min read
Gijswijt's Sequence Gijswijt's sequence is a self-describing sequence where the value of each term is equal to the maximum number of repeated blocks of numbers in the sequence preceding the number.Let us take the ith term of the sequence a(i), Then for this Gijswijt's Sequence: where k is the largest natural number suc
9 min read
Introduction to Sequences A sequence is a list of numbers arranged in a specific order, following a particular rule. Each number in the sequence is called a term. In mathematics, a sequence is an ordered list of numbers, where each number in the list is called a term. Sequences are defined by a specific rule that determines
7 min read
Arithmetic Sequence An arithmetic sequence or progression is defined as a sequence of numbers in which the difference between one term and the next term remains constant.For example: the given below sequence has a common difference of 1.1 2 3 4 5 . . . n â â â â â . . . 1st 2nd 3rd 4th 5th . . . nth TermsThe Arithmetic
8 min read