Skip to content

Commit

Permalink
Refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
eminencegrs committed Nov 12, 2024
1 parent eeb801a commit a3a4d89
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Diagnostics.CodeAnalysis;

namespace LeetCode.Challenges.Problems0XX.P019_RemoveNthNodeFromTheEndOfList;

[ExcludeFromCodeCoverage]
public class ListNode(int val = default, ListNode? next = null)
{
public int Value { get; set; } = val;
public ListNode? Next { get; set; } = next;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
namespace LeetCode.Challenges.Problems0XX.P019_RemoveNthNodeFromTheEndOfList;

// Time Complexity: O(n).
// Space Complexity: O(1).
public static class TwoPointerSolution
{
public static ListNode RemoveNthFromEnd(ListNode head, int n)
{
// For example, we need to remove the 2nd node from the end of this list:
// 1 --> 2 --> 3 --> 4 --> 5 --> null

ListNode dummy = new ListNode(default, head);
ListNode left = dummy;
ListNode? right = head;

// dummy --> 1 --> 2 --> 3 --> 4 --> 5 --> null
// ^ ^
// (left) ^
// (right)

// Find where the right pointer should point to.
while (n > 0 && right != null)
{
right = right.Next;
n--;
}

// The 1st iteration, n is 2 (n > 0 && right IS NOT null):
// dummy --> 1 --> 2 --> 3 --> 4 --> 5 --> null
// ^ ^
// (left) ^
// (right)

// The 2nd iteration, n is 1 (n > 0 && right IS NOT null):
// dummy --> 1 --> 2 --> 3 --> 4 --> 5 --> null
// ^ ^
// (left) ^
// (right)

// The loop stops processing it because n is 0.
// Now, we have the following picture:
// dummy --> 1 --> 2 --> 3 --> 4 --> 5 --> null
// ^ ^
// (left) ^
// (right)

// Move both pointers forward until the right one is null.
// When the right pointer points to null, the left one points to the node before the one that should be removed.
while (right != null)
{
left = left.Next!;
right = right.Next;
}

// The 1st iteration (before the iteration, right IS NOT null).
// Thus, we can move the pointers.
// dummy --> 1 --> 2 --> 3 --> 4 --> 5 --> null
// ^ ^
// (left) ^
// (right)

// The 2nd iteration (before the iteration, right IS NOT null).
// Thus, we can move the pointers.
// dummy --> 1 --> 2 --> 3 --> 4 --> 5 --> null
// ^ ^
// (left) ^
// (right)

// The 3rd iteration (before the iteration, right IS NOT null).
// Thus, we can move the pointers.
// dummy --> 1 --> 2 --> 3 --> 4 --> 5 --> null
// ^ ^
// (left) ^
// (right)

// The loop stops processing it because right IS null.
// So, 'left.next' exactly points to the node to be removed.

// Let's update the pointers.
// Before:
// 1 --> 2 --> 3 --> 4 --> 5 --> null
left.Next = left.Next?.Next;

// After:
// 1 --> 2 --> 3 --> 5 --> null

return dummy.Next!;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System.Diagnostics.CodeAnalysis;

namespace LeetCode.Challenges.Problems0XX.P024_SwapNodesInPairs;

public class ListNode
[ExcludeFromCodeCoverage]
public class ListNode(int value = default, ListNode? next = null)
{
public int val;
public ListNode? next;

public ListNode(int val = 0, ListNode? next = null)
{
this.val = val;
this.next = next;
}
public int Value { get; set; } = value;
public ListNode? Next { get; set; } = next;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ public static class Solution
// Expected Result: 2 --> 1 --> 4 --> 3

// Let's introduce a dummy node that points to the head:
var dummy = new ListNode(0, head);
var dummy = new ListNode(default, head);

// [dummy,next is [1]] --> [1,next is [2]] --> [2,next is [3]] --> [3,next is [4]] --> [4,next is null]

// Let's create a few helper pointers:
var (prev, current) = (dummy, dummy.next);
var (prev, current) = (dummy, next: dummy.Next);

Check warning on line 17 in LeetCode/src/LeetCode.Challenges/Problems0XX/P024_SwapNodesInPairs/Solutions.cs

View workflow job for this annotation

GitHub Actions / build

The tuple element name 'next' is ignored because a different name or no name is specified by the target type '(ListNode, ListNode)'.

Check warning on line 17 in LeetCode/src/LeetCode.Challenges/Problems0XX/P024_SwapNodesInPairs/Solutions.cs

View workflow job for this annotation

GitHub Actions / build

The tuple element name 'next' is ignored because a different name or no name is specified by the target type '(ListNode, ListNode)'.

// [dummy,next is [1]] --> [1,next is [2]] --> [2,next is [3]] --> [3,next is [4]] --> [4,next is null]
// ^ ^
// prev current

// Because we need to swap every two adjacent nodes (?).
while (current != null && current.next != null)
while (current != null && current.Next != null)
{
// STEP 1: Save pointers.
var nextPair = current.next.next;
var second = current.next;
var nextPair = current.Next.Next;
var second = current.Next;

// [dummy,next is [1]] --> [1,next is [2]] --> [2,next is [3]] --> [3,next is [4]] --> [4,next is null]
// ^ ^ ^ ^
Expand All @@ -39,17 +39,17 @@ public static class Solution
// STEP 2: Swap nodes.
// Step 2.1:
// [2,next is [1]] --> [1,next is [2]]
second.next = current;
second.Next = current;

// Step 2.2:
// [2,next is [1]] --> [1,next is [3]] --> [3,next is [4]]
current.next = nextPair;
current.Next = nextPair;

// Step 2.3:
// [dummy,next is [2]] --> [2,next is [1]] --> [1,next is [3]] --> [3,next is [4]]
// ^ ^
// prev prev.next
prev.next = second;
prev.Next = second;

// Update pointers.

Expand All @@ -69,6 +69,6 @@ public static class Solution
// current
}

return dummy.next;
return dummy.Next;
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
using System.Collections;
using LeetCode.Challenges.RemoveNthNodeFromListEnd;
using LeetCode.Challenges.Problems0XX.P019_RemoveNthNodeFromTheEndOfList;

namespace LeetCode.Challenges.UnitTests.RemoveNthNodeFromListEnd;
namespace LeetCode.Challenges.UnitTests.Problems0XX.P019_RemoveNthNodeFromTheEndOfList;

public class TestData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
// 1 --> 2 --> 3 --> 4 --> 5 --> null
// 1 --> 2 --> 3 --> 5 --> null
var head = new ListNode(1, new ListNode(2, new ListNode(3, new ListNode(4, new ListNode(5)))));
var expected = new ListNode(1, new ListNode(2, new ListNode(3, new ListNode(5))));
yield return [ head, 2, expected ];

// 1 --> null
// null
head = new ListNode(1);
yield return [ head, 1, null ];
yield return [ head, 1, null! ];

// 1 --> 2
// 1 --> null
head = new ListNode(1, new ListNode(2));
yield return [ head, 1, new ListNode(1) ];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using LeetCode.Challenges.Problems0XX.P019_RemoveNthNodeFromTheEndOfList;
using Shouldly;
using Xunit;

namespace LeetCode.Challenges.UnitTests.Problems0XX.P019_RemoveNthNodeFromTheEndOfList;

public class TwoPointerSolutionTests
{
[Theory]
[ClassData(typeof(TestData))]
public void GivenListAndNodeNumber_WhenRemoveNthFromEnd_ThenResultAsExpected(
ListNode head, int n, ListNode? expectedResult)
{
TwoPointerSolution.RemoveNthFromEnd(head, n).ShouldBeEquivalentTo(expectedResult);
}
}

This file was deleted.

0 comments on commit a3a4d89

Please sign in to comment.