<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Viraj Mavani</title>
    <description>Viraj Mavani&apos;s Portfolio and Blog</description>
    <link>https://virajmavani.com/</link>
    <atom:link href="https://virajmavani.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 25 Feb 2026 19:00:41 +0000</pubDate>
    <lastBuildDate>Wed, 25 Feb 2026 19:00:41 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>The Engineering Behind Serving LLMs at Scale</title>
        <description>&lt;p&gt;Training a large language model gets most of the attention. But if you’ve ever tried to serve one in production — handling real traffic, real latency requirements, and real cost constraints — you know that inference is where most of the hard engineering lives. Over the past couple of years, researchers and systems engineers have made remarkable progress in closing the gap between what these models can do and what it actually costs to run them. Having worked on large-scale distributed systems and followed the ML research space closely, I find this intersection of systems thinking and machine learning to be one of the most exciting areas in software engineering right now.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-core-problem-autoregressive-generation-is-sequential&quot;&gt;The Core Problem: Autoregressive Generation is Sequential&lt;/h2&gt;

&lt;p&gt;To understand why LLM serving is hard, you need to understand how text generation works. Models generate tokens one at a time, where each new token depends on all the tokens that came before it. This autoregressive nature means you can’t trivially parallelize generation across a single sequence the way you can parallelize training across samples in a batch.&lt;/p&gt;

&lt;p&gt;This creates two distinct phases with very different compute profiles:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Prefill:&lt;/strong&gt; Processing the entire input prompt in parallel. This is compute-bound and GPU-efficient.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Decode:&lt;/strong&gt; Generating output tokens one by one. This is memory-bandwidth-bound and notoriously GPU-inefficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  PREFILL (parallel, compute-bound)         DECODE (sequential, memory-bound)
  ┌────────────────────────────────┐
  │  [P1]  [P2]  [P3]  [P4]  [P5] │──▶  [T1] ──▶ [T2] ──▶ [T3] ──▶ ...
  │   all prompt tokens at once    │      one new token generated per step
  └────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Naively serving requests — waiting for one to finish before starting the next — wastes enormous amounts of GPU capacity. The challenge is to keep the GPU busy without sacrificing latency.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;continuous-batching&quot;&gt;Continuous Batching&lt;/h2&gt;

&lt;p&gt;The first major insight is that you don’t need to wait for an entire batch to finish before admitting new requests. Traditional static batching holds a fixed set of requests together until all of them complete. Since requests have wildly different output lengths, this means fast requests sit idle waiting for slow ones.&lt;/p&gt;

&lt;p&gt;Continuous batching — also called in-flight batching — solves this by treating generation as a stream of iterations. At each step, finished sequences are immediately evicted from the batch and new requests are slotted in. The GPU is kept continuously busy, and short requests don’t pay a penalty for being grouped with long ones. This single change dramatically improves throughput and is now standard in production inference engines.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Static Batching:
  Step:    1    2    3    4    5    6
  Slot A: [████████][  idle  ][  idle  ]   ← done early, slot wasted
  Slot B: [████████████████████████████]
  Slot C: [████████████████][  idle   ]    ← done mid-way, slot wasted

Continuous Batching:
  Step:    1    2    3    4    5    6
  Slot A: [████████][  Req D ████████ ]   ← D admitted immediately
  Slot B: [████████████████████████████]
  Slot C: [████████████████][  Req E  ]   ← E admitted immediately
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;pagedattention-and-kv-cache-management&quot;&gt;PagedAttention and KV Cache Management&lt;/h2&gt;

&lt;p&gt;Every token the model has seen needs to be stored in a key-value (KV) cache so that attention can be computed efficiently on subsequent steps. For long sequences or large batches, this cache becomes the dominant consumer of GPU memory — and the way it’s managed determines how many requests you can serve concurrently.&lt;/p&gt;

&lt;p&gt;The naive approach allocates a contiguous block of memory for each request upfront, sized for the maximum possible sequence length. This leads to severe fragmentation: memory is reserved but unused, and the system can serve far fewer concurrent requests than the hardware should theoretically allow.&lt;/p&gt;

&lt;p&gt;PagedAttention, introduced with vLLM, borrows an idea from OS virtual memory. Instead of contiguous allocation, it partitions the KV cache into fixed-size blocks that can be stored non-contiguously and fetched via a block table during attention computation. Requests share physical memory pages when their prefixes are identical — common in applications where many users share the same system prompt. The result is dramatically higher memory utilization and, consequently, much larger effective batch sizes.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Naive (contiguous pre-allocation):        PagedAttention (non-contiguous blocks):

