Kotlin

Linked List

How to Create a Linked List in Kotlin: Easy Step-by-Step Tutorial

If you’re diving into the world of Kotlin and exploring data structures, you’ve probably come across linked lists. While arrays and lists are common in Kotlin development, understanding linked lists can open up new levels of flexibility in your coding journey. In this guide, we’ll unravel what linked lists are, why you might need them, and most importantly, how to create and use linked lists in Kotlin.

What is a Linked List?

A Linked List is a data structure consisting of a sequence of elements, called nodes. 

Each node has two components:

  • Data: The value we want to store.
  • Next: A reference to the next node in the sequence.

Unlike arrays, Linked Lists are dynamic in size, offering efficient insertions and deletions at any position in the list.

In a linked list, each node stores a value and points to the next node in the chain. The last node in the sequence points to “null,” indicating the end of the list.

Linked lists have several advantages over arrays or ArrayLists in Kotlin:

  • Quick insertions and removals at the front of the list.
  • Consistent performance for operations, especially for inserting or removing elements anywhere in the list.

Types of Linked Lists

  1. Singly Linked List — Each node points to the next node in the sequence (we’ll focus on this one).
  2. Doubly Linked List — Each node has a reference to both the next and the previous node.
  3. Circular Linked List — The last node points back to the first node, forming a loop.

Building a Singly Linked List in Kotlin

Kotlin doesn’t offer a built-in linked list class like Java does. But no worries! We’re going to create our own custom Singly Linked List step-by-step. Let’s create a linked list from scratch! We’ll start by defining the Node class and then build a LinkedList class to manage the nodes.

Defining the Node Class

Each node needs to store data and a reference to the next node. Here’s our Node class:

Kotlin
// We define a node of the linked list as a data class, where it holds a value and a reference to the next node.

data class Node<T>(var value: T, var next: Node<T>? = null) {
    override fun toString(): String {
        return if (next != null) "$value -> ${next.toString()}" else "$value"
    }
}

fun main() {
    val node1 = Node(value = 1)
    val node2 = Node(value = 2)
    val node3 = Node(value = 3)

    node1.next = node2
    node2.next = node3   //here node3 points to null at last, as per our code we only print its value
    println(node1)
}

//OUTPUT

1 -> 2 -> 3

Here, we defined a generic Node class for a linked list in Kotlin. Each Node holds a value of any type (T) and a reference to the next Node, which can be null. The toString() method provides a custom string representation for the node, recursively displaying the value of the node followed by the values of subsequent nodes, separated by ->. If the node is the last in the list, it simply shows its value.

Have you observed how we constructed the list above? We essentially created a chain of nodes by linking their ‘next’ references. However, building lists in this manner becomes impractical as the list grows larger. To address this, we can use a LinkedList, which simplifies managing the nodes and makes the list easier to work with. Let’s explore how we can implement this in Kotlin.

Creating the LinkedList Class

Let’s create our LinkedList class and add core functionalities like adding nodes and displaying the list.

Basically, a linked list has a ‘head’ (the first node) and a ‘tail’ (the last node). In a singly linked list, we usually only deal with the head node, although the tail node can also be relevant, especially when adding elements at the end. The tail node becomes more important in doubly linked lists or circular linked lists, where it supports bidirectional traversal or maintains circular references. However, here, we will use both nodes in a singly linked list.

Kotlin
class LinkedList<T> {
    private var head: Node<T>? = null
    private var tail: Node<T>? = null
    private var size = 0

    // Method to check if the list is empty
    fun isEmpty(): Boolean = size == 0
    
     // to print nodes in linkedlist
    override fun toString(): String {
        if (isEmpty()) {
            return "Empty list"
        } else {
            return head.toString()
        }
    }
}

Here, a linked list has a ‘head’ (the first node) and a ‘tail’ (the last node). We’ll also store the list’s size in a ‘size’ property.

Now, to use this linked list, we need to store or add some values to it. Otherwise, we’d only be using an empty list. There are three major operations for adding values to a linked list, and we’ll explore each one in more details in the next blog. First, let’s see how to add a new value (or node) to the linked list and then print the result.

