<?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: Abhishek Chaudhary</title>
    <description>The latest articles on DEV Community by Abhishek Chaudhary (@theabbie).</description>
    <link>https://dev.to/theabbie</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F315248%2F9ef2ec2a-378e-421a-910f-c75f4596d178.jpg</url>
      <title>DEV Community: Abhishek Chaudhary</title>
      <link>https://dev.to/theabbie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/theabbie"/>
    <language>en</language>
    <item>
      <title>Building a Physics-Accurate Live Wallpaper for Android</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Thu, 30 Jul 2026 09:28:54 +0000</pubDate>
      <link>https://dev.to/theabbie/building-a-physics-accurate-live-wallpaper-for-android-1gi9</link>
      <guid>https://dev.to/theabbie/building-a-physics-accurate-live-wallpaper-for-android-1gi9</guid>
      <description>&lt;p&gt;A while back I built a &lt;a href="https://github.com/theabbie/DoublePendulum" rel="noopener noreferrer"&gt;double-pendulum simulation in the browser&lt;/a&gt;. The motion is hard to stop watching. Two bobs, one hinge, and the trajectory never repeats. I kept thinking it would make a good live wallpaper, so I eventually ported it to Android.&lt;/p&gt;

&lt;p&gt;This is the story of how that port went.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting point: the web simulation
&lt;/h2&gt;

&lt;p&gt;The browser version runs entirely in a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element. Physics are integrated with RK4 over the Hamiltonian equations of motion, and the path tracer stores a circular buffer of past positions. The coordinate system is a normalised viewBox so it scales cleanly to any window size.&lt;/p&gt;

&lt;p&gt;The goal for the Android version was pixel-identical output: same stroke widths, same bob radii, same trace behavior, same graph. Not a visual approximation.&lt;/p&gt;

&lt;h2&gt;
  
  
  WallpaperService and the rendering surface
&lt;/h2&gt;

&lt;p&gt;Android live wallpapers subclass &lt;code&gt;WallpaperService&lt;/code&gt; and expose a &lt;code&gt;Surface&lt;/code&gt; through the &lt;code&gt;Engine&lt;/code&gt; callbacks. The canonical pattern is to acquire a &lt;code&gt;Canvas&lt;/code&gt; from the surface, draw into it, and post it back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;canvas&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;surfaceHolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lockCanvas&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;surfaceHolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unlockCanvasAndPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tricky part is the coordinate system. The surface dimensions are in physical pixels and vary across devices. To get pixel-identical output I mirrored the web approach exactly: define everything in a normalised viewBox of &lt;code&gt;100 x (100 * H/W)&lt;/code&gt; units, then scale the canvas once at the start of each frame:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;100f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;100f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stroke widths, bob radii, and the graph are all specified in viewBox units. The single scale transform handles the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Physics: Hamiltonian + RK4
&lt;/h2&gt;

&lt;p&gt;The double pendulum is not easily simulated with naive Euler integration because energy drifts quickly. The web version uses the Hamiltonian formulation, where generalised momenta are tracked alongside the angles, and RK4 advances the state each tick.&lt;/p&gt;

&lt;p&gt;Translating this from JavaScript to Kotlin was mostly mechanical. The main difference is that Kotlin does not have &lt;code&gt;let&lt;/code&gt; destructuring the same way, so the intermediate RK4 derivatives end up as explicit &lt;code&gt;DoubleArray&lt;/code&gt; copies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;rk4Step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DoubleArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;DoubleArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;k1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;derivatives&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;k2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;derivatives&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addScaled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;k3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;derivatives&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addScaled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;k4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;derivatives&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addScaled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;DoubleArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;k2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;k3&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;k4&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The simulation runs at whatever frame rate the surface provides and scales the timestep accordingly, so speed on fast and slow devices stays consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping settings consistent across three contexts
&lt;/h2&gt;

&lt;p&gt;One of the more interesting design problems was state management. There are three distinct contexts that each need a different view of the settings:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In-app preview&lt;/strong&gt; while the user is tweaking parameters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The live wallpaper surface&lt;/strong&gt; running on the home screen&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saved presets&lt;/strong&gt; the user wants to recall later&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the settings activity wrote directly to the shared prefs that the wallpaper service reads, every slider drag would immediately change the live wallpaper. That felt wrong.&lt;/p&gt;