┌──────────────────────────┐             Physical memory:
│ Req A  [████████░░░░░░░░]│             ┌──────┬──────┬──────┬──────┬──────┐
├──────────────────────────┤             │ A[0] │ B[0] │ A[1] │ C[0] │ B[1] │
│ Req B  [█████░░░░░░░░░░░]│             ├──────┼──────┼──────┼──────┼──────┤
├──────────────────────────┤             │ A[2] │ free │ C[1] │ free │ free │
│ Req C  [██░░░░░░░░░░░░░░]│             └──────┴──────┴──────┴──────┴──────┘
└──────────────────────────┘
  ░ = reserved but unused memory           Block table maps logical → physical
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;speculative-decoding&quot;&gt;Speculative Decoding&lt;/h2&gt;

&lt;p&gt;The decode phase is memory-bandwidth-bound: the GPU spends most of its time loading model weights for each token, not doing useful compute. Speculative decoding exploits this headroom.&lt;/p&gt;

&lt;p&gt;The idea is to use a small, fast draft model to speculatively generate several candidate tokens ahead of the main model. The large model then verifies all candidates in a single forward pass — taking advantage of the fact that verification is parallelizable even if generation is not. If the large model agrees with the draft, all tokens are accepted; if it disagrees at some point, generation falls back from that position.&lt;/p&gt;

&lt;p&gt;When speculative decoding works well — which depends on the draft model’s ability to predict what the larger model would generate — it can reduce end-to-end latency significantly without sacrificing output quality. Recent work like Nightjar has pushed this further by dynamically selecting the speculative window length based on real-time batch conditions, achieving up to 20% lower latency compared to static speculative decoding.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Without Speculative Decoding:
  Large Model: ──[T1]──[T2]──[T3]──[T4]──▶   (4 serial forward passes)

With Speculative Decoding:
  Draft Model: ──[d1]──[d2]──[d3]──[d4]──▶   (4 fast serial passes)
                  │     │     │     │
  Large Model: ──[  verify d1, d2, d3, d4  ]──▶   (1 parallel forward pass)
                       ✓     ✓     ✗
                                   └─▶ reject d3, d4 → regenerate from d3

  Net result: 2 accepted tokens from 1 large model pass instead of 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-this-matters-beyond-llms&quot;&gt;Why This Matters Beyond LLMs&lt;/h2&gt;

&lt;p&gt;What I find intellectually satisfying about this space is that none of these ideas are entirely new. Continuous batching is a scheduling problem. PagedAttention is virtual memory. Speculative execution has been in CPUs for decades. What’s happened is that the scale and economics of LLM deployment have made it worth rigorously applying classical systems thinking to a new domain.&lt;/p&gt;

&lt;p&gt;The engineers who will do the most interesting work at this intersection aren’t those who know only one side — they’re the ones who understand both the model and the system it runs on. That’s a skill set worth building.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Later.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 25 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/software/2026/02/25/LLM-Inference-at-Scale.html</link>
        <guid isPermaLink="true">https://virajmavani.com/software/2026/02/25/LLM-Inference-at-Scale.html</guid>
        
        <category>software engineering</category>
        
        <category>distributed systems</category>
        
        <category>AI</category>
        
        <category>machine learning</category>
        
        <category>system design</category>
        
        <category>LLM</category>
        
        
        <category>Software</category>
        
      </item>
    
      <item>
        <title>The Framework Dilemma: Are Frameworks the Death of Software Engineering?</title>
        <description>&lt;p&gt;In the ever-evolving landscape of software development, the role of frameworks has become increasingly prominent. We’ve all heard it before — developers proudly declaring themselves as “React Developers,” “Django Developers,” or “Spring Developers.” While there’s nothing inherently wrong with specializing in a particular framework, I believe that excessive framework reliance can hinder the growth of software engineering as a whole.&lt;/p&gt;

&lt;p&gt;Let me clarify; I don’t mean to paint all framework enthusiasts with a broad brush. There are certainly skilled engineers among them who understand the core principles of software development. However, my observations have led me to believe that too many developers are falling into the trap of focusing solely on their chosen framework, neglecting the broader knowledge base that makes a well-rounded engineer.&lt;/p&gt;

&lt;p&gt;One of the primary culprits behind this phenomenon is the influence of certain experienced engineers who champion their preferred frameworks as if they were divine creations. It’s perfectly acceptable to have strong opinions, but it’s detrimental not to remain open to change. This tunnel vision has resulted in an overabundance of job listings seeking candidates with expertise in specific frameworks, perpetuating the framework-centric mindset.&lt;/p&gt;

&lt;p&gt;Frameworks, once introduced, tend to stick around, even in modified forms. They establish practices that endure for generations. I don’t harbor any ill will toward frameworks; they serve an invaluable purpose by expediting development, enhancing maintainability, and facilitating collaboration in teams. Each framework has its unique strengths and “flavor.” However, we must not lose sight of the bigger picture.&lt;/p&gt;