Kotlin
// Method to add a new node at the beginning
fun addFirst(data: T) {
    val newNode = Node(data)
    newNode.next = head
    head = newNode
    size++
}

Here, we first create a new node with the passed value. Then, the new node’s next points to the head, and finally, we update the head to point to the newly created node. The same process is repeated whenever we add a new value.

Note: Whenever a new value is added, the list size increases. Therefore, we need to increment the size accordingly.

Now, let’s look at the complete code.

Kotlin
class LinkedList<T> {
    private var head: Node<T>? = null
    private var tail: Node<T>? = null
    private var size = 0

    // Method to check if the list is empty
    fun isEmpty(): Boolean = size == 0

    // to print nodes in linkedlist
    override fun toString(): String {
        if (isEmpty()) {
            return "Empty list"
        } else {
            return head.toString()
        }
    }

    // Method to add a new node at the beginning
    fun addFirst(data: T) {
        val newNode = Node(data)
        newNode.next = head
        head = newNode
        size++
    }
}

Using the Linked List in Kotlin

Let’s put our linked list to the test! Here’s how we can use the LinkedList class:

Kotlin
fun main() {
    val myList = LinkedList<String>()

    println("Is the list empty? ${myList.isEmpty()}")

    myList.addFirst("Kotlin")
    myList.addFirst("Hello")
   
    println(myList) // Output: Hello -> Kotlin -> null

    println("Is the list empty? ${myList.isEmpty()}")
}

Output

Kotlin
Is the list empty? true
Hello -> Kotlin
Is the list empty? false

Conclusion

We’ve explored the key insertion operations in linked lists, along with the foundational concepts and structure that make them an essential part of data management. Understanding these operations provides a solid base for working with linked lists in various scenarios. 

Linked lists might seem daunting, but with a bit of practice, you’ll be using them like a pro.

Internal DSLs

Building Internal DSLs in Your Favorite Programming Language

Software isn’t just about solving problems — it’s about making solutions expressive and readable. One powerful way to do this is by building Internal DSLs (Domain-Specific Languages). If you’ve ever wished your code could read more like English (or your team’s own domain language), then an internal DSL might be the tool you’re looking for. What Are...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Fibonacci in Kotlin

Fibonacci in Kotlin: Recursion, Loops & Dynamic Programming (Complete Guide)

The Fibonacci sequence isn’t just math trivia — it’s a timeless example used in coding interviews, algorithm practice, and real-world software optimization. In this guide, we’ll explore how to implement Fibonacci in Kotlin using: Recursion — Easy to grasp, but not the fastest. Loops — Simple and efficient. Dynamic Programming — Optimized for large numbers. What is the Fibonacci Sequence? The Fibonacci sequence...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
External DSLs

The Power of External DSLs: Definition, Benefits, and Use Cases

In today’s fast-evolving software landscape, building systems that are both powerful and easy to maintain is crucial. One concept gaining increasing attention in software development is External Domain-Specific Languages, or External DSLs

This blog will explore what External DSLs are, their benefits, and practical use cases.

What are external DSLs?

External Domain-Specific Languages (DSLs) are a type of domain-specific language that is distinct from the host programming language in which it is embedded. A domain-specific language is a language designed for a specific problem domain or application context, tailored to address the unique requirements and challenges of that domain.

External DSLs are created to facilitate a more intuitive and expressive way of defining solutions for specific domains. Instead of using the syntax and constructs of a general-purpose programming language, developers create a new language with syntax and semantics that are closely aligned with the problem domain. This allows users (often non-programmers) to express solutions using familiar terminology and concepts, making the code more readable and less error-prone.

Key characteristics of external DSLs include:

  1. Separation from host language: External DSLs have their own syntax and grammar, independent of the underlying host programming language. This means that the DSL code is not written directly in the host language but in a separate file or structure.
  2. Domain-specific abstractions: The syntax and semantics of the external DSL are tailored to the specific domain, making it more natural for domain experts to understand and work with the code.
  3. Readability and simplicity: External DSLs are designed to be easily readable and writable by domain experts, even if they do not have extensive programming knowledge.
  4. Specific scope and focus: Each external DSL is designed to tackle a particular problem domain, ensuring it remains concise and focused.
  5. Custom tools and parsers: To work with external DSLs, custom tools and parsers are developed to interpret and transform the DSL code into executable code or other desired outputs.

