Categories
Career Programming

My “How to solve coding interview” articles so far…

Meme: Coding alone (picture of not-too-bright Spider-Man villain The Rhino with stupid smirk) vs. Coding in an interview (exact same picture of not-too-bright Spider-Man villain The Rhino with stupid smirk).

Are you trying to pivot into a programming job? Are you part of the Great Resignation and looking for your next coding gig? Are you learning coding and looking for examples of how to solve programming problems?

If you answered “yes” to any of these questions, you might want to check out my series of articles on this blog in which I show you how to solve coding problems that tech companies have been known to ask in interviews.

Here’s what I’ve written so far:

Categories
Career

The most important tech skill ISN’T Googling for answers, but THIS…

As a reader of this blog, you’re probably familiar with the wry observation that the most important tech skill is knowing how to Google for answers. Over the years, this observation has been turned into many, many memes:

Meme: Squinting Fry from “Futurama” with caption “Not sure if I am good at programming or good at Googling.”

Meme: Programmer concentrating at laptop with caption “New programmers Google everything; Pro programmers Google everything.”

Meme: “First step in learning programming” dones as Drake “no / yes” meme. “No” caption: “Learn basic syntax, data types and variables.” “Yes” caption: “Learn how to Google.”

Image: Headline reading “Computer programming to be officially renamed ‘Googling Stack Overflow’.”

Meme: Day 1 of programming — Google. 10 Years of programming — Google.

Twitter screenshot: ”My spouse (an artist, not in tech), working her way through a C++ class (part of Digital Arts curriculum) /  Me: Let me know if you need help / She: Will do / 2 hrs later / Me: How's it going? / She: Fine. I'm cheating / Me: ??? / She: I google for stuff don't know / Do I tell her?”

I’ll agree that it’s a valuable tech skill. I do it all the time!

However, with nearly 25 years of Google, it’s now assumed that you Google answers in day-to-day office work, just as it’s assumed that you know the basics of using a word processor, spreadsheet, and presentation software (you can still list Excel on your resume if you have deep spreadsheet skills — don’t forget that Excel is the next big esport!).

The “level two” skill

Googling for answers is a “level one” skill. It will serve you well for immediate needs in your daily life.

What you eventually want to do is move to the next level: Writing the answers that people Google for.

Here are the reasons why you want to reach level two:

  1. It often expands your knowledge of the subject matter you’re covering.
  2. It establishes you as a credible and knowledgeable source of information on the subject matter.
  3. It often gets people to approach you with job offers, or offer to pay you for your services, or ask to work for you.

Achieving level two has two key components:

  1. Putting answers in some online form. Traditionally, this has been writing, but people are increasing looking to video, especially on YouTube (the world’s second largest search engine), Instagram, and TikTok. This is the easy part.
  2. Getting those answers on the first page of Google results for its search terms or keywords. SEO people love to tell each other this joke: “The best place to hide a body is on the second page of Google results.” This one takes a little more work, and takes into account that no two people get the same Google results for the same search terms.

Level two puts you in demand

On any given week, I get a handful of emails from recruiters, HR people, and the occasional manager with hiring authority asking me if I’d like to leave my current job and go work for them instead. Many of them came in the form of the Dreaded LinkedIn Request:

New Yorker cartoon: Man dying of thirst in the desert runs into man in suit with briefcase who says “Hi, I’d like to add you to my professional network on LinkedIn.”

During last year’s “Great Resignation,” there would be weeks where I’d get one or two dozen such emails and follow-ups. (I’ve turned them down, as my current gig as a Senior Developer Advocate at Okta is pretty sweet.)

Level two gives you an extra portfolio

It’s very helpful to have a portfolio to show to prospective employers, collaborators, co-workers, and customers as proof that you can do what you say you can do.

It’s even better if you have multiple portfolios. You might showcase your work on a site, but also have a Github account where people can look at your work and code. My line of work has also given me a chance to collect media clippings where I’ve appeared or have been quoted, as well as records of my apps in the App Store.

Over the last couple of years, I’ve started a new portfolio: search results for which anything I’ve made is on the first page of Google results. It’s proven handy for my last couple of job searches, as it’s something that other candidates never bring up. It could give you the edge you need!

My “level two” tricks

Image: Screenshots of my articles that are on the first page of Google results for their keywords.

Write an existing answer, but better!

There are nearly 1.2 billion web pages, so there’s a good chance that someone’s written up an answer to a question. But that answer may not be easy to understand, or wrong, or out of date. Someone else might need that answer in another language. Another reader might need that answer, but applicable to a different circumstance. This is an opportunity to write a better answer!

Here are some examples of this kind of answer from my own page one portfolio…

Write the answer that nobody else (or nearly nobody else) is providing.

Eventually, you may get the chance to be one of the first people — if not the first person — to post an answer to a specific question, solution to a specific problem, or exploration of a specific topic. This is an excellent way to establish yourself as knowledgable on a given topic and get on the page one results for that topic.

Whenever you encounter a problem that doesn’t have a solution that you can find via Google and the solve that problem, post your solution to that problem!

Here are some examples of this kind of answer from my own page one portfolio…

Use titles with good keywords.

As far as I know, I’m the only person who posts a regular list of tech, entrepreneur, and nerd events for the Tampa Bay area, and I’ve been doing it every week for five years. In spite of that, I’m missing from page one of the results for this search:

tampa bay tech events

Why? Because until last week, my titles failed to use the right keywords:

Screenshot: My “Tampa Bay Tech Events” article for the week of August 8, 2022.

Since 2017, I’ve used the title What’s happening in the Tampa Bay tech/entrepreneur/nerd scene, which fails to use search terms that people are likely to use, such as event or meetup. I’ll try changing it this week and see what happens.

Make sure that your answers have titles that contain words that people will use when searching for your answer.

Put the answer someplace where it’ll be found.

Your answer needs to be someplace where people look for answers or someplace that Google ranks highly. That makes your answer more likely to be found, which makes people link to it, which in turn makes your answer even more likely to be found.

This blog, Global Nerdy, is my personal tech blog, and I’ve been publishing tech content on it since 2006. This is important, as the Google algorithm factor that matters the most for a site is consistent, high-quality content:

Graph: Pie chart showing factors that affect a web page’s Google ranking. The biggest factor is “consistent publication of high-quality content.”

This blog also focuses on certain aspects of technology and software development, which means that I’ve established myself with niche expertise on a handful of topics. Google also considers this in its site rankings.

While you can publish content on social media, I strongly recommend that you get your own site, as it gives you more control over your content and its format.

Tell people about your answer.

Once you’ve posted your answer, you need to tell people about it to increase its exposure and “findability.” This is where social media and forums come in handy.

Wait.