&lt;p&gt;As my mentor used to emphasize, a true software engineer isn’t merely someone who churns out code or develops features in large-scale systems. A genuine software engineer is one who identifies and effectively solves problems. Frameworks, while providing structure and efficiency, can inadvertently stifle creative thinking. They impose a predefined structure on thought, potentially becoming shackles for the free thinker.&lt;/p&gt;

&lt;p&gt;Historically, the most significant leaps in software development have been made by creating new frameworks rather than relying solely on existing ones. These groundbreaking solutions generated substantial value for their respective businesses.&lt;/p&gt;

&lt;p&gt;In conclusion, frameworks have their place and are invaluable tools in the software developer’s arsenal. However, they should not overshadow the importance of developing a well-rounded skill set and embracing a broader perspective. Instead of pigeonholing ourselves into specific frameworks, let’s strive to be true engineers who understand, identify, and genuinely solve problems. In doing so, we can ensure that software engineering continues to evolve and thrive, unburdened by the limitations of any single framework.&lt;/p&gt;
</description>
        <pubDate>Tue, 12 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/software/2023/09/12/The-Framework-Dilemma.html</link>
        <guid isPermaLink="true">https://virajmavani.com/software/2023/09/12/The-Framework-Dilemma.html</guid>
        
        <category>software engineering</category>
        
        <category>frameworks</category>
        
        <category>software development</category>
        
        
        <category>Software</category>
        
      </item>
    
      <item>
        <title>Containerization in Distributed Systems</title>
        <description>&lt;p&gt;As a software engineer, I’ve always been interested in finding ways to improve the efficiency and scalability of my applications. When I first learned about containerization, I was immediately intrigued by the potential benefits it could offer.&lt;/p&gt;

&lt;p&gt;Containerization is a method of packaging and deploying software applications in isolated environments called containers. Containers share the operating system (OS) of the host machine, but they have their own filesystem, network, and process space. This makes them lightweight and portable, and it allows them to be deployed quickly and easily.&lt;/p&gt;

&lt;p&gt;There are many benefits to using containerization for distributed computing. Containers make it easy to deploy and manage applications across multiple machines. They also provide a high level of isolation, which can help to improve security and performance. Additionally, containers can be used to create self-contained environments that are easy to replicate and scale.&lt;/p&gt;

&lt;p&gt;In my experience, containerization has been a valuable tool for improving the efficiency and scalability of my applications. I’ve found that it’s easy to deploy and manage containers, and they’ve helped me to improve the security and performance of my applications.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;advantages-of-containerization&quot;&gt;Advantages of Containerization&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Efficiency:&lt;/strong&gt; Containers are like self-contained packages for your applications. They are lightweight and don’t require a full operating system to run. This makes them highly efficient in terms of resource usage. Containers only include the necessary components to run your application, which means they start quickly, use minimal memory, and have a smaller footprint compared to traditional virtual machines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; Containers excel in scalability. With containerization, you can easily scale your application up or down based on demand. When your application experiences a spike in traffic or needs more resources, you can effortlessly add more containers to handle the increased load. Similarly, during periods of lower demand, you can scale down by reducing the number of containers. This elasticity ensures your application performs optimally at all times, without wasting resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security:&lt;/strong&gt; Containers provide a level of isolation that enhances application security. Each container operates in its own isolated environment, ensuring that if one container is compromised, it won’t affect the others. Containers use a combination of kernel-level isolation and resource control mechanisms to keep applications separated, reducing the attack surface and minimizing the potential impact of security breaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Portability:&lt;/strong&gt; One of the key advantages of containers is their portability. Containers encapsulate your application and its dependencies into a single package, making it easy to run the same containerized application across different computing environments. Whether you’re developing on your local machine, testing on a staging server, or deploying in a production environment, the container remains consistent, reducing the chances of compatibility issues and simplifying the deployment process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reproducibility:&lt;/strong&gt; Containers offer reproducibility, ensuring consistent environments for your applications. Containers are built from images, which are like snapshots of a container’s filesystem and configuration. These images capture the exact state of the container at a specific point in time. With the same image, you can easily recreate the exact environment, ensuring consistency across development, testing, and production. This reproducibility makes it easier to share and collaborate on applications and reduces the likelihood of “it works on my machine” scenarios.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;common-containerization-patterns&quot;&gt;Common Containerization Patterns&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Single-container applications:&lt;/strong&gt; This is a simple pattern where each application is deployed in its own container. This makes it easy to manage and update individual applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Container orchestration:&lt;/strong&gt; This pattern uses a container orchestration tool to manage groups of containers. Orchestration tools can help to automate tasks such as deployment, scaling, and load balancing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Microservices:&lt;/strong&gt; This pattern breaks down an application into a collection of small, independent services. Each service is deployed in its own container, which makes it easy to scale and manage the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function as a Service (FaaS):&lt;/strong&gt; This pattern allows developers to deploy individual functions as containers. This makes it easy to build and deploy applications that are composed of small, independent functions.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;challenges-of-using-containerization&quot;&gt;Challenges of Using Containerization&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Security:&lt;/strong&gt; Yes! It is one of the challenges as well. Containers share the same OS as the host machine, so it is important to take steps to secure them. This includes using secure images and containers, and configuring the host machine securely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt; Containers can add overhead to the host machine, so it is important to choose the right containerization solution for your needs. Some factors to consider include the number of containers that will be deployed, the type of applications that will be deployed, and the host machine’s resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Containerization can be complex, especially for large-scale deployments. It is important to have a good understanding of containerization before you start deploying applications in containers.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Overall, containerization is a powerful tool that can be used to improve the efficiency and scalability of distributed computing. If you are looking for a way to deploy and manage applications across multiple machines, containerization is a great option to consider.&lt;/p&gt;
</description>
        <pubDate>Sun, 14 May 2023 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/software/2023/05/14/Containerization-in-Distributed-Systems.html</link>
        <guid isPermaLink="true">https://virajmavani.com/software/2023/05/14/Containerization-in-Distributed-Systems.html</guid>
        
        <category>software engineering</category>
        
        <category>distributed systems</category>
        
        <category>containerization</category>
        
        <category>docker</category>
        
        <category>microservices</category>
        
        <category>system design</category>
        
        
        <category>Software</category>
        
      </item>
    
      <item>
        <title>Cost of building monolithic applications</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;Almost always, the easy route is not the correct one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For many years, the standard method for creating software applications has been using a monolithic architecture. It entails developing an application as a solitary, independent unit with tightly integrated UI, data read/writes, and business logic. While this method is useful for smaller projects and kick-starting projects at a fast pace, it presents a number of difficulties when applications get bigger and more sophisticated. We’ll examine the drawbacks of monolithic design in this post and look at the motivations for developers’ shift to alternative paradigms like microservices.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/assets/img/blog/software/Cost-of-building-monoliths/Monolith1024_1.jpg&quot; alt=&quot;The migration dilemma&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In a dilemma about whether to make the move yourself to microservices? Read on!&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;scalability-problems&quot;&gt;Scalability Problems:&lt;/h2&gt;