Examples of External DSLs:

  • Regular expressions: Regular expressions are a classic example of an external DSL used for pattern matching in strings. They have a concise and domain-specific syntax for expressing text patterns.
  • SQL (Structured Query Language): SQL is a popular external DSL used for querying and managing relational databases. It provides a language-specific syntax for expressing database operations.
  • HTML (HyperText Markup Language): While HTML is commonly used within web development, it can be considered an external DSL as it has its own specific syntax and is used to describe the structure and content of web pages.

Creating an external DSL typically involves designing the language’s grammar, specifying the semantics, and building the necessary tools (e.g., parsers, interpreters, code generators) to work with the DSL effectively. External DSLs can be a powerful tool for improving productivity and collaboration between domain experts and programmers, as they allow domain experts to focus on their expertise without being overwhelmed by the complexities of a general-purpose programming language.

Conclusion

External DSLs bring a unique power to software development by creating dedicated languages tailored to specific domains. They promote clarity, ease of use, and collaboration across teams. While crafting an External DSL requires upfront effort in designing and implementing the language tools, the long-term gains in productivity, maintainability, and alignment with business goals make them a compelling choice for many projects.

Whenever you encounter complex domain logic that can benefit from clearer expression and better separation from core code, consider the transformative potential of External DSLs.

By embracing External DSLs, you harness the power of specialization, making software more intuitive, agile, and aligned with the real-world domain it serves.

Domain-Specific Language

The Power of Domain-Specific Languages: From Theory to Practical Implementation

If you’ve ever used SQL to query a database, CSS to style a webpage, or Markdown to format text, you’ve already worked with a Domain-Specific Language (DSL). In this post, we’ll unpack what DSLs are, why they’re so powerful, and how you can create one yourself in Kotlin. What Are Domain-Specific Languages? A Domain-Specific Language...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Generate All Permutations of a String

How to Generate All Permutations of a String in Kotlin — Fast O(n) Approach (Handles Duplicates + Large Input Tips)

When most developers search for “Generate All Permutations of a String”, they find solutions that work but are often slow, overly complex, or hard to read. Today, we’re going to cut through the noise and build a simple, fast, and easy-to-understand Kotlin solution that runs in O(n) time per permutation — which is as efficient as it...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Fibonacci in Kotlin Using Dynamic Programming

Fibonacci in Kotlin Using Dynamic Programming: The Ultimate Guide

If you’ve ever dived into programming, chances are you’ve come across the famous Fibonacci sequence. It’s a classic problem that teaches us a lot about algorithms and optimization techniques. In this ultimate guide, we’ll explore Fibonacci in Kotlin Using Dynamic Programming in a friendly and easy-to-understand way. Whether you’re a beginner or an experienced Kotlin...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Fibonacci Using Loops in Kotlin

Fibonacci Using Loops in Kotlin: A Simple & Efficient Approach

If you’ve just started learning Kotlin and want to practice loops in a real-world example, generating the Fibonacci series is a perfect choice. It’s simple enough to grasp, yet teaches you how to handle variables, loops, and logic in Kotlin efficiently.

In this guide, we’ll explore Fibonacci Using Loops in Kotlin, break down the code step-by-step, and keep it beginner-friendly — without skipping important details.

What is the Fibonacci Sequence?

The Fibonacci sequence is a series of numbers where each number is the sum of the two before it.

It starts like this:

Kotlin
0, 1, 1, 2, 3, 5, 8, 13, 21, 34...

Mathematically:

Kotlin
F(n) = F(n-1) + F(n-2)

Where:

  • F(0) = 0
  • F(1) = 1

Why Use Loops Instead of Recursion?

While recursion can generate Fibonacci numbers, it’s less efficient for large sequences because:

  • It repeats calculations unnecessarily.
  • It uses more memory due to function calls.

Using loops in Kotlin:
 Saves memory.
 Runs faster.
 Easier to understand for beginners.

That’s why Fibonacci Using Loops in Kotlin is both simple and efficient.

Kotlin Program for Fibonacci Using Loops

Here’s the complete Kotlin code:

Kotlin
fun main() {
    val terms = 10  // Number of Fibonacci numbers to print
    var first = 0
    var second = 1

    println("Fibonacci Series using loops:")

    for (i in 1..terms) {
        print("$first ")
        // Calculate the next number
        val next = first + second
        first = second
        second = next
    }
}

Step-by-Step Code Explanation

Let’s break it down so you truly understand:

1. Declaring Variables

Kotlin
fun main() {
    val terms = 10  // Number of Fibonacci numbers to print
    var first = 0
    var second = 1

    println("Fibonacci Series using loops:")

    for (i in 1..terms) {
        print("$first ")
        // Calculate the next number
        val next = first + second
        first = second
        second = next
    }
}
  • terms → how many numbers you want to print.
  • first and second → the first two Fibonacci numbers.

2. Using a Loop

Kotlin
for (i in 1..terms) {
    print("$first ")
    val next = first + second
    first = second
    second = next
}
  • Loop runs from 1 to terms → controls how many numbers are printed.
  • print("$first ") → displays the current number.
  • val next = first + second → calculates the next Fibonacci number.

We then shift the values:

  • first becomes the old second.
  • second becomes the new next.

Not clear — let’s dry run it for better understanding.

Iteration 1 (i = 1)

  • Print first → prints 0
  • next = first + second = 0 + 1 = 1
  • Update:
     first = second = 1
     second = next = 1

Output: 0

Iteration 2 (i = 2)

  • Print first → prints 1
  • next = 1 + 1 = 2
  • Update:
     first = 1
     second = 2

Output: 0 1

Iteration 3 (i = 3)

  • Print first → prints 1
  • next = 1 + 2 = 3
  • Update:
     first = 2
     second = 3

Output: 0 1 1

Iteration 4 (i = 4)

  • Print first → prints 2
  • next = 2 + 3 = 5
  • Update:
     first = 3
     second = 5

Output: 0 1 1 2

Iteration 5 (i = 5)

  • Print first → prints 3
  • next = 3 + 5 = 8
  • Update:
     first = 5
     second = 8

Output: 0 1 1 2 3

Iteration 6 (i = 6)

  • Print first → prints 5
  • next = 5 + 8 = 13
  • Update:
     first = 8
     second = 13

Output: 0 1 1 2 3 5

Iteration 7 (i = 7)

  • Print first → prints 8
  • next = 8 + 13 = 21
  • Update:
     first = 13
     second = 21

Output: 0 1 1 2 3 5 8

Iteration 8 (i = 8)

  • Print first → prints 13
  • next = 13 + 21 = 34
  • Update:
     first = 21
     second = 34

Output: 0 1 1 2 3 5 8 13

Iteration 9 (i = 9)

  • Print first → prints 21
  • next = 21 + 34 = 55
  • Update:
     first = 34
     second = 55

Output: 0 1 1 2 3 5 8 13 21

Iteration 10 (i = 10)

  • Print first → prints 34
  • next = 34 + 55 = 89
  • Update:
     first = 55
     second = 89

Output: 0 1 1 2 3 5 8 13 21 34

Final Output

If terms = 10, output will be:

Kotlin
Fibonacci Series using loops:
0 1 1 2 3 5 8 13 21 34

Tips to Make It Even Better

  • User Input: Instead of hardcoding terms, ask the user how many numbers they want.
Kotlin
print("Enter the number of terms: ")
   
val n = readLine()!!.toInt()
  • Formatting: Add commas or line breaks for readability.
  • Performance: This loop method already runs in O(n) time, making it efficient even for large terms.

Why This Approach Works Well

The Fibonacci Using Loops in Kotlin approach is ideal for:

  • Beginners learning loops.
  • Anyone needing quick and efficient Fibonacci generation.
  • Avoiding recursion stack overflow for large sequences.

It’s clean, easy to debug, and performs well.

Conclusion

The Fibonacci sequence is a timeless example for learning programming logic. By using loops in Kotlin, you get the perfect balance between simplicity and efficiency. Whether you’re practicing for interviews or just improving your coding skills, this method will serve you well.

Next time you think about Fibonacci, remember — you don’t always need recursion. A good old loop can do the job beautifully.

Kotlin Flow

