<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Redha Zidan</title>
    <description>The latest articles on DEV Community by Redha Zidan (@zidanredha2).</description>
    <link>https://dev.to/zidanredha2</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3832884%2Fb70dc8b2-cabe-4c2f-9b00-7c283e81bf84.png</url>
      <title>DEV Community: Redha Zidan</title>
      <link>https://dev.to/zidanredha2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zidanredha2"/>
    <language>en</language>
    <item>
      <title>How I Optimized the Maximum Pairwise Product: From O(n^2) to O(n)</title>
      <dc:creator>Redha Zidan</dc:creator>
      <pubDate>Thu, 19 Mar 2026 18:21:07 +0000</pubDate>
      <link>https://dev.to/zidanredha2/how-i-optimized-the-maximum-pairwise-product-from-on2-to-on-278c</link>
      <guid>https://dev.to/zidanredha2/how-i-optimized-the-maximum-pairwise-product-from-on2-to-on-278c</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy8chvppiai6zqwkwm04f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy8chvppiai6zqwkwm04f.png" alt="Coding Algorithm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When starting the Data Structures and Algorithms specialization by UC San Diego on Coursera, the "Maximum Pairwise Product" problem is one of the first real tests of algorithmic efficiency. It’s a perfect example of how a "correct" solution can still be a "wrong" solution if it doesn't scale. The Problem: Given a sequence of non-negative integers, find the maximum product of two distinct numbers in the sequence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Naive Approach&lt;/strong&gt;: &lt;em&gt;O(n^2)&lt;/em&gt;&lt;br&gt;
The most intuitive way to solve this is to use a nested loop to check every possible pair:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;maxProduct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;maxProduct&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;maxProduct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Flaw: This works fine for small arrays. However, if the input size is 10^5, the number of operations reaches 10^{10}, which will lead to a Time Limit Exceeded (TLE) error in most competitive programming environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Optimized Approach&lt;/strong&gt;: &lt;em&gt;O(n)&lt;/em&gt;&lt;br&gt;
Instead of comparing every pair, we only need the two largest numbers in the array. We can find these in a single pass (O(n)) without even sorting the array (which would be O(n log n)).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="nf"&gt;maxPairwiseProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;max1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;indexOfMax1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;max2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;max1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
                &lt;span class="n"&gt;indexOfMax1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max2&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;indexOfMax1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;max2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;max2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Logic: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find the index of the largest number. &lt;/li&gt;
&lt;li&gt;Find the index of the second largest number (ensuring it's not the same index as the first).&lt;/li&gt;
&lt;li&gt;Multiply them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The "Gotcha"&lt;/strong&gt;: &lt;em&gt;Integer Overflow&lt;/em&gt;&lt;br&gt;
Even with a fast algorithm, you can fail the test cases if you don't account for the size of the result.&lt;br&gt;
In many languages, a standard int is 32-bit (max value approx 2 times 10^9). If the input numbers are 2 times 10^5, their product is 4 times 10^{10}. This exceeds the capacity of an int, leading to a negative result due to overflow. &lt;br&gt;
The fix is simple but vital: Use a 64-bit integer (long in Java/C# or long long in C++) for the product calculation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
This problem is a great reminder that software engineering isn't just about solving the logic, it's about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Time Complexity&lt;/em&gt;: Making sure it runs fast enough for the real world.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Memory &amp;amp; Type Safety&lt;/em&gt;: Anticipating where the hardware limits might break your math.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What was your first "aha!" moment with Big O notation? Let me know in the comments!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>algorithms</category>
      <category>learning</category>
    </item>
    <item>
      <title>Why VMs Are Still the "Gold Standard" for Security (Despite the Docker Hype)</title>
      <dc:creator>Redha Zidan</dc:creator>
      <pubDate>Thu, 19 Mar 2026 00:26:33 +0000</pubDate>
      <link>https://dev.to/zidanredha2/why-vms-are-still-the-gold-standard-for-security-despite-the-docker-hype-3kef</link>
      <guid>https://dev.to/zidanredha2/why-vms-are-still-the-gold-standard-for-security-despite-the-docker-hype-3kef</guid>
      <description>&lt;p&gt;The rapid adoption of containerization is frequently attributed to its lightweight nature and deployment agility. However, as production environments scale, the fundamental security trade-offs between shared-kernel architectures and hardware-enforced isolation become critical points of evaluation.&lt;br&gt;
Based on my recent study, "Isolation, Security, and Trust Boundaries: Why Virtual Machines Are Still Preferred over Containers," this article examines the structural reasons why virtual machines (VMs) remain essential for secure cloud infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shared-Kernel Vulnerability
&lt;/h2&gt;

&lt;p&gt;The primary efficiency of Docker stems from operating system-level virtualization, where multiple containers share the host’s OS kernel. While this reduces resource overhead, it creates a single point of failure. A single kernel-level exploit can potentially allow an attacker to compromise all tenants on the host, a risk that is significantly mitigated by the independent guest OS model used in VMs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Container Escape and Privilege Escalation
&lt;/h2&gt;

&lt;p&gt;Container security relies on software-based boundaries like namespaces and control groups (cgroups). These mechanisms are susceptible to "container escape" attacks, where an attacker breaches the container to gain elevated privileges on the host system. In contrast, virtual machines utilize hypervisor-enforced isolation, which requires an attacker to breach a much more robust hardware-abstraction layer to affect the host or other guests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Platform-Dependent Performance
&lt;/h2&gt;

&lt;p&gt;While containers are often cited for near-native performance, this advantage is platform-dependent. On non-Linux systems such as Windows or macOS, Docker frequently operates within a lightweight VM to emulate necessary kernel features. In these scenarios, the performance gap between native containers and traditional virtualization narrows, while the complexity of the attack surface may actually increase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategic Deployment Recommendations
&lt;/h2&gt;

&lt;p&gt;The decision between these technologies should be governed by workload characteristics rather than performance metrics alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Containers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Virtualization Level&lt;/em&gt;: Operating System (OS) level.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Startup Time&lt;/em&gt;: Very fast, often in seconds or milliseconds.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Resource Overhead&lt;/em&gt;: Low; eliminates the need for a full guest OS.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Isolation Strength&lt;/em&gt;: Weaker; relies on a shared host kernel.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Security Boundary&lt;/em&gt;: Software-based using namespaces and cgroups.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Attack Blast Radius&lt;/em&gt;: Larger due to shared kernel dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Best Suited For&lt;/em&gt;: Microservices, CI/CD, and trusted cloud-native applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Virtual Machines:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Virtualization Level&lt;/em&gt;: Hardware level.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Startup Time&lt;/em&gt;: Slower; requires a full operating system boot process.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Resource Overhead&lt;/em&gt;: Higher; requires a full guest OS for each instance.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Isolation Strength&lt;/em&gt;: Strong; provides hardware-enforced separation.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Security Boundary&lt;/em&gt;: Hypervisor-enforced.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Attack Blast Radius&lt;/em&gt;: Smaller; individual guest environments encapsulate risks.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Best Suited For&lt;/em&gt;: Sensitive workloads, multi-tenant systems, and regulatory compliance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Emergence of Hybrid Models
&lt;/h2&gt;

&lt;p&gt;Industry trends suggest a convergence of these technologies through hybrid architectures. Solutions like Kata Containers or Firecracker aim to provide the agility of container orchestration with the security boundaries of a virtual machine. This evolution reinforces the conclusion that VMs and containers are complementary tools in a modern security-in-depth strategy.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>cloud</category>
      <category>docker</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