&lt;p&gt;The limited scalability of monolithic design is one of its main drawbacks. More resources are needed when applications expand, which can be difficult to accommodate within a single, monolithic codebase. Monolithic applications are often scaled by cloning the entire application, which can be time and resource hungry. Apart from that, using a monolithic architecture makes engineers to scale their systems up vertically which normally results in increased costs associated with infrastructure. In contrast, a microservices design makes horizontal scaling pretty easy and allows for the autonomous scaling of each microservice, resulting in a more resource-effective use of resources.&lt;/p&gt;

&lt;h2 id=&quot;increased-complexity&quot;&gt;Increased Complexity:&lt;/h2&gt;

&lt;p&gt;As a monolithic application gets bigger, its coding inevitably gets more intricate and challenging to manage. As a result, developers may need to spend more time on projects because it takes longer to navigate a complicated codebase and add new features. Additionally, it raises the chance of adding flaws or destroying functionality already in place.&lt;/p&gt;

&lt;h2 id=&quot;inflexible-techstack&quot;&gt;Inflexible Tech Stack:&lt;/h2&gt;

&lt;p&gt;Monolithic architecture often locks developers into a specific technology stack. This means that if they want to adopt new technologies, they may need to rewrite the entire application, which can be time-consuming and expensive. In contrast, microservices architecture enables developers to use different technology stacks for individual components, making it easier to adopt new technologies or switch between them as needed.&lt;/p&gt;

&lt;h2 id=&quot;slow-deployment-process&quot;&gt;Slow Deployment Process:&lt;/h2&gt;

&lt;p&gt;The deployment process for monolithic applications can be slow and prone to errors. Since the entire application is bundled together, even small changes require a complete redeployment of the application. This can lead to increased downtime and reduced productivity, particularly in large-scale applications. On the other hand, microservices architecture allows for faster and more targeted deployments, as individual components can be updated independently.&lt;/p&gt;

&lt;h2 id=&quot;difficulty-in-adopting-agile-development-practices&quot;&gt;Difficulty in Adopting Agile Development Practices:&lt;/h2&gt;

&lt;p&gt;Agile development practices, such as continuous integration and continuous deployment, are challenging to implement within a monolithic architecture. The complexity of the codebase, slow deployment process, and inflexible technology stack all contribute to this difficulty. As a result, monolithic applications may struggle to keep pace with the rapid evolution of software development practices and industry standards.&lt;/p&gt;