Getting on the first page of Google results doesn’t happen instantly; it’s the result of steady, consistent content creation. Keep at it, and you’ll build your own page one portfolio!


Try it out — start working on your answers and build your page one portfolio!

Categories
Career

Terminated in 2022: How you know you’ve been invited to a layoff meeting and what to do first

Robinhood is only the latest tech firm to announce layoffs, with their press release saying that they’ll be letting go of nearly a quarter of the firm. Shopify, Netflix, Coinbase, , Tesla, Substack, ByteDance (as in TikTok), OpenSea, Niantic, Unity, and even Crypto.com, whose “Fortune favors the brave” ad with Matt Damon aged like milk, have all laid off a sizable portion of their workforce over the summer.

They won’t be the last in our industry to do some downsizing. Mark Zuckerberg not-so-subtly hinted that there will probably be layoffs as well as pressure on low performers to quit at Meta in a rather ominous way: “Realistically, there are probably a bunch of people at the company who shouldn’t be here.”

With all the layoffs taking place — and many more likely to come — you may be asking yourself this question: How will I know when I’m about to be laid off?

The one sure indicator that you’ve been invited to a layoff meeting

If you get a last-minute invitation to a high-priority meeting with a big or hidden guest list that has a vague name (such as “Special meeting” or something similar), with no agenda and is scheduled near the start of the day, the odds are good that you’re about to be laid off.

The general consensus among HR people whom I’ve talked to on the topic is that layoff meetings should be scheduled with as little advance notice as possible. They’re typically held as early in the day as scheduling and other issues will allow, and preferably not before a weekend or holiday.

Why are layoff meetings announced only at the last minute? It’s to harness the element of surprise, which helps blunt any angry or resentful reaction from employees, and the shock tends to make some people a little more pliant.

Another sign that it’s a layoff meeting

If you see unusual attendees at this last-minute meeting — typically HR people or “The Bobs”, a term referring to the “efficiency experts” from the film Office Space, it’s almost certain that it’s a layoff meeting.

Yet another sign that it’s a layoff meeting

If it’s a video meeting but the organizers have declared it a “camera off / everyone muted but the meeting leader” meeting, it’s probably a layoff meeting.

What to do if you realize that you’ve been invited to a layoff meeting

Do whatever it takes to steel yourself for the bad news. Whether it’s deep breathing, counting to ten, reciting your own personal mantra or firing up your “poker face”, you want to get ready to conduct yourself at the meeting with as much grace, aplomb and professionalism as you can muster.

You’re about to be in the second most important meeting you’ll ever have at this job.

(In case you were wondering, the most important one is the job interview.)

If you work for a decent company, there’ll be one or more follow-up calls, and they’ll be face-to-face. Depending on the size of the company, it might be just your manager or your manager, some other management people, and HR.

No matter what you’re feeling at the meeting, you want your termination to be as good a breakup as possible. This means that you must handle it professionally.

The way you behave at this meeting will set the tone for your departure. If it is full of bitterness, acrimony, and the gnashing of teeth, they won’t be inclined to do you any favors. On the other hand, if you conduct yourself with grace and decorum, you may gain some extra concessions and a willingness on their part to do what they can for you.

If you can remember these questions through the stress of the meeting, you should ask questions like:

  • When is my last day?
  • What is my severance package?
  • How long will my company insurance coverage last?
  • When do I have to return the company laptop and other gear?
  • What arrangements are being made so I can collect my stuff from the office?
  • What do you want me to do with my current projects and files?
  • Can I get a letter of recommendation and use you as a reference?

Don’t worry about memorizing these questions — just remember that you should leave the meeting with a clear idea of what they expect from you and what you can expect from them.

When they send you papers to sign, do not sign them immediately. You’ll be given time to look them over. Don’t look them over just yet.

Walk it off

This is going to sound terribly woo-woo new-agey, but I’m going to say it because it’s an important step: at your first opportunity, get away from whatever you’re doing, get out and go for a walk. Physical activity is a key part of this step, so don’t get into a motorized vehicle. You want to get moving, and you want to do it outside, preferably in your own neighborhood.

The walk is important because it gets you out of the house and gives you a chance to clear your head. It gives you a chance to come down from one of the most stressful experiences you’ll ever face in your working life and come to terms with what’s happened. It is not the time for figuring out what your immediate next steps are; it is the time to collect yourself for figuring out what your next steps are.

Deal with it…non-self-destructively

No matter how good a job you were doing or how well you served the company, and despite the fact that all this is being brought about by a combination of circumstances over which most of us have little control, you’ll feel like this cat:

It will feel as if you had been weighed in the balance and found wanting. In fact, that may have happened. Perhaps you weren’t found wanting as a person or an employee, but when the bean-counters did the books, they did the math and determined that either you went or the company did.

Deal with the shame, using whatever constructive coping mechanisms work best for you. In my case when I was laid off from my previous company in April 2020, I hit the bike, made some lunch, did a little housework, played a little music on the ol’ squeezebox and got involved in some very severe grenade-launcher-assisted altercations in Grand Theft Auto V:

If you must, have a drink or two but don’t go beyond that. You want to take the edge off, not go on a binge.

Network!

Update your LinkedIn — and don’t simply mark the end date of your job:

  • Announce your situation in a post.
  • Update your profile.
  • Reach out to your network.
  • Do the things that get your name in circulation, and let the world know that you’re open to work.

What to do if you weren’t laid off

If you escaped a layoff, the very next thing you should do after celebrating briefly is to follow the advice of Florida’s own “Tommy the Tech Recruiter,” who posted this excellent suggestion on LinkedIn:

If you know someone who is on the job search…

No, no they’re not okay. Especially in these times.
They are tired. Exhausted. Frustrated. Scared.

Each passing day brings a rollercoaster of emotions.
Each rejection or time they never hear anything back leaves them questioning or doubting themselves.

It’s a soul crushing process.

If you are on a job search… I am here for you and making it my mission to help shorten how long that search takes.

And if you see someone who was just laid off or has that green banner, comment on their posts for visibility. Share it. Leave a kind and uplifting comment or send them a DM of support.

We can help each other through this.

Categories
Career Programming

How to solve coding interview questions: Linked lists, part 3

The linked list exercises continue! In case you missed them, be sure to check out part 1 and part 2 of this linked list series before moving forward…

Adding an item to the start of a linked list

In this article, the first new feature we’ll implement is the ability to add new items to the start of the list. It’s similar to adding an item to the end of a list, which is why I reviewed it above.

The diagram below shows the first two nodes of a linked list. Recall that a linked list’s head points to its first node and that every node points to the next one:

Here’s how you add a new node to the start of the list. The new node becomes the first node, and the former first node becomes the second node:

Here are the steps:

  • Create a new node. In our implementation, newly-created nodes have a next property that points to null, nil, or None by default.
  • If the list is empty (i.e. head points to null, nil, or None), adding it to the list is the same thing as adding it to the start of the list. Point head to the new node and you’re done.
  • If the list is not empty, you need to do just a little more work.
    • Point the new node’s next property to head. This makes the current first node the one that comes after the new node.
    • Point head at the new node. This makes the new node the first one in the list.

Here’s how I implemented this in Python…

# Python

def add_first(self, value):
    new_node = Node(value)

    # If the list is empty,
    # point `head` to the newly-added node
    # and exit.
    if self.head is None:
        self.head = new_node
        return

    # If the list isn’t empty,
    # make the current first node the second node
    # and make the new node the first node.
    new_node.next = self.head
    self.head = new_node

…and here’s my JavaScript implementation:

# JavaScript

addFirst(value) {
    let newNode = new Node(value)
    
    // If the list is empty,
    // point `head` to the newly-added node
    // and exit.
    if (this.head === null) {
        this.head = newNode
        return
    }
    
    // If the list isn’t empty,
    // make the current first node the second node
    // and make the new node the first node.
    newNode = this.head
    this.head = newNode
}

Inserting a new item at a specified position in the list

So far, we’ve implemented methods to:

  • Add a new item to the start of the list, and
  • Add a new item to the end of the list.

Let’s do something a little more complicated: adding a new item at a specified position in the list. The position is specified using a number, where 0 denotes the first position in the list.

Here’s how you add a new node at a specified position in the list.

Here are the steps:

  • The function has two parameters:
    1. index: The index where a new node should be inserted into the list, with 0 denoting the first item.
    2. value: The value that should be stored in the new node.
  • Create a new node, new_node, and put value into it.
  • Use a variable, current_index, to keep track of the index of the node we’re currently looking at as we traverse the list. It should initially be set to 0.
  • Use another variable, current_node, which will hold a reference to the node we’re currently looking at. It should initially be set to head, which means that we’ll start at the first item in the list.
  • Repeat the following as long as current_node is not referencing null, nil, or None:
    • We’re looking for the node in the position immediately before the position where we want to insert the new node. If current_index is one less than index:
      • Point the new node at the current node’s next node.
      • Point the current node at the new node.
      • Return true, meaning that we successfully inserted a new item into the list
    • If we’re here, it means that we haven’t yet reached the node immediately before the insertion point. Move to the next node and increment current_index.
  • If we’re here, it means that we’ve gone past the last item in the list. Return false, meaning we didn’t insert a new item into the list.

Here’s how I implemented this in Python…

# Python

def insert_element_at(self, index, value):
    new_node = Node(value)
    current_index = 0
    current_node = self.head

    # Traverse the list, keeping count of 
    # the nodes that you visit,
    # until you’ve reached the specified node.  
    while current_node:
        if current_index == index - 1:
            # We’re at the node before the insertion point!
            # Make the new node point to the next node
            # and the current node point to the new node.
            new_node.next = current_node.next
            current_node.next = new_node
            return True
        
        # We’re not there yet...
        current_node = current_node.next
        current_index += 1
        
    # If you’re here, the given index is larger
    # than the number of elements in the list.
    return False

…and here’s my JavaScript implementation:

// JavaScript

insertElementAt(index, value) {
    let newNode = new Node(value)
    let currentIndex = 0
    let currentNode = this.head
    
    // Traverse the list, keeping count of 
    // the nodes that you visit,
    // until you’ve reached the specified node.     
    while (currentNode) {
        if (currentIndex === index - 1) {
            // We’re at the node before the insertion point!
            // Make the new node point to the next node
            // and the current node point to the new node.
            newNode.next = currentNode.next
            currentNode.next = newNode
            return true
        }
        
        // We’re not there yet...
        currentNode = currentNode.next
        currentIndex++
    }
    
    // If you’re here, the given index is larger
    // than the number of elements in the list.
    return false        
}

Deleting an item from a specified position in the list

Now that we can add a new item at a specified position in the list, let’s implement its opposite: deleting an item from a specified position in the list. Once again, the position is specified using a number, where 0 denotes the first position in the list.

Here’s how you delete a new node from a specified position in the list:

Here are the steps:

  • The function has a single parameter, index: the index of the node to be deleted, with 0 denoting the first item in the list.
  • Use a variable, current_index, to keep track of the index of the node we’re currently looking at as we traverse the list. It should initially be set to 0.
  • Use another variable, current_node, which will hold a reference to the node we’re currently looking at. It should initially be set to head, which means that we’ll start at the first item in the list.
  • Repeat the following as long as current_node is not referencing null, nil, or None:
    • We’re looking for the node in the position immediately before the position of the node we want to delete. If current_index is one less than index:
      • Point the current node to the next node’s next node, which removes the next node from the list.
      • Set both the next node’s data and next properties to null, nil, or None. At this point, this node is no longer in the list and is an “island” — no object points to it, and it doesn’t point to any objects. It will eventually be garbage collected.
      • Return true, meaning that we successfully deleted the item from the list
    • If we’re here, it means that we haven’t yet reached the node immediately before the deletion point. Move to the next node and increment current_index.
  • If we’re here, it means that we’ve gone past the last item in the list. Return false, meaning we didn’t delete the item from the list.

Here’s how I implemented this in Python…

# Python

def delete_element_at(self, index):
    current_index = 0
    current_node = self.head

    # Traverse the list, keeping count of 
    # the nodes that you visit,
    # until you’ve reached the specified node.  
    while current_node:
        if current_index == index - 1:
            # We’re at the node before the node to be deleted!
            # Make the current node point to the next node’s next node
            # and set the next node’s `data` and `next` properties
            # to `None`.
            delete_node = current_node.next
            current_node.next = delete_node.next
            delete_node.data = None
            delete_node.next = None
            return True
        
        # We’re not there yet...
        current_node = current_node.next
        current_index += 1
        
    # If you’re here, the given index is larger
    # than the number of elements in the list.
    return False

…and here’s my JavaScript implementation:

// JavaScript

deleteElementAt(index) {
    let currentIndex = 0
    let currentNode = this.head
    
    // Traverse the list, keeping count of 
    // the nodes that you visit,
    // until you’ve reached the specified node.  
    while (currentNode) {
        if (currentIndex === index - 1) {
            // We’re at the node before the node to be deleted!
            // Make the current node point to the next node’s next node
            // and set the next node’s `data` and `next` properties
            // to `null`.
            const deleteNode = currentNode.next
            currentNode.next = deleteNode.next
            deleteNode.data = null
            deleteNode.next = null
            return true
        }
        
        // We’re not there yet...
        currentNode = currentNode.next
        currentIndex++
    }
    
    // If you’re here, the given index is larger
    // than the number of elements in the list.
    return false  
}