&lt;p&gt;The solution was three separate &lt;code&gt;SharedPreferences&lt;/code&gt; stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;chaotic_session&lt;/code&gt;: written freely during the settings session, cleared on every app launch so it never bleeds into the wallpaper&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chaotic_wallpaper&lt;/code&gt;: read by the &lt;code&gt;WallpaperService&lt;/code&gt;; written only when the user taps SET AS WALLPAPER&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chaotic_persistent&lt;/code&gt;: stores named presets, survives the session&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way the user can drag bobs, shuffle with RANDOM, adjust mass and speed, and watch the in-app preview update in real time. None of that touches the live wallpaper until they explicitly commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drag-to-customize while paused
&lt;/h2&gt;

&lt;p&gt;The in-app preview lets you drag the bobs to set the initial position. Hit detection maps the touch coordinates back through the inverse of the viewBox scale and checks distance against each bob's radius. When a bob is being dragged, the physics step is skipped and the state is overwritten with the new angles derived from the touch position.&lt;/p&gt;

&lt;p&gt;One edge case: if both bobs are near each other, you want the touch to grab the nearer one. A simple nearest-first sort on touch-distance handles it.&lt;/p&gt;

&lt;h2&gt;
  
  
  OLED and battery
&lt;/h2&gt;

&lt;p&gt;The wallpaper uses a pure black background (&lt;code&gt;0xFF000000&lt;/code&gt;), which means OLED pixels in the black regions are literally off. This is intentional.&lt;/p&gt;

&lt;p&gt;For battery, the &lt;code&gt;WallpaperService.Engine&lt;/code&gt; provides &lt;code&gt;onVisibilityChanged&lt;/code&gt;. When the wallpaper is not visible (another app is in the foreground, screen is off), the rendering loop stops:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onVisibilityChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;startRendering&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;stopRendering&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app also has zero permissions beyond &lt;code&gt;BIND_WALLPAPER&lt;/code&gt; and makes no network requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build setup
&lt;/h2&gt;

&lt;p&gt;The project uses AGP 8.7.3 with R8 minification and resource shrinking in release. Release signing goes through a gitignored &lt;code&gt;keystore.properties&lt;/code&gt; file; if the file is absent the build falls back to the debug key automatically so CI and forks can still build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew :app:bundleRelease   &lt;span class="c"&gt;# AAB for Play Store&lt;/span&gt;
./gradlew :app:assembleRelease &lt;span class="c"&gt;# APK for sideloading&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Result
&lt;/h2&gt;

&lt;p&gt;The final app is a faithful port of the web simulation, running as a live wallpaper. The physics are identical, the visuals are pixel-matched across screen sizes, and the settings model keeps the preview experience independent from the live wallpaper until you decide to commit.&lt;/p&gt;

&lt;p&gt;It is free, has no ads, and collects no data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.theabbie.chaos" rel="noopener noreferrer"&gt;Get it on Google Play&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/theabbie/ChaoticLiveWallpaper" rel="noopener noreferrer"&gt;Source on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>physics</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Canvas API</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Thu, 21 Mar 2024 03:09:14 +0000</pubDate>
      <link>https://dev.to/theabbie/canvas-api-1db7</link>
      <guid>https://dev.to/theabbie/canvas-api-1db7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for DEV Challenge v24.03.20, One Byte Explainer: Browser API or Feature.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Explainer
&lt;/h2&gt;

&lt;p&gt;The Canvas API provides a drawing surface for creating visually engaging graphics and images using JavaScript to dynamically render shapes, paths, text, and images, enabling the creation of interactive charts, animations, and games on the web.&lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Serialize and Deserialize BST</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sun, 19 Jun 2022 04:00:48 +0000</pubDate>
      <link>https://dev.to/theabbie/serialize-and-deserialize-bst-45dm</link>
      <guid>https://dev.to/theabbie/serialize-and-deserialize-bst-45dm</guid>
      <description>&lt;p&gt;Serialization is converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.&lt;/p&gt;