&lt;h2 id=&quot;human-resource&quot;&gt;Human Resource:&lt;/h2&gt;

&lt;p&gt;The biggest cost that most people do not consider is the human cost. When an organization has been maintaining a monolithic service for a long period of time, there eventually arises a unique sort of an engineer called an SME (subject matter expert). The SMEs in software engineering world become a bottleneck in the software development lifecycle as there seems to be no progress made if they are not present leading to inefficiencies.&lt;/p&gt;

&lt;p&gt;In conclusion, monolithic architecture has substantial drawbacks in terms of scalability, complexity, technology stack flexibility, deployment speed, and adoption of agile development approaches, even though it may be appropriate for some projects. As a result, many developers are using alternate strategies to create apps that are more effective, scalable, and flexible. The limits of monolithic architecture might help developers choose the strategy that best satisfies their unique demands and requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Later.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 16 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/software/2023/04/16/Cost-of-building-monoliths.html</link>
        <guid isPermaLink="true">https://virajmavani.com/software/2023/04/16/Cost-of-building-monoliths.html</guid>
        
        <category>software engineering</category>
        
        <category>distributed computing</category>
        
        <category>high performance architecture</category>
        
        <category>software resiliency</category>
        
        <category>microservices</category>
        
        
        <category>Software</category>
        
      </item>
    
      <item>
        <title>Product of Array Except Self - LeetCode #238</title>
        <description>&lt;p&gt;Being one of the most asked questions and also one of the important problem patterns on LeetCode, the product of array except self problem has become a subject of interest for this blog. It uses a modification of a general approach called prefix sum as an optimal solution.&lt;/p&gt;

&lt;p&gt;Let’s dive into it!&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;problem-statement&quot;&gt;Problem Statement&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;You can find the problem statement here: &lt;a href=&quot;https://leetcode.com/problems/product-of-array-except-self/&quot;&gt;Product of Array except Self - LeetCode&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;solutions&quot;&gt;Solution(s)&lt;/h2&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;1-naive-approach---brute-force&quot;&gt;1. Naive Approach - Brute Force&lt;/h3&gt;

&lt;p&gt;The brute-force approach to solution is simple. For each index in the the array, we calculate the product of every remaining element.&lt;/p&gt;

&lt;p&gt;The python code for it will look like this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;productExceptSelf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;
Time Complexity: O(N&lt;sup&gt;2&lt;/sup&gt;)
&lt;br /&gt;
Space Complexity: O(1) [Not considering the result array]
&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-better-approach---prefix-and-postfix-products&quot;&gt;2. Better Approach - Prefix and postfix products&lt;/h3&gt;

&lt;p&gt;As we can observe in the brute-force solution, there is a lot of recomputation happening which can be avoided to speed up our code. All we have to do is to precompute all the products from the left side and right side leaving apart the element at their index and have 2 new arrays holding the products. We can do this in two single passes through the array and then we can finally make the result array going through the arrays once more. A more detailed explanation can be seen in the image below:&lt;/p&gt;

&lt;div align=&quot;center&quot;&gt;
  &lt;img width=&quot;800&quot; height=&quot;300&quot; src=&quot;/static/assets/img/blog/prod-array-except-self/prod_array_except_self.jpg&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;The time complexity will be reduced to O(N) due to single passes but the space complexity will rise to be O(N) as well.&lt;/p&gt;

&lt;p&gt;The python code for this approach is given below:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;productExceptSelf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;left_prod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;right_prod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;left_prod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_prod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_prod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_prod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_prod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_prod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;
Time Complexity: O(N)
&lt;br /&gt;
Space Complexity: O(N) [Extra space used for Left Product and Right Product arrays]
&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;3-optimal-approach---prefix-and-postfix-products-without-extra-space&quot;&gt;3. Optimal Approach - Prefix and postfix products without extra space&lt;/h3&gt;

&lt;p&gt;We can modify the approach discussed above to not use any extra space by simple trickery.&lt;/p&gt;

&lt;p&gt;The python code for it is given below:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;productExceptSelf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        
    &lt;span class=&quot;n&quot;&gt;r_prod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r_prod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;r_prod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;