The classes so far

Let’s take a look at the complete Node and LinkedList classes so far, in both Python and JavaScript.

Python

# Python

class Node:
    
    def __init__(self, data):
        self.data = data
        self.next = None
        
    def __str__(self):
        return f"{self.data}"


class LinkedList:
    
    def __init__(self):
        self.head = None
        
    def __str__(self):
        if self.head is None:
            return('Empty list.')
        
        result = ""
        current_node = self.head
        while current_node:
            result += f'{current_node}\n'
            current_node = current_node.next
            
        return result.strip()
    
    def add_last(self, value):
        new_node = Node(value)

        # If the list is empty,
        # point `head` to the newly-added node
        # and exit.
        if self.head is None:
            self.head = new_node
            return
        
        # If the list isn’t empty,
        # traverse the list by going to each node’s
        # `next` node until there isn’t a `next` node...
        current_node = self.head
        while current_node.next:
            current_node = current_node.next
        
        # If you’re here, `current_node` is
        # the last node in the list.
        # Point `current_node` at
        # the newly-added node.
        current_node.next = new_node
        
    def __len__(self):
        count = 0
        current_node = self.head
        
        # Traverse the list, keeping count of 
        # the nodes that you visit,
        # until you’ve gone past the last node.
        while current_node:
            current_node = current_node.next
            count += 1
            
        return count        
        
    def get_element_at(self, index):
        current_index = 0
        current_node = self.head
        
        # Traverse the list, keeping count of 
        # the nodes that you visit,
        # until you’ve reached the specified node.        
        while current_node:
            if current_index == index:
                # We’re at the node at the given index!
                return current_node.data
            
            # We’re not there yet...
            current_node = current_node.next
            current_index += 1
    
        # If you’re here, the given index is larger
        # than the number of elements in the list.
        return None
    
    def set_element_at(self, index, value):
        current_index = 0
        current_node = self.head
        
        # Traverse the list, keeping count of 
        # the nodes that you visit,
        # until you’ve reached the specified node.  
        while current_node:
            if current_index == index:
                # We’re at the node at the given index!
                current_node.data = value
                return True
            
            # We’re not there yet...
            current_node = current_node.next
            current_index += 1
            
        # If you’re here, the given index is larger
        # than the number of elements in the list.
        return False
        
    def add_first(self, value):
        new_node = Node(value)

        # If the list is empty,
        # point `head` to the newly-added node
        # and exit.
        if self.head is None:
            self.head = new_node
            return
        
        # If the list isn’t empty,
        # make the current first node the second node
        # and make the new node the first node.
        new_node.next = self.head
        self.head = new_node
        
    def insert_element_at(self, index, value):
        new_node = Node(value)
        current_index = 0
        current_node = self.head
        
        # Traverse the list, keeping count of 
        # the nodes that you visit,
        # until you’ve reached the specified node.  
        while current_node:
            if current_index == index - 1:
                # We’re at the node before the insertion point!
                # Make the new node point to the next node
                # and the current node point to the new node.
                new_node.next = current_node.next
                current_node.next = new_node
                return True
            
            # We’re not there yet...
            current_node = current_node.next
            current_index += 1
            
        # If you’re here, the given index is larger
        # than the number of elements in the list.
        return False
        
    def delete_element_at(self, index):
        current_index = 0
        current_node = self.head
        
        # Traverse the list, keeping count of 
        # the nodes that you visit,
        # until you’ve reached the specified node.  
        while current_node:
            if current_index == index - 1:
                # We’re at the node before the node to be deleted!
                # Make the current node point to the next node’s next node
                # and set the next node’s `data` and `next` properties
                # to `None`.
                delete_node = current_node.next
                current_node.next = delete_node.next
                delete_node.data = None
                delete_node.next = None
                return True
            
            # We’re not there yet...
            current_node = current_node.next
            current_index += 1
            
        # If you’re here, the given index is larger
        # than the number of elements in the list.
        return False

JavaScript

// JavaScript

class Node {
    
    constructor(data) {
        this.data = data
        this.next = null
    }
    
    toString() {
        return this.data.toString()
    }
    
}


class LinkedList {
    
    constructor() {
        this.head = null
    }
    
    toString() {
        if (!this.head) {
            return('Empty list.')
        }
        
        let output = ""
        let currentNode = this.head

        while (currentNode) {
            output += `${currentNode.data.toString()}\n`
            currentNode = currentNode.next
        }
        
        return output.trim()
    }
    
    addLast(value) {
        let newNode = new Node(value)
        
        // If the list is empty,
        // point `head` to the newly-added node
        // and exit.
        if (this.head === null) {
            this.head = newNode
            return
        }
        
        // If the list isn’t empty,
        // traverse the list by going to each node’s
        // `next` node until there isn’t a `next` node...
        let currentNode = this.head
        while (currentNode.next) {
            currentNode = currentNode.next
        }
        
        // If you’re here, `currentNode` is
        // the last node in the list.
        // Point `currentNode` at
        // the newly-added node.
        currentNode.next = newNode
    }
    
    getCount() {
        let count = 0
        let currentNode = this.head
        
        // Traverse the list, keeping count of 
        // the nodes that you visit,
        // until you’ve gone past the last node.
        while (currentNode) {
            currentNode = currentNode.next
            count++
        }
        
        return count
    }
    
    getElementAt(index) {
        let currentIndex = 0
        let currentNode = this.head
        
        // Traverse the list, keeping count of 
        // the nodes that you visit,
        // until you’ve reached the specified node.     
        while (currentNode) {
            if (currentIndex === index) {
                // We’re at the node at the given index!
                return currentNode.data
            }
            
            // We’re not there yet...
            currentNode = currentNode.next
            currentIndex++
        }
        
        // If you’re here, the given index is larger
        // than the number of elements in the list.
        return null
    }
    
    setElementAt(index, value) {
        let currentIndex = 0
        let currentNode = this.head
        
        // Traverse the list, keeping count of 
        // the nodes that you visit,
        // until you’ve reached the specified node.     
        while (currentNode) {
            if (currentIndex === index) {
                // We’re at the node at the given index!
                currentNode.data = value
                return true
            }
            
            // We’re not there yet...
            currentNode = currentNode.next
            currentIndex++
        }
        
        // If you’re here, the given index is larger
        // than the number of elements in the list.
        return false
    }
    
    addFirst(value) {
        let newNode = new Node(value)
        
        // If the list is empty,
        // point `head` to the newly-added node
        // and exit.
        if (this.head === null) {
            this.head = newNode
            return
        }
        
        // If the list isn’t empty,
        // make the current first node the second node
        // and make the new node the first node.
        newNode = this.head
        this.head = newNode
    }
    