&lt;p&gt;Design an algorithm to serialize and deserialize a &lt;strong&gt;binary search tree&lt;/strong&gt;. There is no restriction on how your serialization/deserialization algorithm should work. You need to ensure that a binary search tree can be serialized to a string, and this string can be deserialized to the original tree structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The encoded string should be as compact as possible.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; root = [2,1,3]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; [2,1,3]&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; root = []&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; []&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  The number of nodes in the tree is in the range &lt;code&gt;[0, 104]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;0 &amp;lt;= Node.val &amp;lt;= 104&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  The input tree is &lt;strong&gt;guaranteed&lt;/strong&gt; to be a binary search tree.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Codec:

    def serialize(self, root: Optional[TreeNode]) -&amp;gt; str:
        tree = {}
        paths = [(root, 0)]
        while len(paths) &amp;gt; 0:
            curr, i = paths.pop()
            if curr:
                tree[i] = curr.val
                paths.append((curr.left, 2 * i + 1))
                paths.append((curr.right, 2 * i + 2))
        return ";".join(["{}={}".format(k, v) for k, v in tree.items()])

    def deserialize(self, data: str) -&amp;gt; Optional[TreeNode]:
        vals = data.split(";")
        tree = {}
        for v in vals:
            if len(v) &amp;gt; 0:
                key, value = v.split("=")
                tree[int(key)] = int(value)
        if len(tree) == 0:
            return None
        root = TreeNode()
        paths = [(root, 0)]
        while len(paths) &amp;gt; 0:
            curr, i = paths.pop()
            curr.val = tree[i]
            if (2 * i + 1) in tree:
                curr.left = TreeNode()
                paths.append((curr.left, 2 * i + 1))
            if (2 * i + 2) in tree:
                curr.right = TreeNode()
                paths.append((curr.right, 2 * i + 2))
        return root

# Your Codec object will be instantiated and called as such:
# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# tree = ser.serialize(root)
# ans = deser.deserialize(tree)
# return ans
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
    <item>
      <title>Valid Palindrome</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sun, 19 Jun 2022 03:30:36 +0000</pubDate>
      <link>https://dev.to/theabbie/valid-palindrome-5aoa</link>
      <guid>https://dev.to/theabbie/valid-palindrome-5aoa</guid>
      <description>&lt;p&gt;A phrase is a &lt;strong&gt;palindrome&lt;/strong&gt; if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers.&lt;/p&gt;