Kotlin Flow vs LiveData: Why Android Developers Are Moving On (And How to Migrate Smoothly)

If you’ve been building Android apps for a few years, you’ve probably written your fair share of LiveData. For a long time, it was the go-to choice for exposing observable data from a ViewModel to the UI. It solved an important problem: lifecycle awareness. But the Android world has changed. Kotlin coroutines have become the...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Fibonacci Sequence in Kotlin Using Recursion

Fibonacci Sequence in Kotlin Using Recursion — From Theory to Code

If you’ve ever been fascinated by numbers that seem to appear everywhere in nature — from the petals of flowers to the spirals in seashells — then you’ve already met the Fibonacci sequence.

In this blog, we’ll explore Fibonacci Sequence in Kotlin Using Recursion step by step. We’ll start with the theory, then move into writing simple yet powerful Kotlin code. Everything will be easy to follow, and beginner-friendly.

Understanding the Fibonacci Sequence

The Fibonacci sequence is a series of numbers where:

Kotlin
F(n) = F(n-1) + F(n-2)

with:

Kotlin
F(0) = 0
F(1) = 1

So, the sequence begins like this:

Kotlin
0, 1, 1, 2, 3, 5, 8, 13, 21, ...

Each term is the sum of the previous two terms. It’s a simple rule with surprisingly deep applications — mathematics, art, computer science, and even stock market analysis.

Why Use Recursion?

Recursion is when a function calls itself to solve smaller parts of a problem.
 In the case of the Fibonacci sequence, recursion works naturally because the definition of Fibonacci is already recursive in nature:

  • To find F(n), you find F(n-1) and F(n-2) and add them.
  • Each of those smaller problems breaks down further until you hit the base case (F(0) or F(1)).

Think of it like climbing stairs:

  • To reach the nth step, you must have come from either step (n-1) or (n-2).
  • You keep breaking it down until you reach the first or second step.

Writing Fibonacci Sequence in Kotlin Using Recursion

Here’s the code:

Kotlin
fun fibonacci(n: Int): Int {
    // Base cases: when n is 0 or 1
    if (n == 0) return 0
    if (n == 1) return 1

// Recursive call
    return fibonacci(n - 1) + fibonacci(n - 2)
}

fun main() {
    val terms = 10

    println("Fibonacci sequence up to $terms terms:")

    for (i in 0 until terms) {
        print("${fibonacci(i)} ")
    }
}

Code Explanation

1. Base Cases

Kotlin
if (n == 0) return 0
if (n == 1) return 1

These are our stopping points. If n is 0 or 1, we simply return the value without further calculations.

2. Recursive Step

Kotlin
return fibonacci(n - 1) + fibonacci(n - 2)

The function calls itself twice:

  • Once for the previous term (n-1)
  • Once for the term before that (n-2)
     It then adds them together to produce the nth term.

3. Main Function

Kotlin
for (i in 0 until terms) {
    print("${fibonacci(i)} ")
}

We loop through and print the first terms Fibonacci numbers, giving us a clean, readable sequence.

A Note on Performance

While Fibonacci Sequence in Kotlin Using Recursion is elegant and easy to understand, pure recursion can be slow for large n because it recalculates the same values multiple times.

Example:

  • fibonacci(5) calls fibonacci(4) and fibonacci(3).
  • But fibonacci(4) again calls fibonacci(3) — we’re repeating work.

Solution: Use memoization or dynamic programming to store results and avoid recalculations. But for learning recursion, the basic approach is perfect.

Real-World Applications

  • Algorithm practice: Great for learning recursion and problem-solving.
  • Mathematical modeling: Growth patterns in populations or financial data.
  • Computer graphics: Spiral designs and procedural patterns.

Key Takeaways

  • The Fibonacci sequence is naturally suited to recursion because of its self-referential definition.
  • Kotlin makes it clean and readable with its concise syntax.
  • For small inputs, recursion works perfectly, but for larger inputs, optimization is needed.

Conclusion

Recursion is like magic — it hides complexity behind a few lines of code. With the Fibonacci Sequence in Kotlin Using Recursion, you get both an elegant algorithm and a deep understanding of how problems can solve themselves step by step.

error: Content is protected !!