-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Add algorithms for 2Sum, 3Sum, Kadane's Algorithm, and linked list pr... #1716
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// threeSum.js | ||
|
||
/** | ||
* Time Complexity: O(n^2) — The outer loop runs in O(n), and the inner two-pointer approach runs in O(n). | ||
Space Complexity: O(1) — The output list is the only extra space used (not counting input). | ||
* | ||
* | ||
* Finds all unique triplets in the array that sum up to zero. | ||
* @param {number[]} nums - An array of numbers. | ||
* @returns {number[][]} - A list of unique triplets. | ||
*/ | ||
function threeSum(nums) { | ||
const result = []; | ||
nums.sort((a, b) => a - b); // Sort the array | ||
|
||
for (let i = 0; i < nums.length - 2; i++) { | ||
// Skip duplicate values | ||
if (i > 0 && nums[i] === nums[i - 1]) continue; | ||
|
||
let left = i + 1; | ||
let right = nums.length - 1; | ||
|
||
while (left < right) { | ||
const sum = nums[i] + nums[left] + nums[right]; | ||
|
||
if (sum === 0) { | ||
result.push([nums[i], nums[left], nums[right]]); | ||
while (left < right && nums[left] === nums[left + 1]) left++; // Skip duplicates | ||
while (left < right && nums[right] === nums[right - 1]) right--; // Skip duplicates | ||
left++; | ||
right--; | ||
} else if (sum < 0) { | ||
left++; | ||
} else { | ||
right--; | ||
} | ||
} | ||
} | ||
|
||
return result; // Return the list of triplets | ||
} | ||
|
||
export { threeSum } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
|
||
// kadanesAlgorithm.js | ||
|
||
/** | ||
* | ||
* | ||
* Time Complexity: O(n) — The algorithm processes each element of the array once. | ||
Space Complexity: O(1) — Only a constant amount of additional space is used. | ||
|
||
|
||
* Finds the maximum sum of a contiguous subarray using Kadane's Algorithm. | ||
* @param {number[]} nums - An array of numbers. | ||
* @returns {number} - The maximum sum of the contiguous subarray. | ||
*/ | ||
function kadane(nums) { | ||
let maxSoFar = nums[0]; | ||
let maxEndingHere = nums[0]; | ||
|
||
for (let i = 1; i < nums.length; i++) { | ||
maxEndingHere = Math.max(nums[i], maxEndingHere + nums[i]); | ||
maxSoFar = Math.max(maxSoFar, maxEndingHere); | ||
} | ||
|
||
return maxSoFar; // Return the maximum sum | ||
} | ||
|
||
export { kadane } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { threeSum } from '../3sum.js'; // Adjust the path as necessary | ||
|
||
describe('Three Sum', () => { | ||
it('should return all unique triplets that add up to zero', () => { | ||
const nums = [-1, 0, 1, 2, -1, -4]; | ||
const expected = [[-1, -1, 2], [-1, 0, 1]]; | ||
const result = threeSum(nums); | ||
expect(result).toEqual(expected); | ||
}); | ||
|
||
// Add more test cases as needed | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { kadane } from '../KandanesAlgo.js'; // Adjust the path as necessary | ||
|
||
describe('Kadane\'s Algorithm', () => { | ||
it('should return the maximum sum of a contiguous subarray', () => { | ||
const nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]; | ||
const expected = 6; // 4 + -1 + 2 + 1 | ||
const result = kadane(nums); | ||
expect(result).toBe(expected); | ||
}); | ||
|
||
// Add more test cases as needed | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// FindIntersectionPoint.js | ||
|
||
// Definition for singly-linked list node | ||
class ListNode { | ||
constructor(value) { | ||
this.value = value; | ||
this.next = null; | ||
} | ||
} | ||
|
||
/** | ||
* Finds the intersection point of two linked lists. | ||
* @param {ListNode} headA - The head of the first linked list. | ||
* @param {ListNode} headB - The head of the second linked list. | ||
* @returns {ListNode|null} The intersection node or null if no intersection. | ||
*/ | ||
function findIntersection(headA, headB) { | ||
if (!headA || !headB) return null; | ||
|
||
let a = headA; | ||
let b = headB; | ||
|
||
// Traverse both lists | ||
while (a !== b) { | ||
a = a ? a.next : headB; // When reaching the end of list A, redirect to list B | ||
b = b ? b.next : headA; // When reaching the end of list B, redirect to list A | ||
} | ||
|
||
return a; // This will be either the intersection node or null | ||
} | ||
|
||
export { ListNode, findIntersection }; // Ensure ListNode is exported |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// SlowFast.js | ||
|
||
// Definition for singly-linked list node | ||
class ListNode { | ||
constructor(value) { | ||
this.value = value; | ||
this.next = null; | ||
} | ||
} | ||
|
||
/** | ||
* Detects if a linked list has a cycle. | ||
* @param {ListNode} head - The head of the linked list. | ||
* @returns {boolean} - True if there's a cycle, false otherwise. | ||
*/ | ||
function hasCycle(head) { | ||
let slow = head; | ||
let fast = head; | ||
|
||
while (fast && fast.next) { | ||
slow = slow.next; // Move slow pointer one step | ||
fast = fast.next.next; // Move fast pointer two steps | ||
|
||
if (slow === fast) { | ||
return true; // Cycle detected | ||
} | ||
} | ||
return false; // No cycle | ||
} | ||
|
||
/** | ||
* Creates a linked list from an array of values. | ||
* @param {Array<number>} values - The values to create the linked list from. | ||
* @returns {ListNode|null} - The head of the created linked list. | ||
*/ | ||
function createLinkedList(values) { | ||
const dummyHead = new ListNode(0); | ||
let current = dummyHead; | ||
|
||
for (const value of values) { | ||
current.next = new ListNode(value); | ||
current = current.next; | ||
} | ||
|
||
return dummyHead.next; // Return the head of the created linked list | ||
} | ||
|
||
// Exporting the ListNode class and functions for testing | ||
export { ListNode, hasCycle, createLinkedList }; // Ensure ListNode is exported |
25 changes: 25 additions & 0 deletions
Data-Structures/Linked-List/test/FindIntersectionpoint.test.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// FindIntersectionPoint.test.js | ||
|
||
import { ListNode, findIntersection } from '../FindIntersectionPoint.js'; // Ensure the path is correct | ||
import { createLinkedList } from '../SlowFast.js'; // Ensure the path is correct | ||
|
||
describe('Find Intersection Point', () => { | ||
it('should find the intersection point in two linked lists', () => { | ||
// Create linked list 1: 1 -> 2 -> 3 -> 6 -> 7 | ||
const list1 = createLinkedList([1, 2, 3]); | ||
const intersection = new ListNode(6); // ListNode should be correctly imported | ||
intersection.next = new ListNode(7); | ||
list1.next.next.next = intersection; // Connect 3 -> 6 | ||
|
||
// Create linked list 2: 4 -> 5 -> 6 -> 7 | ||
const list2 = createLinkedList([4, 5]); | ||
list2.next.next = intersection; // Connect 5 -> 6 | ||
|
||
const expected = intersection; // We expect the intersection node | ||
|
||
const result = findIntersection(list1, list2); | ||
expect(result).toBe(expected); // Check if the result matches the expected output | ||
}); | ||
|
||
// Additional test cases can be added here | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// slowfast.test.js | ||
|
||
import { ListNode, hasCycle, createLinkedList } from '../SlowFast.js'; // Adjust the path as necessary | ||
|
||
describe('Slow and Fast Pointer', () => { | ||
it('should detect if a linked list has a cycle', () => { | ||
// Create a linked list: 1 -> 2 -> 3 -> 4 -> 5 -> (cycle to 3) | ||
const node1 = new ListNode(1); | ||
const node2 = new ListNode(2); | ||
const node3 = new ListNode(3); | ||
const node4 = new ListNode(4); | ||
const node5 = new ListNode(5); | ||
|
||
node1.next = node2; | ||
node2.next = node3; | ||
node3.next = node4; | ||
node4.next = node5; | ||
node5.next = node3; // Create a cycle here | ||
|
||
const result = hasCycle(node1); | ||
expect(result).toBe(true); // Expecting a cycle | ||
}); | ||
|
||
it('should not detect a cycle in a linear linked list', () => { | ||
// Create a linked list: 1 -> 2 -> 3 | ||
const head = createLinkedList([1, 2, 3]); | ||
|
||
const result = hasCycle(head); | ||
expect(result).toBe(false); // Expecting no cycle | ||
}); | ||
}); | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.