Time Complexity: O(N)
&lt;br /&gt;
Space Complexity: O(1) [Extra space not used - Disregarding result array]
&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Best of Luck! Later.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 25 May 2020 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/leetcode/2020/05/25/Product-Array-Except-Self.html</link>
        <guid isPermaLink="true">https://virajmavani.com/leetcode/2020/05/25/Product-Array-Except-Self.html</guid>
        
        <category>product of array except self</category>
        
        <category>LeetCode</category>
        
        <category>Interview Question</category>
        
        <category>Facebook</category>
        
        <category>Amazon</category>
        
        <category>Lyft</category>
        
        <category>Goldman Sachs</category>
        
        <category>Microsoft</category>
        
        <category>Apple</category>
        
        <category>Oracle</category>
        
        <category>Google</category>
        
        <category>Adobe</category>
        
        <category>Asana</category>
        
        
        <category>Leetcode</category>
        
      </item>
    
      <item>
        <title>Contains Duplicate - LeetCode #217</title>
        <description>&lt;p&gt;The Contains Duplicate problem on LeetCode is again one of the most asked questions and has the distinction to be on the Blind Community curated 75 questions list and therefore it makes it a subject of this blog’s interest. While it looks simple at first glance, there are a few things that need to be noted and will be helpful further in your journey through LeetCode.&lt;/p&gt;

&lt;p&gt;Let’s dive into it!
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;problem-statement&quot;&gt;Problem Statement&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;Given an array of integers, find if the array contains any duplicates.&lt;/p&gt;

&lt;p&gt;Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.&lt;/p&gt;

&lt;p&gt;Example 1:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Input: [1,2,3,1]
Output: true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Example 2:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Input: [1,2,3,4]
Output: false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Example 3:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Input: [1,1,1,3,3,4,3,2,4,2]
Output: true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;problem-analysis&quot;&gt;Problem Analysis&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;The problem is to basically to check if the array contains the same element twice or more. Simple enough. Also, note that the array is unsorted. Nothing more to it than this and so we’ll move on to solutions.
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;solutions&quot;&gt;Solution(s)&lt;/h2&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;1-naive-approach---brute-force-timelimitexceeded-on-leetcode&quot;&gt;1. Naive Approach - Brute Force (TimeLimitExceeded on LeetCode)&lt;/h3&gt;

&lt;p&gt;The brute force approach for any problem is probably the easiest to come up with. Here, we need to check for duplicates and in order to do that we will fix one element and try to find it again in the rest of the array.&lt;/p&gt;

&lt;p&gt;The python code for it looks something like this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;containsDuplicate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
    

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;
Time Complexity: O(N&lt;sup&gt;2&lt;/sup&gt;)
&lt;br /&gt;
Space Complexity: O(1)
&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-better-approach---sorting&quot;&gt;2. Better Approach - Sorting&lt;/h3&gt;

&lt;p&gt;We could have come up with a better solution only if we knew where to look for the second element after fixing the first in the brute force approach. Well, we can do this by simply sorting the array as after that, the duplicates will always be consecutive. We can then just conduct a linear search and determine if there are any duplicates or not.&lt;/p&gt;

&lt;p&gt;The python code for this approach will look like:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;containsDuplicate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# In-place sorting
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;
Time Complexity: O(N*log(N))
&lt;br /&gt;
Space Complexity: O(1)
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;While we reduced the time complexity from O(N&lt;sup&gt;2&lt;/sup&gt;) to O(N*log(N)), we still can do better in terms of the time complexity. But, it comes at a cost.
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;3-optimal-approach---hash-set&quot;&gt;3. Optimal Approach - Hash Set&lt;/h3&gt;

&lt;p&gt;The most optimal approach in terms of time complexity does indeed use extra space. But, as discussed before, space is cheap and time invaluable. Therefore, we can simple put all elements in a Hash Set and as it does not allow for duplicates, the size of the resulting Hash Set should be equal to the length of the array if there are no duplicates and less otherwise.&lt;/p&gt;

&lt;p&gt;A simple one line code in python looks like:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;containsDuplicate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Beautiful indeed. The computational complexities are:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
Time Complexity: O(N)
&lt;br /&gt;
Space Complexity: O(N)
&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Later.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 22 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/leetcode/2020/04/22/Contains-Duplicate.html</link>
        <guid isPermaLink="true">https://virajmavani.com/leetcode/2020/04/22/Contains-Duplicate.html</guid>
        
        <category>contains duplicate</category>
        
        <category>LeetCode</category>
        
        <category>Interview Question</category>
        
        <category>Amazon</category>
        
        <category>Apple</category>
        
        <category>Adobe</category>
        
        
        <category>Leetcode</category>
        
      </item>
    
      <item>
        <title>Two Sum - LeetCode #1</title>
        <description>&lt;p&gt;As “Hello, World!” is to Programming, so is the Two Sum problem to LeetCode. Any blog series or YouTube channel targeted towards solving LeetCode problems has to first pay deference to this problem. It is therefore implied that this blog series will be no different.&lt;/p&gt;

&lt;p&gt;So let’s just jump right into it.
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;problem-statement&quot;&gt;Problem Statement&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;Given an array of integers, return indices of the two numbers such that they add up to a specific target.&lt;/p&gt;