&lt;p&gt;Given a string &lt;code&gt;s&lt;/code&gt;, return &lt;code&gt;true&lt;/code&gt; &lt;em&gt;if it is a &lt;strong&gt;palindrome&lt;/strong&gt;, or&lt;/em&gt; &lt;code&gt;false&lt;/code&gt; &lt;em&gt;otherwise&lt;/em&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "A man, a plan, a canal: Panama"&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; true&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; "amanaplanacanalpanama" is a palindrome.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "race a car"&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; false&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; "raceacar" is not a palindrome.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = " "&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; true&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; s is an empty string "" after removing non-alphanumeric characters.&lt;br&gt;
Since an empty string reads the same forward and backward, it is a palindrome.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;1 &amp;lt;= s.length &amp;lt;= 2 * 105&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;s&lt;/code&gt; consists only of printable ASCII characters.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution:
    def isPalindrome(self, s: str) -&amp;gt; bool:
        s = "".join([c.lower() for c in s if c.isalnum()])
        return s == s[::-1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
    <item>
      <title>Average Salary Excluding the Minimum and Maximum Salary</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sun, 19 Jun 2022 03:00:41 +0000</pubDate>
      <link>https://dev.to/theabbie/average-salary-excluding-the-minimum-and-maximum-salary-4gn6</link>
      <guid>https://dev.to/theabbie/average-salary-excluding-the-minimum-and-maximum-salary-4gn6</guid>
      <description>&lt;p&gt;You are given an array of &lt;strong&gt;unique&lt;/strong&gt; integers &lt;code&gt;salary&lt;/code&gt; where &lt;code&gt;salary[i]&lt;/code&gt; is the salary of the &lt;code&gt;ith&lt;/code&gt; employee.&lt;/p&gt;

&lt;p&gt;Return &lt;em&gt;the average salary of employees excluding the minimum and maximum salary&lt;/em&gt;. Answers within &lt;code&gt;10-5&lt;/code&gt; of the actual answer will be accepted.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; salary = [4000,3000,1000,2000]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 2500.00000&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; Minimum salary and maximum salary are 1000 and 4000 respectively.&lt;br&gt;
Average salary excluding minimum and maximum salary is (2000+3000) / 2 = 2500&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; salary = [1000,2000,3000]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 2000.00000&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; Minimum salary and maximum salary are 1000 and 3000 respectively.&lt;br&gt;
Average salary excluding minimum and maximum salary is (2000) / 1 = 2000&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;3 &amp;lt;= salary.length &amp;lt;= 100&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;1000 &amp;lt;= salary[i] &amp;lt;= 106&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  All the integers of &lt;code&gt;salary&lt;/code&gt; are &lt;strong&gt;unique&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution:
    def average(self, salary: List[int]) -&amp;gt; float:
        n = len(salary)
        total = 0
        currmin = float('inf')
        currmax = float('-inf')
        for i in range(n):
            currmin = min(currmin, salary[i])
            currmax = max(currmax, salary[i])
            total += salary[i]
        return (total - currmin - currmax) / (n - 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
    <item>
      <title>Backspace String Compare</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sun, 19 Jun 2022 02:30:40 +0000</pubDate>
      <link>https://dev.to/theabbie/backspace-string-compare-5c0c</link>
      <guid>https://dev.to/theabbie/backspace-string-compare-5c0c</guid>
      <description>&lt;p&gt;Given two strings &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;t&lt;/code&gt;, return &lt;code&gt;true&lt;/code&gt; &lt;em&gt;if they are equal when both are typed into empty text editors&lt;/em&gt;. &lt;code&gt;'#'&lt;/code&gt; means a backspace character.&lt;/p&gt;

&lt;p&gt;Note that after backspacing an empty text, the text will continue empty.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "ab#c", t = "ad#c"&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; true&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; Both s and t become "ac".&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "ab##", t = "c#d#"&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; true&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; Both s and t become "".&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "a#c", t = "b"&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; false&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; s becomes "c" while t becomes "b".&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;1 &amp;lt;= s.length, t.length &amp;lt;= 200&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;t&lt;/code&gt; only contain lowercase letters and &lt;code&gt;'#'&lt;/code&gt; characters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Follow up:&lt;/strong&gt; Can you solve it in &lt;code&gt;O(n)&lt;/code&gt; time and &lt;code&gt;O(1)&lt;/code&gt; space?&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution:
    def backspaceCompare(self, s: str, t: str) -&amp;gt; bool:
        ss = ""
        tt = ""
        for c in s:
            if c == "#":
                ss = ss[:-1]
            else:
                ss += c
        for c in t:
            if c == "#":
                tt = tt[:-1]
            else:
                tt += c
        return ss == tt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
    <item>
      <title>Maximum Erasure Value</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sun, 19 Jun 2022 02:00:46 +0000</pubDate>
      <link>https://dev.to/theabbie/maximum-erasure-value-4m96</link>
      <guid>https://dev.to/theabbie/maximum-erasure-value-4m96</guid>
      <description>&lt;p&gt;You are given an array of positive integers &lt;code&gt;nums&lt;/code&gt; and want to erase a subarray containing&amp;nbsp;&lt;strong&gt;unique elements&lt;/strong&gt;. The &lt;strong&gt;score&lt;/strong&gt; you get by erasing the subarray is equal to the &lt;strong&gt;sum&lt;/strong&gt; of its elements.&lt;/p&gt;

&lt;p&gt;Return &lt;em&gt;the &lt;strong&gt;maximum score&lt;/strong&gt; you can get by erasing &lt;strong&gt;exactly one&lt;/strong&gt; subarray.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An array &lt;code&gt;b&lt;/code&gt; is called to be a subarray of &lt;code&gt;a&lt;/code&gt; if it forms a contiguous subsequence of &lt;code&gt;a&lt;/code&gt;, that is, if it is equal to &lt;code&gt;a[l],a[l+1],...,a[r]&lt;/code&gt; for some &lt;code&gt;(l,r)&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; nums = [4,2,4,5,6]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 17&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; The optimal subarray here is [2,4,5,6].&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; nums = [5,2,1,2,5,2,1,2,5]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 8&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; The optimal subarray here is [5,2,1] or [1,2,5].&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;1 &amp;lt;= nums.length &amp;lt;= 105&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;1 &amp;lt;= nums[i] &amp;lt;= 104&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution:
    def maximumUniqueSubarray(self, nums: List[int]) -&amp;gt; int:
        n = len(nums)
        msum = 0
        p = [0]
        for el in nums:
            p.append(p[-1] + el)
        prev = {}
        i = 0
        for j in range(n):
            if nums[j] in prev:
                i = max(i, prev[nums[j]] + 1)
            msum = max(msum, p[j + 1] - p[i])
            prev[nums[j]] = j
        return msum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
    <item>
      <title>Balance a Binary Search Tree</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sun, 19 Jun 2022 01:30:42 +0000</pubDate>
      <link>https://dev.to/theabbie/balance-a-binary-search-tree-29i1</link>
      <guid>https://dev.to/theabbie/balance-a-binary-search-tree-29i1</guid>
      <description>&lt;p&gt;Given the &lt;code&gt;root&lt;/code&gt; of a binary search tree, return &lt;em&gt;a &lt;strong&gt;balanced&lt;/strong&gt; binary search tree with the same node values&lt;/em&gt;. If there is more than one answer, return &lt;strong&gt;any of them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A binary search tree is &lt;strong&gt;balanced&lt;/strong&gt; if the depth of the two subtrees of every node never differs by more than &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c_ViwiMq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.leetcode.com/uploads/2021/08/10/balance1-tree.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c_ViwiMq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.leetcode.com/uploads/2021/08/10/balance1-tree.jpg" alt="" width="714" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; root = [1,null,2,null,3,null,4,null,null]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; [2,1,3,null,null,null,4]&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; This is not the only correct answer, [3,1,4,null,2] is also correct.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T-zN1ACJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.leetcode.com/uploads/2021/08/10/balanced2-tree.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T-zN1ACJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.leetcode.com/uploads/2021/08/10/balanced2-tree.jpg" alt="" width="224" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; root = [2,1,3]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; [2,1,3]&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  The number of nodes in the tree is in the range &lt;code&gt;[1, 104]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;1 &amp;lt;= Node.val &amp;lt;= 105&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorder(self, root):
        if root:
            self.inorder(root.left)
            self.tree.append(root.val)
            self.inorder(root.right)

    def arrToTree(self, arr, i, j):
        if i &amp;lt;= j - 1:
            root = TreeNode()
            mid = (i + j) // 2
            root.val = arr[mid]
            root.left = self.arrToTree(arr, i, mid)
            root.right = self.arrToTree(arr, mid + 1, j)
            return root
        return None

    def balanceBST(self, root: TreeNode) -&amp;gt; TreeNode:
        self.tree = []
        self.inorder(root)
        return self.arrToTree(self.tree, 0, len(self.tree))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
    <item>
      <title>Smallest String With Swaps</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sun, 19 Jun 2022 01:00:46 +0000</pubDate>
      <link>https://dev.to/theabbie/smallest-string-with-swaps-2nof</link>
      <guid>https://dev.to/theabbie/smallest-string-with-swaps-2nof</guid>
      <description>&lt;p&gt;You are given a string &lt;code&gt;s&lt;/code&gt;, and an array of pairs of indices in the string&amp;nbsp;&lt;code&gt;pairs&lt;/code&gt;&amp;nbsp;where&amp;nbsp;&lt;code&gt;pairs[i] =&amp;nbsp;[a, b]&lt;/code&gt;&amp;nbsp;indicates 2 indices(0-indexed) of the string.&lt;/p&gt;

&lt;p&gt;You can&amp;nbsp;swap the characters at any pair of indices in the given&amp;nbsp;&lt;code&gt;pairs&lt;/code&gt;&amp;nbsp;&lt;strong&gt;any number of times&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Return the&amp;nbsp;lexicographically smallest string that &lt;code&gt;s&lt;/code&gt;&amp;nbsp;can be changed to after using the swaps.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "dcab", pairs = [[0,3],[1,2]]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; "bacd"&lt;br&gt;
&lt;strong&gt;Explaination:&lt;/strong&gt; &lt;br&gt;
Swap s[0] and s[3], s = "bcad"&lt;br&gt;
Swap s[1] and s[2], s = "bacd"&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "dcab", pairs = [[0,3],[1,2],[0,2]]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; "abcd"&lt;br&gt;
&lt;strong&gt;Explaination:&lt;/strong&gt; &lt;br&gt;
Swap s[0] and s[3], s = "bcad"&lt;br&gt;
Swap s[0] and s[2], s = "acbd"&lt;br&gt;
Swap s[1] and s[2], s = "abcd"&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "cba", pairs = [[0,1],[1,2]]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; "abc"&lt;br&gt;
&lt;strong&gt;Explaination:&lt;/strong&gt; &lt;br&gt;
Swap s[0] and s[1], s = "bca"&lt;br&gt;
Swap s[1] and s[2], s = "bac"&lt;br&gt;
Swap s[0] and s[1], s = "abc"&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;1 &amp;lt;= s.length &amp;lt;= 10^5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;0 &amp;lt;= pairs.length &amp;lt;= 10^5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;0 &amp;lt;= pairs[i][0], pairs[i][1] &amp;lt;&amp;nbsp;s.length&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;s&lt;/code&gt;&amp;nbsp;only contains lower case English letters.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from collections import defaultdict

class Solution:
    def dfs(self, graph, node, visited):
        for j in graph[node]:
            if j not in visited:
                visited.add(j)
                self.dfs(graph, j, visited)

    def smallestStringWithSwaps(self, s: str, pairs: List[List[int]]) -&amp;gt; str:
        op = list(s)
        graph = defaultdict(list)
        for a, b in pairs:
            graph[a].append(b)
            graph[b].append(a)
        globalvisited = set()
        for x in graph:
            if x not in globalvisited:
                currvisited = {x}
                self.dfs(graph, x, currvisited)
                indexes = sorted(currvisited)
                indexes_asc = sorted(currvisited, key = lambda p: s[p])
                n = len(indexes)
                for i in range(n):
                    op[indexes[i]] = s[indexes_asc[i]]
                globalvisited.update(currvisited)
        return "".join(op)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
    <item>
      <title>Crawler Log Folder</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sun, 19 Jun 2022 00:30:36 +0000</pubDate>
      <link>https://dev.to/theabbie/crawler-log-folder-6d5</link>
      <guid>https://dev.to/theabbie/crawler-log-folder-6d5</guid>
      <description>&lt;p&gt;The Leetcode file system keeps a log each time some user performs a &lt;em&gt;change folder&lt;/em&gt; operation.&lt;/p&gt;

&lt;p&gt;The operations are described below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;"../"&lt;/code&gt; : Move to the parent folder of the current folder. (If you are already in the main folder, &lt;strong&gt;remain in the same folder&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;"./"&lt;/code&gt; : Remain in the same folder.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;"x/"&lt;/code&gt; : Move to the child folder named &lt;code&gt;x&lt;/code&gt; (This folder is &lt;strong&gt;guaranteed to always exist&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are given a list of strings &lt;code&gt;logs&lt;/code&gt; where &lt;code&gt;logs[i]&lt;/code&gt; is the operation performed by the user at the &lt;code&gt;ith&lt;/code&gt; step.&lt;/p&gt;

&lt;p&gt;The file system starts in the main folder, then the operations in &lt;code&gt;logs&lt;/code&gt; are performed.&lt;/p&gt;

&lt;p&gt;Return &lt;em&gt;the minimum number of operations needed to go back to the main folder after the change folder operations.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iK3QcfMn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.leetcode.com/uploads/2020/09/09/sample_11_1957.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iK3QcfMn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.leetcode.com/uploads/2020/09/09/sample_11_1957.png" alt="" width="800" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; logs = ["d1/","d2/","../","d21/","./"]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 2&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; Use this change folder operation "../" 2 times and go back to the main folder.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4SOJo-fr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.leetcode.com/uploads/2020/09/09/sample_22_1957.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4SOJo-fr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.leetcode.com/uploads/2020/09/09/sample_22_1957.png" alt="" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; logs = ["d1/","d2/","./","d3/","../","d31/"]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 3&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; logs = ["d1/","../","../","../"]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 0&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;1 &amp;lt;= logs.length &amp;lt;= 103&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;2 &amp;lt;= logs[i].length &amp;lt;= 10&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;logs[i]&lt;/code&gt; contains lowercase English letters, digits, &lt;code&gt;'.'&lt;/code&gt;, and &lt;code&gt;'/'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;logs[i]&lt;/code&gt; follows the format described in the statement.&lt;/li&gt;
&lt;li&gt;  Folder names consist of lowercase English letters and digits.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution:
    def minOperations(self, logs: List[str]) -&amp;gt; int:
        ctr = 0
        for log in logs:
            if log == "../":
                ctr =  max(ctr - 1, 0)
            elif log != "./":
                ctr += 1
        return ctr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
    <item>
      <title>Remove Palindromic Subsequences</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sun, 19 Jun 2022 00:00:45 +0000</pubDate>
      <link>https://dev.to/theabbie/remove-palindromic-subsequences-2hmj</link>
      <guid>https://dev.to/theabbie/remove-palindromic-subsequences-2hmj</guid>
      <description>&lt;p&gt;You are given a string &lt;code&gt;s&lt;/code&gt; consisting &lt;strong&gt;only&lt;/strong&gt; of letters &lt;code&gt;'a'&lt;/code&gt; and &lt;code&gt;'b'&lt;/code&gt;. In a single step you can remove one &lt;strong&gt;palindromic subsequence&lt;/strong&gt; from &lt;code&gt;s&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Return &lt;em&gt;the &lt;strong&gt;minimum&lt;/strong&gt; number of steps to make the given string empty&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A string is a &lt;strong&gt;subsequence&lt;/strong&gt; of a given string if it is generated by deleting some characters of a given string without changing its order. Note that a subsequence does &lt;strong&gt;not&lt;/strong&gt; necessarily need to be contiguous.&lt;/p&gt;

&lt;p&gt;A string is called &lt;strong&gt;palindrome&lt;/strong&gt; if is one that reads the same backward as well as forward.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "ababa"&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 1&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; s is already a palindrome, so its entirety can be removed in a single step.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "abb"&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 2&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; "abb" -&amp;gt; "bb" -&amp;gt; "". &lt;br&gt;
Remove palindromic subsequence "a" then "bb".&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; s = "baabb"&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 2&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; "baabb" -&amp;gt; "b" -&amp;gt; "". &lt;br&gt;
Remove palindromic subsequence "baab" then "b".&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;1 &amp;lt;= s.length &amp;lt;= 1000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;s[i]&lt;/code&gt; is either &lt;code&gt;'a'&lt;/code&gt; or &lt;code&gt;'b'&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution:
    def removePalindromeSub(self, s: str) -&amp;gt; int:
        if s == s[::-1]:
            return 1
        return 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
    <item>
      <title>Asteroid Collision</title>
      <dc:creator>Abhishek Chaudhary</dc:creator>
      <pubDate>Sat, 18 Jun 2022 23:30:38 +0000</pubDate>
      <link>https://dev.to/theabbie/asteroid-collision-acf</link>
      <guid>https://dev.to/theabbie/asteroid-collision-acf</guid>
      <description>&lt;p&gt;We are given an array &lt;code&gt;asteroids&lt;/code&gt; of integers representing asteroids in a row.&lt;/p&gt;

&lt;p&gt;For each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed.&lt;/p&gt;

&lt;p&gt;Find out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; asteroids = [5,10,-5]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; [5,10]&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; The 10 and -5 collide resulting in 10. The 5 and 10 never collide.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; asteroids = [8,-8]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; []&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; The 8 and -8 collide exploding each other.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; asteroids = [10,2,-5]&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; [10]&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; The 2 and -5 collide resulting in -5. The 10 and -5 collide resulting in 10.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;2 &amp;lt;= asteroids.length &amp;lt;= 104&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;-1000 &amp;lt;= asteroids[i] &amp;lt;= 1000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;asteroids[i] != 0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Solution:
    def asteroidCollision(self, asteroids: List[int]) -&amp;gt; List[int]:
        n = len(asteroids)
        stack = []
        survivors = set()
        for i in range(n):
            if asteroids[i] &amp;gt; 0:
                stack.append(i)
            else:
                while len(stack) &amp;gt; 0 and abs(asteroids[stack[-1]]) &amp;lt; abs(asteroids[i]):
                    stack.pop()
                if len(stack) &amp;gt; 0:
                    if abs(asteroids[stack[-1]]) &amp;lt;= abs(asteroids[i]):
                        stack.pop()
                else:
                    survivors.add(i)
        for i in stack:
            survivors.add(i)
        return [asteroids[i] for i in range(n) if i in survivors]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>theabbie</category>
    </item>
  </channel>
</rss>