    insertElementAt(index, value) {
        let newNode = new Node(value)
        let currentIndex = 0
        let currentNode = this.head
        
        // Traverse the list, keeping count of 
        // the nodes that you visit,
        // until you’ve reached the specified node.     
        while (currentNode) {
            if (currentIndex === index - 1) {
                // We’re at the node before the insertion point!
                // Make the new node point to the next node
                // and the current node point to the new node.
                newNode.next = currentNode.next
                currentNode.next = newNode
                return true
            }
            
            // We’re not there yet...
            currentNode = currentNode.next
            currentIndex++
        }
        
        // If you’re here, the given index is larger
        // than the number of elements in the list.
        return false        
    }
    
    deleteElementAt(index) {
        let currentIndex = 0
        let currentNode = this.head
        
        // Traverse the list, keeping count of 
        // the nodes that you visit,
        // until you’ve reached the specified node.  
        while (currentNode) {
            if (currentIndex === index - 1) {
                // We’re at the node before the node to be deleted!
                // Make the current node point to the next node’s next node
                // and set the next node’s `data` and `next` properties
                // to `null`.
                const deleteNode = currentNode.next
                currentNode.next = deleteNode.next
                deleteNode.data = null
                deleteNode.next = null
                return true
            }
            
            // We’re not there yet...
            currentNode = currentNode.next
            currentIndex++
        }
        
        // If you’re here, the given index is larger
        // than the number of elements in the list.
        return false  
    }
    
}

Coming up next

It’s time to reverse that list!

Previously in this series

Categories
Career Programming

How to solve coding interview questions: Linked lists, part 2

In case you missed part 1…

Before you continue reading, be sure to check out part 1! It’s where I explain what a linked list is, and provide a couple of basic classes that we’ll build on in this article.

A quick recap

A linked list is a data structure that holds data as a list of items in a specific order. Each item in the list is represented by a node, which “knows” two things:

  • Its data
  • Where the next node is

Here’s a picture of a node’s structure:

A node in a linked list.
Tap to view at full size.

Linked lists are created by connecting nodes together, as shown in the diagram below for a list containing the characters a, b, c, and d in that order:

A linked list of nodes.
Tap to view at full size.

The diagram above features the following:

  • Four nodes, each one for a letter in the list.
  • A variable called head, which is a pointer or reference to the first item in the list. It’s the entry point to the list, and it’s a necessary part of the list — you can’t access a linked list if you can’t access its head.
  • An optional variable called tail, which is a pointer or reference to the last item in the list. It’s not absolutely necessary, but it’s convenient if you use the list like a queue, where the last element in the list is also the last item that was added to the list.

The JavaScript version of the previous article’s code

In the previous article, I provided code for the Node and LinkedList classes in Python. As promised, here are those classes implemented in JavaScript.

// JavaScript

class Node {
    
    constructor(data) {
        this.data = data
        this.next = null
    }
    
    toString() {
        return this.data.toString()
    }
    
}


class LinkedList {
    
    constructor() {
        this.head = null
    }
    
    toString() {
        let output = ""
        let currentNode = this.head

        while (currentNode) {
            output += `${currentNode.data.toString()}\n`
            currentNode = currentNode.next
        }
        
    toString() {
        if (!this.head) {
            return('Empty list.')
        }
        
        let output = ""
        let currentNode = this.head

        while (currentNode) {
            output += `${currentNode.data.toString()}\n`
            currentNode = currentNode.next
        }
        
        return output.trim()
    }
    
    addLast(data) {
        let newNode = new Node(data)
        
        // If the list is empty,
        // point `head` to the newly-added node
        // and exit.
        if (this.head === null) {
            this.head = newNode
            return
        }
        
        // If the list isn’t empty,
        // traverse the list by going to each node’s
        // `next` node until there isn’t a `next` node...
        let currentNode = this.head
        while (currentNode.next) {
            currentNode = currentNode.next
        }
        
        // If you’re here, `currentNode` is
        // the last node in the list.
        // Point `currentNode` at
        // the newly-added node.
        currentNode.next = newNode
    }

}

…where each item in a list is represented by the node. A node knows only about the data it contains and where the next node in the list is.

The JavaScript version of Node and LinkedList uses the same algorithms as the Python version. The Python version follows the snake_case naming convention, while the JavaScript version follows the camelCase convention.

The JavaScript LinkedList class has the following members:

  • head: A property containing a pointer or reference to the first item in the list, or null if the list is empty. This property has the same name in the Python version.
  • constructor(): The class constructor, which initializes head to null, meaning that any newly created LinkedList instance is an empty list. In the Python version, the __init__() method has this role.
  • toString(): Returns a string representation of the contents of the linked list for debugging purposes. If the list contains at least one item, it returns the contents of the list. If the list is empty, it returns the string Empty list. In the Python version, the __str__() method has this role.
  • addLast(): Given a value, it creates a new Node containing that value and adds that Node to the end of the list. In the Python version, the add_last() method has this role.

Adding more functionality to the list

In this article, we’re going to add some much-needed additional functionality to the LinkedList class, namely:

  • Reporting how many elements are in the list
  • Getting the value of the nth item in the list
  • Setting the value of the nth item in the list

I’ll provide both Python and JavaScript implementations.

How many elements are in the list?

To find out how many elements are in a linked list, you have to start at its head and “step through” every item in the list by following each node’s next property, keeping a count of each node you visit. When you reach the last node — the one whose next property is set to None in Python or null in JavaScript — report the number of nodes you counted.

The Python version uses one of its built-in “dunder” (Pythonese for double-underscore) methods, __len__(), to report the number of items in the list. Defining __len__() for LinkedList means that any LinkedList instance will report the number of items it contains when passed as an argument to the built-in len() function. For example, if a LinkedList instance named my_list contains 5 items, len(my_list) returns the value 5.

Here’s the Python version, which you should add to the Python version of LinkedList:

# Python

def __len__(self):
    count = 0
    current_node = self.head
    
    # Traverse the list, keeping count of 
    # the nodes that you visit,
    # until you’ve gone past the last node.
    while current_node:
        current_node = current_node.next
        count += 1
        
    return count    

The JavaScript version is getCount(). If a LinkedList instance named myList contains 5 items, len(myList) returns the value 5.

Here’s the JavaScript version, which you should add to the JavaScript version of LinkedList:

// JavaScript

getCount() {
    let count = 0
    let currentNode = this.head
    
    // Traverse the list, keeping count of 
    // the nodes that you visit,
    // until you’ve gone past the last node.
    while (currentNode) {
        currentNode = currentNode.next
        count++
    }
    
    return count
}

How do I get the data at the nth node in the list?

To get the data at the nth node of the list, you can use an approach that’s similar to the one for counting the list’s elements. You have to start at the head and “step through” every item in the list by following each node’s next property, keeping a count of each node you visit and comparing it against n, where n is the index of the node whose data you want. When the count of nodes you’ve visited is equal to n, report the data contained within the current node.

Here’s the Python version, get_element_at(), which you should add to the Python version of LinkedList:

# Python

def get_element_at(self, index):
    current_index = 0
    current_node = self.head