&lt;p&gt;You may assume that each input would have exactly one solution, and you may not use the same element twice.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;problem-analysis&quot;&gt;Problem Analysis&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;Well, the problem statement is clear and to the point enough that we don’t need to do much analysis. The only points to note here are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;We have to return indices&lt;/li&gt;
  &lt;li&gt;The array is not sorted&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;solutions&quot;&gt;Solution(s)&lt;/h2&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;1-brute-force-approach&quot;&gt;1. Brute Force Approach&lt;/h3&gt;

&lt;p&gt;First and foremost, we must try to solve the problem using a brute-force approach so as to get more insight into how to further optimize it.&lt;/p&gt;

&lt;p&gt;We can simply iterate over each element and for each such element, we can iterate over the rest of the elements in the array to check if they sum up to the target value.&lt;/p&gt;

&lt;p&gt;The python code will look something like this:
&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;two_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
Well, that was cute. But really abhorrent if you want to land that FAANG job you are looking for.&lt;/p&gt;

&lt;p&gt;We can safely rely on our Algorithms and Data Structures course content and say that the time complexity here is in the order of O(N&lt;sup&gt;2&lt;/sup&gt;) and we are not really using any extra space so the space complexity will be O(1).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
Time Complexity: O(N&lt;sup&gt;2&lt;/sup&gt;)
&lt;br /&gt;
Space Complexity: O(1)
&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-optimal-approach---using-hash-table&quot;&gt;2. Optimal Approach - Using Hash Table&lt;/h3&gt;

&lt;p&gt;I recall that I once was watching a YouTube video on LeetCoding practices and the content creator said that Hash Tables are very over-powered. You can’t come up with a solution, just throw Hash Tables at the problem and you will make some progress. Constant time access IS over-powered.&lt;/p&gt;

&lt;p&gt;Same applies to this problem as well and in this case, it is the most optimal approach known to programmers worldwide.&lt;/p&gt;

&lt;p&gt;The idea here is that we can use Hash Table to store the elements and keys and their indices as values. While iterating through each element, we can then check if (target - element) is present in the Hash Table or not. The answer will simply then become the iterator index and the index stored in the Hash Table.&lt;/p&gt;

&lt;p&gt;The python code looks something like this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;two_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;htable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;residual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;residual&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;htable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;htable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;residual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;htable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Isn’t it beautiful? Indeed it is. We have sacrificed some space in order to achieve linear time complexity for the solution. The Hash Table uses O(N) space and the time complexity becomes O(N) as well. But, space is cheap and time invaluable. Therefore, this being the most optimal approach.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
Time Complexity: O(N)
&lt;br /&gt;
Space Complexity: O(N)
&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;alternative-problem-statement---sorting&quot;&gt;Alternative Problem Statement - Sorting&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Return Elements&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When asked to return the elements and not the indices, the following is also one of the approaches. It is not as good as the Hash Table approach, but still is better than brute force.&lt;/p&gt;

&lt;p&gt;The approach is called the two pointer approach. It might be difficult to get to it logically, but on knowing it, it is as simple as it can be.&lt;/p&gt;

&lt;p&gt;In this problem, we noticed that there have been no comments on the order of the elements in the array making us assume that it is an unsorted one. We can initially sort the array to get ordering introduced in the problem. Once, we have the ordering we can make decisions by trying out different sum of two elements.&lt;/p&gt;

&lt;p&gt;For any indices [i, j] (where i &amp;lt; j) in the sorted array, we can
safely say that if the sum of the elements at i and j is greater than
the target, then we might want to decrement j in order to get to the
target. Same applies vice versa, that is, if the sum is less than the
target, incrementing i will rbing us closer to the solution.&lt;/p&gt;

&lt;p&gt;Basically, we will start with i = 0 and j = n-1 (where n = len(array))
adn increment i or decrement j in accordance with the sum of the
elements at i and j.&lt;/p&gt;

&lt;p&gt;The python code for this approach looks something like this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;two_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Sort array in place
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;curr_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The computational complexities for this approach are given below:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
Time Complexity: O(N*log(N))
&lt;br /&gt;
Space Complexity: O(1) // as sorting in place
&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;end-note&quot;&gt;End Note&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;I know developing intuition for solving LeetCode problems is difficult. Over time, you will understand that there are a few approaches that should first be tried out for each problem. Just try to apply them mentally and think if they would in any way help you in getting to the answer. One such approach that we learned today is the Two Pointer Approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Later.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 20 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/leetcode/2020/04/20/Two-Sum-LeetCode.html</link>
        <guid isPermaLink="true">https://virajmavani.com/leetcode/2020/04/20/Two-Sum-LeetCode.html</guid>
        
        <category>#1</category>
        
        <category>Two Sum</category>
        
        <category>LeetCode</category>
        
        <category>Interview Question</category>
        
        
        <category>Leetcode</category>
        
      </item>
    
      <item>
        <title>Automatic Post from Java Web Service</title>
        <description>&lt;h1 id=&quot;dummy-post-made-using-the-java-web-service&quot;&gt;Dummy Post made using the Java Web Service&lt;/h1&gt;
