Neetcode 150

Neetcode 150

Neetcode 150 is a collection of 150 coding problems for software engineers and developers to practice their coding skills. The problems are carefully selected to cover a wide range of topics and difficulty levels, making it an ideal resource for interview preparation and skill development.

  1. Problem 1: Duplicate Integer

Description

Examples

Example 1:

Example 2:

Hints / Notes:

  1. Brute Force
  1. Hash Set
  1. Sorting
  1. Pythonic Solution

Solution

# Pythonic Solution
def containsDuplicate(nums):
    return len(nums) != len(set(nums))
 
# Sorting
def containsDuplicate(nums):
    nums.sort()
    for i in range(1, len(nums)):
        if nums[i] == nums[i - 1]:
            return True
    return False
 
# Hash Set
def containsDuplicate(nums):
    seen = set()
    for num in nums:
        if num in seen:
            return True
        seen.add(num)
    return False
 
# Brute Force
def containsDuplicate(nums):
    for i in range(len(nums)):
        for j in range(i + 1, len(nums)):
            if nums[i] == nums[j]:
                return True
    return False

Complexity Analysis

  1. Is Anagram

Description

Given two strings s and t, return true if the two strings are anagrams of each other, otherwise return false. An anagram is a string that contains the exact same characters as another string, but the order of the characters can be different.

Examples

Example 1:

Example 2:

Hints / Notes:

  1. Sorting
  1. Hash Map
  1. Pythonic Solution

Solution

# Pythonic Solution
from collections import Counter
 
def isAnagram(s, t):
    return Counter(s) == Counter(t)
 
# Hash Map
def isAnagram(s, t):
    if len(s) != len(t):
        return False
    freq_s = {}
    freq_t = {}
    for char in s:
        freq_s[char] = freq_s.get(char, 0) + 1
    for char in t:
        freq_t[char] = freq_t.get(char, 0) + 1
    return freq_s == freq_t
 
# Sorting
def isAnagram(s, t):
    return sorted(s) == sorted(t)

Complexity Analysis

  1. Two Integer Sum

Description

Given an array of integers nums and an integer target, return the indices i and j such that nums[i] + nums[j] == target and i != j.

You may assume that every input has exactly one pair of indices i and j that satisfy the condition.

Return the answer with the smaller index first.

Examples

Example 1:

Example 2:

Hints / Notes:

  1. Brute Force
  1. Hash Map
  1. Sorting

Solution

# Hash Map
def twoSum(nums, target):
    num_to_index = {}
    for i, num in enumerate(nums):
        complement = target - num
        if complement in num_to_index:
            return [num_to_index[complement], i]
        num_to_index[num] = i
 
# Brute Force
def twoSum(nums, target):
    for i in range(len(nums)):
        for j in range(i + 1, len(nums)):
            if nums[i] + nums[j] == target:
                return [i, j]

Complexity Analysis

  1. Anagram Groups

Description

Given an array of strings strs, group the anagrams together. You can return the answer in any order.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

Examples

Example 1:

Example 2:

Hints / Notes:

  1. Hash Map and Sorting
  1. Pythonic Solution
  1. Hash Map and Character Count

Solution

# Hash Map and Sorting
def groupAnagrams(strs):
    anagrams = {}
    for s in strs:
        key = tuple(sorted(s))
        if key in anagrams:
            anagrams[key].append(s)
        else:
            anagrams[key] = [s]
    return list(anagrams.values())
 
# Pythonic Solution
from collections import defaultdict
 
def groupAnagrams(strs):
    anagrams = defaultdict(list)
    for s in strs:
        anagrams[tuple(sorted(s))].append(s)
    return list(anagrams.values())
 
# Hash Map and Character Count
def groupAnagrams(strs):
    anagrams = {}
    for s in strs:
        count = [0] * 26
        for char in s:
            count[ord(char) - ord('a')] += 1
        key = tuple(count)
        if key in anagrams:
            anagrams[key].append(s)
        else:
            anagrams[key] = [s]
    return list(anagrams.values())

Complexity Analysis

  1. Top k Elements in list

Description

Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.

Examples

Example 1:

Example 2:

Hints / Notes:

  1. Hash Map and Sorting
  1. Min Heap
  1. Bucket Sort

Solution

# Hash Map and Sorting
def topKFrequent(nums, k):
    freq = {}
    for num in nums:
        freq[num] = freq.get(num, 0) + 1
    sorted_freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
    return [x[0] for x in sorted_freq[:k]]
 
 
# Min Heap
import heapq
 
def topKFrequent(nums, k):
    freq = {}
    for num in nums:
        freq[num] = freq.get(num, 0) + 1
    min_heap = []
 
    for num, count in freq.items():
        heapq.heappush(min_heap, (count, num))
        if len(min_heap) > k:
            heapq.heappop(min_heap)
    return [num for count, num in min_heap]
 
# Bucket Sort
from collections import Counter
 
def topKFrequent(nums, k):
    freq = Counter(nums)
    buckets = [[] for _ in range(len(nums) + 1)]
    for num, count in freq.items():
        buckets[count].append(num)
    result = []
    for i in range(len(buckets) - 1, -1, -1):
        result.extend(buckets[i])
        if len(result) >= k:
            return result[:k]

Complexity Analysis

  1. String Encode and Decode

Description

Design an algorithm to encode a list of strings to a string and decode it back to the original list of strings.

Examples

Example 1:

Hints / Notes:

  1. Custom Separator
  1. Length Prefix

Solution

# Custom Separator
def encode(strs):
    encoded = ""
    for s in strs:
        encoded += str(len(s)) + "#" + s
    return encoded
 
def decode(s):
    decoded = []
    i = 0
    while i < len(s):
        j = i
        while s[j] != "#":
            j += 1
        length = int(s[i:j])
        decoded.append(s[j + 1:j + 1 + length])
        i = j + 1 + length
    return decoded
 
# Length Prefix
def encode(strs):
    encoded = ""
    for s in strs:
        encoded += str(len(s)) + "#" + s
    return encoded
 
def decode(s):
    decoded = []
    i = 0       
    while i < len(s):
        j = i
        while s[j] != "#":
            j += 1
        length = int(s[i:j])
        decoded.append(s[j + 1:j + 1 + length])
        i = j + 1 + length
    return decoded

Complexity Analysis

  1. Product of Array Except Self

Description

Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].

The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

You must write an algorithm that runs in O(n) time and without using the division operation.

Examples

Example 1:

Example 2:

Hints / Notes:

  1. Prefix and Suffix Products
  1. Single Array

Solution

# Prefix and Suffix Products
def productExceptSelf(nums):
    n = len(nums)
    prefix = [1] * n
    suffix = [1] * n
 
    for i in range(1, n):
        prefix[i] = prefix[i - 1] * nums[i - 1]
        suffix[n - i - 1] = suffix[n - i] * nums[n - i]
    
    return [prefix[i] * suffix[i] for i in range(n)]
 
# Single Array
def productExceptSelf(nums):
    n = len(nums)
    result = [1] * n
    prefix = 1
    suffix = 1
 
    for i in range(n):
        result[i] *= prefix
        prefix *= nums[i]
        result[n - i - 1] *= suffix
        suffix *= nums[n - i - 1]
 
    return result

Complexity Analysis

MIT © Archit Rathod.