    # Traverse the list, keeping count of 
    # the nodes that you visit,
    # until you’ve reached the specified node.        
    while current_node:
        if current_index == index:
            # We’re at the node at the given index!
            return current_node.data
        
        # We’re not there yet...
        current_node = current_node.next
        current_index += 1

    # If you’re here, the given index is larger
    # than the number of elements in the list.
    return None

Here’s the JavaScript version, getElementAt(), which you should add to the JavaScript version of LinkedList:

// JavaScript

getElementAt(index) {
    let currentIndex = 0
    let currentNode = this.head
    
    // Traverse the list, keeping count of 
    // the nodes that you visit,
    // until you’ve reached the specified node.     
    while (currentNode) {
        if (currentIndex === index) {
            // We’re at the node at the given index!
            return currentNode.data
        }
        
        // We’re not there yet...
        currentNode = currentNode.next
        currentIndex++
    }
    
    // If you’re here, the given index is larger
    // than the number of elements in the list.
    return null
}

How do I set the value of the nth node in the list?

To set the data at the nth node of the list, you can use an approach that’s similar to the one for getting the data at the nth node. You have to start at the head and “step through” every item in the list by following each node’s next property, keeping a count of each node you visit and comparing it against n, where n is the index of the node whose data you want. When the count of nodes you’ve visited is equal to n, set the current node’s data property to the new value.

Here’s the Python version, set_element_at(), which you should add to the Python version of LinkedList:

# Python

def set_element_at(self, index, value):
    current_index = 0
    current_node = self.head

    # Traverse the list, keeping count of 
    # the nodes that you visit,
    # until you’ve reached the specified node.  
    while current_node:
        if current_index == index:
            # We’re at the node at the given index!
            current_node.data = value
            return True
        
        # We’re not there yet...
        current_node = current_node.next
        current_index += 1
        
    # If you’re here, the given index is larger
    # than the number of elements in the list.
    return False

Here’s the JavaScript version, setElementAt(), which you should add to the JavaScript version of LinkedList:

// JavaScript

setElementAt(index, value) {
    let currentIndex = 0
    let currentNode = this.head
    
    // Traverse the list, keeping count of 
    // the nodes that you visit,
    // until you’ve reached the specified node.     
    while (currentNode) {
        if (currentIndex === index) {
            // We’re at the node at the given index!
            currentNode.data = value
            return true
        }
        
        // We’re not there yet...
        currentNode = currentNode.next
        currentIndex++
    }
    
    // If you’re here, the given index is larger
    // than the number of elements in the list.
    return false
}

The classes so far

Let’s take a look at the complete Node and LinkedList classes so far, in both Python and JavaScript.

Python

# Python

class Node:
    
    def __init__(self, data):
        self.data = data
        self.next = None
        
    def __str__(self):
        return f"{self.data}"


class LinkedList:
    
    def __init__(self):
        self.head = None
        
    def __str__(self):
        if self.head is None:
            return('Empty list.')
        
        result = ""
        current_node = self.head
        while current_node:
            result += f'{current_node}\n'
            current_node = current_node.next
            
        return result.strip()
    
    def add_last(self, value):
        new_node = Node(value)

        # If the list is empty,
        # point `head` to the newly-added node
        # and exit.
        if self.head is None:
            self.head = new_node
            return
        
        # If the list isn’t empty,
        # traverse the list by going to each node’s
        # `next` node until there isn’t a `next` node...
        current_node = self.head
        while current_node.next:
            current_node = current_node.next
        
        # If you’re here, `current_node` is
        # the last node in the list.
        # Point `current_node` at
        # the newly-added node.
        current_node.next = new_node
        
    def __len__(self):
        count = 0
        current_node = self.head
        
        # Traverse the list, keeping count of 
        # the nodes that you visit,
        # until you’ve gone past the last node.
        while current_node:
            current_node = current_node.next
            count += 1
            
        return count        
        
    def get_element_at(self, index):
        current_index = 0
        current_node = self.head
        
        # Traverse the list, keeping count of 
        # the nodes that you visit,
        # until you’ve reached the specified node.        
        while current_node:
            if current_index == index:
                # We’re at the node at the given index!
                return current_node.data
            
            # We’re not there yet...
            current_node = current_node.next
            current_index += 1
    
        # If you’re here, the given index is larger
        # than the number of elements in the list.
        return None
    
    def set_element_at(self, index, value):
        current_index = 0
        current_node = self.head
        
        # Traverse the list, keeping count of 
        # the nodes that you visit,
        # until you’ve reached the specified node.  
        while current_node:
            if current_index == index:
                # We’re at the node at the given index!
                current_node.data = value
                return True
            
            # We’re not there yet...
            current_node = current_node.next
            current_index += 1
            
        # If you’re here, the given index is larger
        # than the number of elements in the list.
        return False

JavaScript

// JavaScript

class Node {
    
    constructor(data) {
        this.data = data
        this.next = null
    }
    
    toString() {
        return this.data.toString()
    }
    
}


class LinkedList {
    
    constructor() {
        this.head = null
    }
    
    toString() {
        if (!this.head) {
            return('Empty list.')
        }
        
        let output = ""
        let currentNode = this.head

        while (currentNode) {
            output += `${currentNode.data.toString()}\n`
            currentNode = currentNode.next
        }
        
        return output.trim()
    }
    
    addLast(value) {
        let newNode = new Node(value)
        
        // If the list is empty,
        // point `head` to the newly-added node
        // and exit.
        if (this.head === null) {
            this.head = newNode
            return
        }
        
        // If the list isn’t empty,
        // traverse the list by going to each node’s
        // `next` node until there isn’t a `next` node...
        let currentNode = this.head
        while (currentNode.next) {
            currentNode = currentNode.next
        }
        
        // If you’re here, `currentNode` is
        // the last node in the list.
        // Point `currentNode` at
        // the newly-added node.
        currentNode.next = newNode
    }
    
    getCount() {
        let count = 0
        let currentNode = this.head
        
        // Traverse the list, keeping count of 
        // the nodes that you visit,
        // until you’ve gone past the last node.
        while (currentNode) {
            currentNode = currentNode.next
            count++
        }
        
        return count
    }
    
