Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Jacobsthal and Jacobsthal-Lucas Numbers
Jacobsthal Numbers
Lucas sequence ??(?,?) where P = 1 and Q = -2 are called Jacobsthal numbers. The recurrence relation for Jacobsthal numbers is,
$$\mathrm{?_? = 0\: ??? \: ? = 0}$$
$$\mathrm{?_? = 1\: ??? \: ? = 1}$$
$$\mathrm{?_? = ?_??1 + 2?_{??2}\: ??? \: ? > 1}$$
Following are the Jacobsthal numbers ?
0, 1, 1, 3, 5, 11, 21, 43, 85, 171, 341, 683, 1365, ?.
Jacobsthal-Lucas Numbers
Complementary Lucas sequence $\mathrm{?_?(?,?)}$ where P = 1 and Q = -2 are called JacobsthalLucas numbers. The recurrence relation for Jacobsthal-Lucas numbers is,
$\mathrm{?_?}$ = 2 ??? ? = 0
$\mathrm{?_?}$ = 1 ??? ? = 1
$\mathrm{?_? = ?_{??1} + 2?_{??2}\: ??? \: ? > 1}$
Following are the Jacobsthal-Lucas numbers ?
2, 1, 5, 7, 17, 31, 65, 127, 257, 511, 1025, 2047, 4097, ?.
Problem Statement
Given an integer, N. Find the Nth Jacobsthal and Jacobsthal-Lucas number.
Example 1
Input: 2
Output: Jacobsthal = 1 Jacobsthal-Lucas = 5
Explanation
Jacobsthal Numbers - 0, 1, 1
Jacobsthal-Lucas Numbers - 2, 1, 5
Example 2
Input: 12
Output: Jacobsthal = 1365 Jacobsthal-Lucas = 4097
Explanation
Jacobsthal Numbers ? 0, 1, 1, 3, 5, 11, 21, 43, 85, 171, 341, 683, 1365
Jacobsthal-Lucas Numbers ? 2, 1, 5, 7, 17, 31, 65, 127, 257, 511, 1025, 2047, 4097
Approach 1: Recursive Approach
Using the recurrence relation of Jacobsthal and Jacobsthal-Lucas numbers, we can form a recursive relation as, $\mathrm{?_? = ?_{??1} + 2?_{??2}}$
Pseudocode
procedure jacobsthalNumber (n)
if n == 0
ans = 0
end if
if n == 1
ans = 1
end if
ans = jacobsthalNumber(n-1) + 2*jacobsthalNumber(n-2)
end procedure
procedure jacobsthalLucasNumber (n)
if n == 0
ans = 2
end if
if n == 1
ans = 1
end if
ans = jacobsthalLucasNumber(n-1) + 2*jacobsthalLucasNumber(n-2)
end procedure
Example
In the following program, we have created separate functions for jacobsthal and jacobsthal-lucas numbers and used their recurrence relation to recursively calculate the nth number.
#include<bits/stdc++.h>
using namespace std;
// Recursive function for finding the nth Jacobsthal Number
int jacobsthalNumber (int n){
// Defining the first case in recurrence relation
if (n == 0) {
return 0;
}
// Defining the second case in recurrence relation
if (n == 1) {
return 1;
}
// Defining the third case in recurrence relation when n>1
return jacobsthalNumber(n-1) + 2*jacobsthalNumber(n-2);
}
// Recursive function for finding the nth Jacobsthal-Lucas Number
int jacobsthalLucasNumber (int n){
// Defining the first case in recurrence relation
if (n == 0) {
return 2;
}
// Defining the second case in recurrence relation
if (n == 1) {
return 1;
}
// Defining the third case in recurrence relation when n>1
return jacobsthalLucasNumber(n-1) + 2*jacobsthalLucasNumber(n-2);
}
int main(){
int N = 7;
cout << N << "th Jacobsthal number = " << jacobsthalNumber(N) << endl;
cout << N << "th Jacobsthal-Lucas number = " << jacobsthalLucasNumber(N) << endl;
}
Output
7th Jacobsthal number = 43 7th Jacobsthal-Lucas number = 127
Time Complexity ? O(2n) due to the recursive tree formed.
Space Complexity ? O(1) + Recursive stack space.
Approach 2: Memoization
Memoization is helpful in reducing time complexity as it helps compute the function for one input only once by storing the results.
Pseudocode ?
Initialize two arrays j[N+1] and jL[N+1] with -1
procedure jacobsthalNumber (n)
if n == 0
ans = 0
end if
if n == 1
ans = 1
end if
if j[n] == -1
j[n] = jacobsthalNumber(n-1) + 2*jacobsthalNumber(n-2)
end if
ans = j[n]
end procedure
procedure jacobsthalLucasNumber (n)
if n == 0
ans = 2
end if
if n == 1
ans = 1
end if
if jL[n] == -1
jL[n] = jacobsthalLucasNumber(n-1) + 2*jacobsthalLucasNumber(n-2)
end if
ans = jL[n]
end procedure
Example
In this program, we use memoization to reduce the time complexity of the previous approach.
#include<bits/stdc++.h>
using namespace std;
int N = 12;
// initializing memoization table
vector<int> j(N+1, -1), jL(N+1, -1);
// Memoized function for finding the nth Jacobsthal Number
int jacobsthalNumber (int n){
// Defining the first case in recurrence relation
if (n == 0) {
return 0;
}
// Defining the second case in recurrence relation
if (n == 1) {
return 1;
}
// Checking if nth jacobsthal number is already calculated or not
if(j[n] != -1) {
return j[n];
} else {
return j[n] = jacobsthalNumber(n-1) + 2*jacobsthalNumber(n-2);
}
}
// Memoized function for finding the nth Jacobsthal-Lucas Number
int jacobsthalLucasNumber (int n){
// Defining the first case in recurrence relation
if (n == 0) {
return 2;
}
// Defining the second case in recurrence relation
if (n == 1) {
return 1;
}
// Checking if nth jacobsthal-lucas number is already calculated or not
if(jL[n] != -1) {
return jL[n];
} else {
return jL[n] = jacobsthalLucasNumber(n-1) + 2*jacobsthalLucasNumber(n-2);
}
}
// Driver code
int main(){
cout << N << "th Jacobsthal number = " << jacobsthalNumber(N) << endl;
cout << N << "th Jacobsthal-Lucas number = " << jacobsthalLucasNumber(N) << endl;
}
Output
12th Jacobsthal number = 1365 12th Jacobsthal-Lucas number = 4097
Time Complexity ? O(N) as repetitive recursive calls are not calculated.
Space Complexity ? O(N) (because of the space used for the memoization table) + recursive stack space.
Approach 3: Dynamic Programming
Pseudocode ?
procedure jacobsthal (n)
initialize dp table jacobsthalDP[n+1]
jacobsthalDP[0] = 0
jacobsthalDP[1] = 1
for i = 2 to n
jacobsthalDP[i] = jacobsthalDP[i-1] + 2*jacobsthalDP[i-2]
end for
ans = jacobsthalDP[n]
end procedure
procedure jacobsthalLucas (n)
initialize dp table jacobsthalLucasDP[n+1]
jacobsthalLucasDP[0] = 2
jacobsthalLucasDP[1] = 1
for i = 2 to n
jacobsthalLucasDP[i] = jacobsthalLucasDP[i-1] + 2*jacobsthalLucasDP[i-2]
end for
ans = jacobsthalLucasDP[n]
end procedure
Example
In the following program, dynamic programming approach is used.
#include<bits/stdc++.h>
using namespace std;
// Function for finding the nth Jacobsthal Number
int jacobsthalNumber (int n){
int jacobsthalDP[n+1];
// Defining base condition
jacobsthalDP[0] = 0;
jacobsthalDP[1] = 1;
for (int i = 2 ; i <= n ; i++){
jacobsthalDP[i] = jacobsthalDP[i-1] + 2*jacobsthalDP[i-2];
}
return jacobsthalDP[n];
}
// Function for finding the nth Jacobsthal-Lucas Number
int jacobsthalLucasNumber (int n){
int jacobsthalLucasDP[n+1];
// Defining base condition
jacobsthalLucasDP[0] = 2;
jacobsthalLucasDP[1] = 1;
for (int i = 2 ; i <= n ; i++){
jacobsthalLucasDP[i] = jacobsthalLucasDP[i-1] + 2*jacobsthalLucasDP[i-2];
}
return jacobsthalLucasDP[n];
}
int main(){
int N = 5;
cout << N << "th Jacobsthal number = " << jacobsthalNumber(N) << endl;
cout << N << "th Jacobsthal-Lucas number = " << jacobsthalLucasNumber(N) << endl;
}
Output
5th Jacobsthal number = 11 5th Jacobsthal-Lucas number = 31
Time Complexity ? O(n) as for loop is only executed once in each function
Space Complexity ? O(n) for the dp table. In this approach, no extra stack recursive space is used.
Conclusion
In conclusion, Jacobsthal numbers are obtained from the Lucas sequence and Jacobsthal-Lucas numbers are obtained from the complementary Lucas sequence. In order to find the nth Jacobsthal and Jacobsthal-Lucas number, we can move from a recursive to a dynamic programming approach with minimum time and space complexity.