&lt;hr /&gt;
&lt;p&gt;Posted using the Java Web Service which automatically makes updates to the blog and commits on GitHub which is being used to host the website.&lt;/p&gt;
</description>
        <pubDate>Wed, 08 Jan 2020 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/personal/2020/01/08/auto_post.html</link>
        <guid isPermaLink="true">https://virajmavani.com/personal/2020/01/08/auto_post.html</guid>
        
        <category>Quizzing</category>
        
        <category>LDCE</category>
        
        
        <category>Personal</category>
        
      </item>
    
      <item>
        <title>My first experience as a Quiz Master!</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;MIND PALACE’S youngest Quizmaster takes the stage.&lt;br /&gt;
Internal Gen Quiz Session&lt;br /&gt;
By Viraj Mavani,&lt;br /&gt;
Wednesday, 18th March, 2015&lt;br /&gt;
3 pm @ Room 3001, Annexe Building&lt;br /&gt;
No prior registration required. Just be there and spread the word. 😉&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was how the invite was to majority of the students who share the college with me. Just a few months into the field and here I was conducting “My First Quiz”. It was definitely worth experiencing as no one would have ever had to present one holding a laptop in his hands and raising it so that the crowd could see. Yes. The projector was out-of-order. So, I conducted half of the prelims round(which was converted to a common pounce-bounce round for ease) speaking as loudly as I could and briskly walking around the hall (with the 14″ laptop) so that every one could have a look.&lt;/p&gt;

&lt;p&gt;Then, by god’s grace, we moved to the class with the projector, WORKING. And it was then that I started having a good time. I took back a moment as everyone read the question and thought to myself, “Blue Blistering Barnacles! This is really happening!”&lt;/p&gt;

&lt;p&gt;We ended The Quiz quite gracefully. Many loved friends attended it while those who didn’t, just got hold of the PPT later on.&lt;/p&gt;

&lt;p&gt;That was how it feels to be a Quiz Master. (For the First Time! 😉 )&lt;/p&gt;

&lt;p&gt;Mischief Managed.&lt;/p&gt;

&lt;p&gt;Share with me your views. Comment below. 😉&lt;/p&gt;
</description>
        <pubDate>Thu, 16 Apr 2015 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/personal/2015/04/16/Quizzing.html</link>
        <guid isPermaLink="true">https://virajmavani.com/personal/2015/04/16/Quizzing.html</guid>
        
        <category>Quizzing</category>
        
        <category>LDCE</category>
        
        
        <category>Personal</category>
        
      </item>
    
      <item>
        <title>Hello World!</title>
        <description>&lt;p&gt;This is the first thing that most entities on the internet start with. The Hello World. So here I am, bidding hello to the world and to you.&lt;/p&gt;

&lt;p&gt;Viraj Mavani. This is how people know me. An Average Joe. The Muhammed Lee. A student at L. D. College of Engineering pursuing his interests in the bold and huge field of Electronics. As I mentioned, an Average Joe means an average student too. The seven point someone guy. I live in Ahmedabad and roam about just a little even though I want to. When it comes to attending classes, I am regularly irregular. The story of every to-be-engineer.&lt;/p&gt;

&lt;p&gt;Apart from being common, I also happen to be an Editor for the College Magazine and that is not so common among the ‘House of Commons’ (literally). The magazine goes by the name Vox Populi (Check it out on FB). I am also a regular quizzer and an occasional Quiz Master for the quizzing club of the college under the name Mind Palace. A free lance photographer too. The blog background you see is credited to me. So, that’s where I am at present, leading a common happening life ;). (That was all too common-common :P)&lt;/p&gt;

&lt;p&gt;Thus, the purpose is defined. I will be updating my experiences with the Magazine, the Quiz Club and the Photography. I may go out of the line sometimes and get some creative. You will come to know it then. 😉&lt;/p&gt;

&lt;p&gt;So here I am, signing off with a sentence that I adore a lot.&lt;/p&gt;

&lt;p&gt;“I solemnly swear that I am up to no good.”&lt;/p&gt;

&lt;p&gt;Later.&lt;/p&gt;
</description>
        <pubDate>Wed, 15 Apr 2015 00:00:00 +0000</pubDate>
        <link>https://virajmavani.com/personal/2015/04/15/Hello_World.html</link>
        <guid isPermaLink="true">https://virajmavani.com/personal/2015/04/15/Hello_World.html</guid>
        
        <category>Hello</category>
        
        <category>World</category>
        
        
        <category>Personal</category>
        
      </item>
    
  </channel>
</rss>