    getElementAt(index) {
        let currentIndex = 0
        let currentNode = this.head
        
        // Traverse the list, keeping count of 
        // the nodes that you visit,
        // until you’ve reached the specified node.     
        while (currentNode) {
            if (currentIndex === index) {
                // We’re at the node at the given index!
                return currentNode.data
            }
            
            // We’re not there yet...
            currentNode = currentNode.next
            currentIndex++
        }
        
        // If you’re here, the given index is larger
        // than the number of elements in the list.
        return null
    }
    
    setElementAt(index, value) {
        let currentIndex = 0
        let currentNode = this.head
        
        // Traverse the list, keeping count of 
        // the nodes that you visit,
        // until you’ve reached the specified node.     
        while (currentNode) {
            if (currentIndex === index) {
                // We’re at the node at the given index!
                currentNode.data = value
                return true
            }
            
            // We’re not there yet...
            currentNode = currentNode.next
            currentIndex++
        }
        
        // If you’re here, the given index is larger
        // than the number of elements in the list.
        return false
    }

}

Wait…this “linked list” thing is beginning to look like a Python or JavaScript array, but not as fully-featured. What’s going on here?

The truth about linked lists

Here’s the truth: there’s a better-than-even chance that you’ll never use them…directly.

If you program in most languages from the 1990s or later (for example, Python was first released in 1991, PHP’s from 1994, Java and JavaScript came out in 1995), you’re working with arrays — or in Python’s case, lists, which are almost the same thing — that you can you can add elements to, remove elements from, perform searches on, and do all sorts of things with.

When you use one of these data types in a modern language…

  • Python lists or a JavaScript arrays
  • Dictionaries, also known as objects in JavaScript, hashes in Ruby, or associative arrays
  • Stacks and queues
  • React components

…there’s a linked list behind the scenes, moving data around by traversing, adding, and deleting nodes. There’s a pretty good chance that you’re indirectly using linked lists in your day-to-day programming; you’re just insulated from the details by layers of abstractions.

So why do they still pose linked list challenges in coding interviews?

History plays a major factor.

In older languages like FORTRAN (1957), Pascal (1970), and C (1972), arrays weren’t dynamic, but fixed in size. If you declared an array with 20 elements, it remained a 20-element array. You couldn’t add or remove elements at run-time.

But Pascal and C supported pointers from the beginning, and pointers make it possible to create dynamic data structures — the kind where you can add or delete elements at run-time. In those early pre-web days, when programming languages’ standard libraries weren’t as rich and complete as today’s, and you often had to “roll your own” dynamic data structures, such as trees, queues, stacks, and…linked lists.

If you majored in computer science in the ’70s, ’80s, and even the ’90s, you were expected to know how to build your own dynamic data structures from scratch, and they most definitely appeared on the exam. These computer science majors ended up in charge at tech companies, and they expected the people they hired to know this stuff as well. Over time, it became tradition, and to this day, you’ll still get the occasional linked list question in a coding interview.

What’s the point in learning about linked lists when we’re mostly insulated from having to work with them directly?

For starters, there’s just plain old pragmatism. As long as they’re still asking linked list questions in coding interviews, it’s a good idea to get comfortable with them and be prepared to answer all manner of questions about algorithms and data structures.

Secondly, it’s a good way to get better at the kind of problem solving that we need in day-to-day programming. Working with linked lists requires us to think about pointers/references, space and time efficiency, tradeoffs, and even writing readable, maintainable code. And of course, there’s always a chance that you might have to implement a linked list yourself, whether because you’re working on an IoT or embedded programming project with a low-level language like C or implementing something lower-level such as the reconciler in React.

Coming up next

  • Adding a new element to the head of a linked list
  • Adding a new element at a specific place in the middle of a linked list
  • Deleting a specified element of a linked list

Previously in this series

Categories
Career Programming

How to solve coding interview questions: Linked lists, part 1

Programmer Humor, How, and Coding: Me: I can't wait for my first coding
 interview!
 The interviewer:
 I'm about to end this man's whole career
That’s how it works
Okay, maybe coding interviews aren’t that bad.
But they’re close!

If you’re interviewing for a position that requires you to code, the odds are pretty good that you’ll have to face a coding interview. This series of articles is here to help you gain the necessary knowledge and skills to tackle them!

Over the next couple of articles in this series, I’ll walk you through a classic computer science staple: linked lists. And by the end of these articles, you’ll be able to handle this most clichéd of coding interview problems, satirized in the meme below:

r/ProgrammerHumor - Reverse it right now

You’ve probably seen the ads for AlgoExpert with the woman pictured above, where she asks you if you want a job at Google and if you know how to reverse a linked list.

But before you learn about reversing linked lists — or doing anything else with them — let’s first answer an important question: what are they?

What are linked lists?

A linked list is a data structure that holds data as a list of items in a specific order. Linked lists are simple and flexible, which is why they’re the basis of many of the data structures that you’ll probably use in your day-to-day programming.

Linked list basics

Nodes

The basic component of a linked list is a node, which is diagrammed below:

A node in a linked list.
Tap to view at full size.

In its simplest form, a node is a data structure that holds two pieces of information:

  • data: This holds the actual data of the list item. For example, if the linked list is a to-do list, the data could be a string representing a task, such as “clean the bathroom.”
  • next: A linked list is simply a set of nodes that are linked together. In addition to the data it holds, a node should also know where the next node is, and that’s what its next property is for: it points to the next item in the list. In languages like C and Go, this would be a pointer, while in languages like C#, Java, JavaScript, Kotlin, Python, and Swift, this would be a reference.

Here’s a Python implementation of a node. We’ll use it to implement a linked list:

# Python

class Node:
    
    def __init__(self, data):
        self.data = data
        self.next = None
        
    def __str__(self):
        return f"{self.data}"

With Node defined, you can create a new node containing the data “Hello, world!” with this line of code:

new_node = Node("Hello, world!")

To print the data contained inside a node, call Node’s print() method, which in turn uses the value returned by its __str__() method:

print(new_node)
# Outputs “Hello, world!”

Assembling nodes into a linked list

You create a linked list by connecting nodes together using their next properties. For example, the linked list in the diagram below represents a list of the first four letters of the alphabet: a, b, c, and d, in that order:

A linked list of nodes.
Tap to view at full size.

The diagram above features the following:

  • Four nodes, each one for a letter in the list.
  • A variable called head, which is a pointer or reference to the first item in the list. It’s the entry point to the list, and it’s a necessary part of the list — you can’t access a linked list if you can’t access its head.
  • An optional variable called tail, which is a pointer or reference to the last item in the list. It’s not absolutely necessary, but it’s convenient if you use the list like a queue, where the last element in the list is also the last item that was added to the list.

Let’s build the linked list pictured above by putting some nodes together:

# Python

# Let’s build this linked list:
# a -> b -> c -> d

head = Node("a")
head.next = Node("b")
head.next.next = Node("c")
head.next.next.next = Node("d")

That’s a lot of nexts. Don’t worry; we’ll come up with a better way of adding items to a linked list soon.

Here’s an implementation that creates the same list but doesn’t rely on chaining nexts:

# Python

# Another way to build this linked list:
# a -> b -> c -> d

head = Node("a")

node_b = Node("b")
head.next = node_b

node_c = Node("c")
node_b.next = node_c

node_d = Node("d")
node_c.next = node_d

To see the contents of the list, you traverse it by visiting each node. This is possible because each node points to the next one in the list:

# Python

print(head)
print(head.next)
print(head.next.next)
print(head.next.next.next)
print(head.next.next.next.next)

Here’s the output for the code above:

a
b
c
d
None

Of course, the code above becomes impractical if you don’t know how many items are in the list or as the list grows in size.

Fortunately, the repetition in the code — all those prints and nexts — suggests that we can use a loop to get the same result:

# Python

current = head

while current is not None:
    print(current)
    current = current.next

Here’s the output for the code above:

a
b
c
d

A linked list class

Working only with nodes is a little cumbersome. Let’s put together a linked list class that makes use of the Node class:

# Python

class LinkedList:
    
    def __init__(self):
        self.head = None
        
    def __str__(self):
        if self.head is None:
            return('Empty list.')
        
        result = ""
        current_node = self.head
        while current_node is not None:
            result += f'{current_node}\n'
            current_node = current_node.next
        return result.strip()
    
    def add_last(self, data):
        new_node = Node(data)

        # If the list is empty,
        # point `head` to the newly-added node
        # and exit.
        if self.head is None:
            self.head = new_node
            return
        
        # If the list isn’t empty,
        # traverse the list by going to each node’s
        # `next` node until there isn’t a `next` node...
        current_node = self.head
        while current_node.next:
            current_node = current_node.next
        
        # If you’re here, `current_node` is
        # the last node in the list.
        # Point `current_node` at
        # the newly-added node.
        current_node.next = new_node

This LinkedList class has the following members:

  • head: A property containing a pointer or reference to the first item in the list, or None if the list is empty.
  • __init__(): The class initializer, which initializes head to None, meaning that any newly created LinkedList instance is an empty list.
  • __str__(): Returns a string representation of the contents of the linked list for debugging purposes. If the list contains at least one item, it returns the contents of the list. If the list is empty, it returns the string Empty list.
  • add_last(): Given a value, it creates a new Node containing that value and adds that Node to the end of the list.

With this class defined, building a new list requires considerably less typing…

# Python

list = LinkedList()
list.add_last("a")
list.add_last("b")
list.add_last("c")
list.add_last("d")

…and displaying its contents is reduced to a single function call, print(list), which produces this output:

a
b
c
d

Coming up next:

  • JavaScript implementations
  • Adding an item to the start of a linked list
  • Finding an item in a linked list
  • Will you ever use a linked list, and why do they ask linked list questions in coding interviews?

Previously in this series

Categories
Career Programming

How to solve coding interview questions: Finding the first NON-recurring character in a string in Swift

This reminds me of what happened in my worst interview.

In previous posts, I’ve presented Python, JavaScript, and TypeScript solutions for the coding interview challenge: “Write a function that returns the first NON-recurring character in a given string.” In this post, I’ll show you my solution in Swift.

Here’s a table that provides some sample input and corresponding expected output for this function:

If you give the function this input……it should produce this output:
aabbbXccddX
a🤣abbbXcc3dd🤣
aabbccddnull / None / nil

The algorithm

I’ve been using an algorithm that takes on the problem in two stages:

In the first stage, the function steps through the input string one character at a time, counting the number of times each character in the string appears in a “character record”. Because we’re looking for the first non-recurring character in the input string, the order in which data is stored in the character record is important. It needs to maintain insertion order — that is, the order of the character record must be the same order in which each unique character in the input string first appears.

For example, given the input string aabbbXccdd, the function should build a character record that looks like this:

CharacterCount
a2
b3
X1
c2
d2

Given the input string a🤣abbbXcc3dd, it should build a character record that looks like this:

CharacterCount
a2
🤣1
b3
X1
c2
31
d2

Given the input string aabbccdd, it should build a character record that looks like this:

CharacterCount
a2
b2
c2
d2

Once the function has built the character record, it’s time to move to the second stage, where it iterates through the character record in search of a character with a count of 1, and:

  • If the function finds such a character, it exits the function at the first such occurrence, returning that character. For the input string aabbbXccdd, it returns X, and for the input string a🤣abbbXcc3dd, it returns 🤣.
  • If the function doesn’t find any characters with a count of 1, it exits the function, having gone through every character in the character record, returning a null value (which in the case of Swift is nil).

Using a Swift OrderedDictionary

The character record is the key to making the algorithm work, and the key to the character record is that must be an ordered collection. If I add a, b, and c to the character record, it must maintain the order a, b, c.

This isn’t a problem in Python. While Python dictionaries have traditionally been unordered, as of Python 3.7, dictionaries maintain insertion order. In the previous articles covering this coding interview question, my Python solutions used a regular Python dictionary.

Because JavaScript runs in so many places in so many versions, I decided not to trust that everyone would be running a later version, which preserves insertion order. In the previous article, I wrote a JavaScript solution that implemented the character record using Map, a key-value data structure that keeps the items stored in the order in which they were inserted.

Swift’s built-in Dictionary does not keep the items in any defined order. Luckily, the Swift Collections package provides OrderedDictionary, which gives us both key-value storage and insertion order.

You’ll need to add Swift Collections to your project in order to use it. To do this, select FileAdd Packages…

The dialog box for adding packages will appear:

Do the following:

  • Enter swift-collections into the search field.
  • Select swift-collections from the package list.
  • Click Add Package.

You’ll be presented with a list of products within the Swift Collections package:

For this exercise, you’ll need only OrderedCollections, so check its box and click Add Package, which will add the package to your project.

Implementing the solution

Now we can implement the solution!

// We need this for `OrderedDictionary` 
import OrderedCollections

func firstNonRecurringCharacter(text: String) -> String? {
  var characterRecord = OrderedDictionary<Character, Int>()
   
  for character in text {
    if characterRecord.keys.contains(character) {
      characterRecord[character]! += 1
    } else {
      characterRecord[character] = 1
    }
  }
  
  for character in characterRecord.keys {
    if characterRecord[character] == 1 {
      return String(character)
    }
  }
 
  return nil
}

characterRecord, which keeps track of the characters encountered as we go character by character through the input string, is an OrderedDictionary. Note that with Swift, which is both statically and strongly typed, we need to specify that characterRecord’s keys are of type Character and its values are Ints.

After that, the implementation’s similar to my Python and JavaScript versions.

Previously in this series