From 08d23006a33f038ce60f17aa79e91f60032e7453 Mon Sep 17 00:00:00 2001 From: karan1_2 Date: Sun, 6 Oct 2024 12:50:22 +0530 Subject: [PATCH 1/4] Add algorithms for 2Sum, 3Sum, Kadane's Algorithm, and linked list problems --- Data-Structures/Array/2Sum.js | 26 +++++++ Data-Structures/Array/3sum.js | 41 ++++++++++ Data-Structures/Array/KandanesAlgo.js | 25 ++++++ Data-Structures/Array/test/2sum.test.js | 34 ++++++++ Data-Structures/Array/test/3sum.test.js | 30 ++++++++ .../Array/test/KadanesAlgo.test.js | 35 +++++++++ .../Linked-List/FindIntersectionPoint.js | 39 ++++++++++ Data-Structures/Linked-List/SlowFast.js | 77 +++++++++++++++++++ .../test/FindIntersectionpoint.test.js | 44 +++++++++++ .../Linked-List/test/slowfast.test.js | 49 ++++++++++++ 10 files changed, 400 insertions(+) create mode 100644 Data-Structures/Array/2Sum.js create mode 100644 Data-Structures/Array/3sum.js create mode 100644 Data-Structures/Array/KandanesAlgo.js create mode 100644 Data-Structures/Array/test/2sum.test.js create mode 100644 Data-Structures/Array/test/3sum.test.js create mode 100644 Data-Structures/Array/test/KadanesAlgo.test.js create mode 100644 Data-Structures/Linked-List/FindIntersectionPoint.js create mode 100644 Data-Structures/Linked-List/SlowFast.js create mode 100644 Data-Structures/Linked-List/test/FindIntersectionpoint.test.js create mode 100644 Data-Structures/Linked-List/test/slowfast.test.js diff --git a/Data-Structures/Array/2Sum.js b/Data-Structures/Array/2Sum.js new file mode 100644 index 0000000000..a710cf0950 --- /dev/null +++ b/Data-Structures/Array/2Sum.js @@ -0,0 +1,26 @@ +// twoSum.js + +/** + * + * Time Complexity: O(n) — We traverse the list once while storing elements in a hash map. +Space Complexity: O(n) — In the worst case, we store all elements in the hash map. + + + * Finds indices of the two numbers such that they add up to a specific target. + * @param {number[]} nums - An array of numbers. + * @param {number} target - The target sum. + * @returns {number[]|null} - Indices of the two numbers or null if not found. + */ +export function twoSum(nums, target) { + const map = new Map(); + + for (let i = 0; i < nums.length; i++) { + const complement = target - nums[i]; + if (map.has(complement)) { + return [map.get(complement), i]; + } + map.set(nums[i], i); + } + + return null; // No two sum solution +} diff --git a/Data-Structures/Array/3sum.js b/Data-Structures/Array/3sum.js new file mode 100644 index 0000000000..44319750b4 --- /dev/null +++ b/Data-Structures/Array/3sum.js @@ -0,0 +1,41 @@ +// 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. + */ +export 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 +} diff --git a/Data-Structures/Array/KandanesAlgo.js b/Data-Structures/Array/KandanesAlgo.js new file mode 100644 index 0000000000..22df0a1f12 --- /dev/null +++ b/Data-Structures/Array/KandanesAlgo.js @@ -0,0 +1,25 @@ + +// 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. + */ +export function maxSubArray(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 +} diff --git a/Data-Structures/Array/test/2sum.test.js b/Data-Structures/Array/test/2sum.test.js new file mode 100644 index 0000000000..b3f7c7919f --- /dev/null +++ b/Data-Structures/Array/test/2sum.test.js @@ -0,0 +1,34 @@ +// test.js + +import { twoSum } from '../2Sum'; + + + +function testTwoSum() { + // Test Case 1: Basic case + let nums = [2, 7, 11, 15]; + let target = 9; + let result = twoSum(nums, target); + console.assert(JSON.stringify(result) === JSON.stringify([0, 1]), `Expected [0, 1], got ${result}`); + + // Test Case 2: No solution + nums = [1, 2, 3]; + target = 6; + result = twoSum(nums, target); + console.assert(result === null, `Expected null, got ${result}`); + + // Test Case 3: Duplicate values + nums = [3, 2, 4]; + target = 6; + result = twoSum(nums, target); + console.assert(JSON.stringify(result) === JSON.stringify([1, 2]), `Expected [1, 2], got ${result}`); + + // Test Case 4: Negative numbers + nums = [-3, 4, 3, 90]; + target = 0; + result = twoSum(nums, target); + console.assert(JSON.stringify(result) === JSON.stringify([0, 2]), `Expected [0, 2], got ${result}`); + + console.log("All 2-Sum tests passed!"); +} +testTwoSum(); diff --git a/Data-Structures/Array/test/3sum.test.js b/Data-Structures/Array/test/3sum.test.js new file mode 100644 index 0000000000..d459257bbb --- /dev/null +++ b/Data-Structures/Array/test/3sum.test.js @@ -0,0 +1,30 @@ +// test.js + + +import { threeSum } from '../3sum'; +function testThreeSum() { + // Test Case 1: Basic case + let nums = [-1, 0, 1, 2, -1, -4]; + let result = threeSum(nums); + console.assert(JSON.stringify(result) === JSON.stringify([[-1, -1, 2], [-1, 0, 1]]), `Expected [[-1, -1, 2], [-1, 0, 1]], got ${JSON.stringify(result)}`); + + // Test Case 2: No triplet + nums = [1, 2, 3]; + result = threeSum(nums); + console.assert(JSON.stringify(result) === JSON.stringify([]), `Expected [], got ${JSON.stringify(result)}`); + + // Test Case 3: Duplicate triplets + nums = [-2, 0, 0, 2, 2]; + result = threeSum(nums); + console.assert(JSON.stringify(result) === JSON.stringify([[-2, 0, 2]]), `Expected [[-2, 0, 2]], got ${JSON.stringify(result)}`); + + // Test Case 4: All negative numbers + nums = [-1, -2, -3, -4]; + result = threeSum(nums); + console.assert(JSON.stringify(result) === JSON.stringify([]), `Expected [], got ${JSON.stringify(result)}`); + + console.log("All 3-Sum tests passed!"); +} + +// Run the tests +testThreeSum(); diff --git a/Data-Structures/Array/test/KadanesAlgo.test.js b/Data-Structures/Array/test/KadanesAlgo.test.js new file mode 100644 index 0000000000..fedff034bb --- /dev/null +++ b/Data-Structures/Array/test/KadanesAlgo.test.js @@ -0,0 +1,35 @@ +// testKadanesAlgorithm.js + +import { maxSubArray } from '../KandanesAlgo.js'; + +function runKadaneTests() { + // Test Case 1: Basic case + let nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]; + let result = maxSubArray(nums); + console.assert(result === 6, `Expected 6, got ${result}`); + + // Test Case 2: All negative numbers + nums = [-1, -2, -3, -4]; + result = maxSubArray(nums); + console.assert(result === -1, `Expected -1, got ${result}`); + + // Test Case 3: All positive numbers + nums = [1, 2, 3, 4]; + result = maxSubArray(nums); + console.assert(result === 10, `Expected 10, got ${result}`); + + // Test Case 4: Mixed numbers with zero + nums = [0, -1, 2, 3, -2, 5, -3]; + result = maxSubArray(nums); + console.assert(result === 8, `Expected 8, got ${result}`); + + // Test Case 5: Single element + nums = [-5]; + result = maxSubArray(nums); + console.assert(result === -5, `Expected -5, got ${result}`); + + console.log("All Kadane's Algorithm tests passed!"); +} + +// Run the tests +runKadaneTests(); diff --git a/Data-Structures/Linked-List/FindIntersectionPoint.js b/Data-Structures/Linked-List/FindIntersectionPoint.js new file mode 100644 index 0000000000..6a504accf5 --- /dev/null +++ b/Data-Structures/Linked-List/FindIntersectionPoint.js @@ -0,0 +1,39 @@ + + +/** + * Calculates the intersection point of two lines + * defined by the points (x1, y1) to (x2, y2) and (x3, y3) to (x4, y4). + * + * @param {number} x1 - x-coordinate of the first point of the first line + * @param {number} y1 - y-coordinate of the first point of the first line + * @param {number} x2 - x-coordinate of the second point of the first line + * @param {number} y2 - y-coordinate of the second point of the first line + * @param {number} x3 - x-coordinate of the first point of the second line + * @param {number} y3 - y-coordinate of the first point of the second line + * @param {number} x4 - x-coordinate of the second point of the second line + * @param {number} y4 - y-coordinate of the second point of the second line + * @returns {Object|null} The intersection point { x, y } or null if no intersection + */ + +export function findIntersection(x1, y1, x2, y2, x3, y3, x4, y4) { + const denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); + + // Lines are parallel if denom is zero + if (denom === 0) { + return null; // No intersection + } + + const ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom; + const ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom; + + // Check if intersection is within the segments + if (ua < 0 || ua > 1 || ub < 0 || ub > 1) { + return null; // Intersection not within the segments + } + + // Calculate the intersection point + const intersectionX = x1 + ua * (x2 - x1); + const intersectionY = y1 + ua * (y2 - y1); + + return { x: intersectionX, y: intersectionY }; +} \ No newline at end of file diff --git a/Data-Structures/Linked-List/SlowFast.js b/Data-Structures/Linked-List/SlowFast.js new file mode 100644 index 0000000000..d16f7ae3e0 --- /dev/null +++ b/Data-Structures/Linked-List/SlowFast.js @@ -0,0 +1,77 @@ +// 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. + */ +export 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 +} + +/** + * Finds the middle element of a linked list. + * @param {ListNode} head - The head of the linked list. + * @returns {ListNode|null} - The middle node or null if the list is empty. + */ +export function findMiddle(head) { + if (!head) return null; + + 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 + } + return slow; // Slow pointer is at the middle +} + +/** + * Detects the start of the cycle in a linked list. + * @param {ListNode} head - The head of the linked list. + * @returns {ListNode|null} - The node where the cycle starts or null if there is no cycle. + */ +export function detectCycle(head) { + let slow = head; + let fast = head; + + // First phase: determine if a cycle exists + while (fast && fast.next) { + slow = slow.next; + fast = fast.next.next; + + if (slow === fast) { + // Cycle detected + let entry = head; + while (entry !== slow) { + entry = entry.next; // Move entry pointer + slow = slow.next; // Move slow pointer + } + return entry; // Start of the cycle + } + } + return null; // No cycle +} + +// Exporting the ListNode class for testing +export { ListNode }; diff --git a/Data-Structures/Linked-List/test/FindIntersectionpoint.test.js b/Data-Structures/Linked-List/test/FindIntersectionpoint.test.js new file mode 100644 index 0000000000..305f2596ad --- /dev/null +++ b/Data-Structures/Linked-List/test/FindIntersectionpoint.test.js @@ -0,0 +1,44 @@ + +import { findIntersection } from '../FindIntersectionPoint'; + +function runTests() { + const tests = [ + { + desc: 'Intersecting lines', + input: [0, 0, 2, 2, 0, 2, 2, 0], + expected: { x: 1, y: 1 } + }, + { + desc: 'Parallel lines (no intersection)', + input: [0, 0, 2, 2, 0, 1, 2, 3], + expected: null + }, + { + desc: 'Overlap lines (fully overlapping)', + input: [0, 0, 2, 2, 1, 1, 3, 3], + expected: { x: 1, y: 1 } + }, + { + desc: 'Non-intersecting lines (far apart)', + input: [0, 0, 1, 1, 2, 2, 3, 3], + expected: null + }, + { + desc: 'Intersecting at an endpoint', + input: [0, 0, 2, 2, 2, 0, 0, 2], + expected: { x: 2, y: 2 } + } + ]; + + tests.forEach(({ desc, input, expected }, index) => { + const result = findIntersection(...input); + const isPassed = JSON.stringify(result) === JSON.stringify(expected); + console.log(`Test ${index + 1}: ${desc} - ${isPassed ? 'Passed' : 'Failed'}`); + if (!isPassed) { + console.log(` Expected: ${JSON.stringify(expected)}, Got: ${JSON.stringify(result)}`); + } + }); +} + +// Run the tests +runTests(); diff --git a/Data-Structures/Linked-List/test/slowfast.test.js b/Data-Structures/Linked-List/test/slowfast.test.js new file mode 100644 index 0000000000..37b4fd2117 --- /dev/null +++ b/Data-Structures/Linked-List/test/slowfast.test.js @@ -0,0 +1,49 @@ +// test.js + +import { ListNode, hasCycle, findMiddle, detectCycle } from '../SlowFast.js'; + +function createLinkedList(arr) { + let head = null; + let current = null; + + for (let value of arr) { + const newNode = new ListNode(value); + if (!head) { + head = newNode; + current = newNode; + } else { + current.next = newNode; + current = newNode; + } + } + + return head; +} + +function runTests() { + // Test Case 1: Cycle detection + const cycleList = createLinkedList([1, 2, 3]); + cycleList.next.next.next = cycleList.next; // Creates a cycle (3 -> 2) + console.log(`Test 1: Cycle exists - ${hasCycle(cycleList) ? 'Passed' : 'Failed'}`); + + // Test Case 2: No cycle + const noCycleList = createLinkedList([1, 2, 3]); + console.log(`Test 2: No cycle - ${!hasCycle(noCycleList) ? 'Passed' : 'Failed'}`); + + // Test Case 3: Finding the middle element + const midList = createLinkedList([1, 2, 3, 4, 5]); + const midNode = findMiddle(midList); + console.log(`Test 3: Middle element - Expected: 3, Got: ${midNode.value} - ${midNode.value === 3 ? 'Passed' : 'Failed'}`); + + // Test Case 4: Finding the start of the cycle + const cycleStartList = createLinkedList([1, 2, 3]); + cycleStartList.next.next.next = cycleStartList.next; // Creates a cycle (3 -> 2) + const startNode = detectCycle(cycleStartList); + console.log(`Test 4: Start of cycle - Expected: 2, Got: ${startNode ? startNode.value : 'null'} - ${startNode && startNode.value === 2 ? 'Passed' : 'Failed'}`); + + // Test Case 5: No cycle in detectCycle + console.log(`Test 5: No cycle - Expected: null, Got: ${detectCycle(noCycleList) ? detectCycle(noCycleList).value : 'null'} - ${detectCycle(noCycleList) === null ? 'Passed' : 'Failed'}`); +} + +// Run the tests +runTests(); From d5cef9d8040dde25623d6f762048f2caa8b2879f Mon Sep 17 00:00:00 2001 From: karan1_2 Date: Sun, 6 Oct 2024 14:31:14 +0530 Subject: [PATCH 2/4] fix test case --- Data-Structures/Array/2Sum.js | 4 +- Data-Structures/Array/3sum.js | 4 +- Data-Structures/Array/KandanesAlgo.js | 4 +- Data-Structures/Array/test/2sum.test.js | 47 +++-------- Data-Structures/Array/test/3sum.test.js | 42 +++------- .../Array/test/KadanesAlgo.test.js | 47 +++-------- .../Linked-List/FindIntersectionPoint.js | 53 ++++++------- Data-Structures/Linked-List/SlowFast.js | 56 ++++--------- .../test/FindIntersectionpoint.test.js | 61 +++++--------- .../Linked-List/test/slowfast.test.js | 79 ++++++++----------- 10 files changed, 135 insertions(+), 262 deletions(-) diff --git a/Data-Structures/Array/2Sum.js b/Data-Structures/Array/2Sum.js index a710cf0950..cab05cc368 100644 --- a/Data-Structures/Array/2Sum.js +++ b/Data-Structures/Array/2Sum.js @@ -11,7 +11,7 @@ Space Complexity: O(n) — In the worst case, we store all elements in the hash * @param {number} target - The target sum. * @returns {number[]|null} - Indices of the two numbers or null if not found. */ -export function twoSum(nums, target) { +function twoSum(nums, target) { const map = new Map(); for (let i = 0; i < nums.length; i++) { @@ -24,3 +24,5 @@ export function twoSum(nums, target) { return null; // No two sum solution } + +export { twoSum } \ No newline at end of file diff --git a/Data-Structures/Array/3sum.js b/Data-Structures/Array/3sum.js index 44319750b4..37969b817a 100644 --- a/Data-Structures/Array/3sum.js +++ b/Data-Structures/Array/3sum.js @@ -9,7 +9,7 @@ Space Complexity: O(1) — The output list is the only extra space used (not cou * @param {number[]} nums - An array of numbers. * @returns {number[][]} - A list of unique triplets. */ -export function threeSum(nums) { +function threeSum(nums) { const result = []; nums.sort((a, b) => a - b); // Sort the array @@ -39,3 +39,5 @@ export function threeSum(nums) { return result; // Return the list of triplets } + +export { threeSum } \ No newline at end of file diff --git a/Data-Structures/Array/KandanesAlgo.js b/Data-Structures/Array/KandanesAlgo.js index 22df0a1f12..6816a14c2b 100644 --- a/Data-Structures/Array/KandanesAlgo.js +++ b/Data-Structures/Array/KandanesAlgo.js @@ -12,7 +12,7 @@ Space Complexity: O(1) — Only a constant amount of additional space is used. * @param {number[]} nums - An array of numbers. * @returns {number} - The maximum sum of the contiguous subarray. */ -export function maxSubArray(nums) { +function kadane(nums) { let maxSoFar = nums[0]; let maxEndingHere = nums[0]; @@ -23,3 +23,5 @@ export function maxSubArray(nums) { return maxSoFar; // Return the maximum sum } + +export { kadane } \ No newline at end of file diff --git a/Data-Structures/Array/test/2sum.test.js b/Data-Structures/Array/test/2sum.test.js index b3f7c7919f..ad23e831c6 100644 --- a/Data-Structures/Array/test/2sum.test.js +++ b/Data-Structures/Array/test/2sum.test.js @@ -1,34 +1,13 @@ -// test.js - -import { twoSum } from '../2Sum'; - - - -function testTwoSum() { - // Test Case 1: Basic case - let nums = [2, 7, 11, 15]; - let target = 9; - let result = twoSum(nums, target); - console.assert(JSON.stringify(result) === JSON.stringify([0, 1]), `Expected [0, 1], got ${result}`); - - // Test Case 2: No solution - nums = [1, 2, 3]; - target = 6; - result = twoSum(nums, target); - console.assert(result === null, `Expected null, got ${result}`); - - // Test Case 3: Duplicate values - nums = [3, 2, 4]; - target = 6; - result = twoSum(nums, target); - console.assert(JSON.stringify(result) === JSON.stringify([1, 2]), `Expected [1, 2], got ${result}`); - - // Test Case 4: Negative numbers - nums = [-3, 4, 3, 90]; - target = 0; - result = twoSum(nums, target); - console.assert(JSON.stringify(result) === JSON.stringify([0, 2]), `Expected [0, 2], got ${result}`); - - console.log("All 2-Sum tests passed!"); -} -testTwoSum(); +import { twoSum } from '../2Sum.js'; // Adjust the path as necessary + +describe('Two Sum', () => { + it('should return indices of the two numbers such that they add up to a specific target', () => { + const nums = [2, 7, 11, 15]; + const target = 9; + const expected = [0, 1]; + const result = twoSum(nums, target); + expect(result).toEqual(expected); + }); + + // Add more test cases as needed +}); diff --git a/Data-Structures/Array/test/3sum.test.js b/Data-Structures/Array/test/3sum.test.js index d459257bbb..13d868ef87 100644 --- a/Data-Structures/Array/test/3sum.test.js +++ b/Data-Structures/Array/test/3sum.test.js @@ -1,30 +1,12 @@ -// test.js - - -import { threeSum } from '../3sum'; -function testThreeSum() { - // Test Case 1: Basic case - let nums = [-1, 0, 1, 2, -1, -4]; - let result = threeSum(nums); - console.assert(JSON.stringify(result) === JSON.stringify([[-1, -1, 2], [-1, 0, 1]]), `Expected [[-1, -1, 2], [-1, 0, 1]], got ${JSON.stringify(result)}`); - - // Test Case 2: No triplet - nums = [1, 2, 3]; - result = threeSum(nums); - console.assert(JSON.stringify(result) === JSON.stringify([]), `Expected [], got ${JSON.stringify(result)}`); - - // Test Case 3: Duplicate triplets - nums = [-2, 0, 0, 2, 2]; - result = threeSum(nums); - console.assert(JSON.stringify(result) === JSON.stringify([[-2, 0, 2]]), `Expected [[-2, 0, 2]], got ${JSON.stringify(result)}`); - - // Test Case 4: All negative numbers - nums = [-1, -2, -3, -4]; - result = threeSum(nums); - console.assert(JSON.stringify(result) === JSON.stringify([]), `Expected [], got ${JSON.stringify(result)}`); - - console.log("All 3-Sum tests passed!"); -} - -// Run the tests -testThreeSum(); +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 +}); diff --git a/Data-Structures/Array/test/KadanesAlgo.test.js b/Data-Structures/Array/test/KadanesAlgo.test.js index fedff034bb..c7fe4b11ff 100644 --- a/Data-Structures/Array/test/KadanesAlgo.test.js +++ b/Data-Structures/Array/test/KadanesAlgo.test.js @@ -1,35 +1,12 @@ -// testKadanesAlgorithm.js - -import { maxSubArray } from '../KandanesAlgo.js'; - -function runKadaneTests() { - // Test Case 1: Basic case - let nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]; - let result = maxSubArray(nums); - console.assert(result === 6, `Expected 6, got ${result}`); - - // Test Case 2: All negative numbers - nums = [-1, -2, -3, -4]; - result = maxSubArray(nums); - console.assert(result === -1, `Expected -1, got ${result}`); - - // Test Case 3: All positive numbers - nums = [1, 2, 3, 4]; - result = maxSubArray(nums); - console.assert(result === 10, `Expected 10, got ${result}`); - - // Test Case 4: Mixed numbers with zero - nums = [0, -1, 2, 3, -2, 5, -3]; - result = maxSubArray(nums); - console.assert(result === 8, `Expected 8, got ${result}`); - - // Test Case 5: Single element - nums = [-5]; - result = maxSubArray(nums); - console.assert(result === -5, `Expected -5, got ${result}`); - - console.log("All Kadane's Algorithm tests passed!"); -} - -// Run the tests -runKadaneTests(); +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 +}); diff --git a/Data-Structures/Linked-List/FindIntersectionPoint.js b/Data-Structures/Linked-List/FindIntersectionPoint.js index 6a504accf5..58d87ca0c0 100644 --- a/Data-Structures/Linked-List/FindIntersectionPoint.js +++ b/Data-Structures/Linked-List/FindIntersectionPoint.js @@ -1,39 +1,32 @@ +// FindIntersectionPoint.js +// Definition for singly-linked list node +class ListNode { + constructor(value) { + this.value = value; + this.next = null; + } +} /** - * Calculates the intersection point of two lines - * defined by the points (x1, y1) to (x2, y2) and (x3, y3) to (x4, y4). - * - * @param {number} x1 - x-coordinate of the first point of the first line - * @param {number} y1 - y-coordinate of the first point of the first line - * @param {number} x2 - x-coordinate of the second point of the first line - * @param {number} y2 - y-coordinate of the second point of the first line - * @param {number} x3 - x-coordinate of the first point of the second line - * @param {number} y3 - y-coordinate of the first point of the second line - * @param {number} x4 - x-coordinate of the second point of the second line - * @param {number} y4 - y-coordinate of the second point of the second line - * @returns {Object|null} The intersection point { x, y } or null if no intersection + * 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; -export function findIntersection(x1, y1, x2, y2, x3, y3, x4, y4) { - const denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); - - // Lines are parallel if denom is zero - if (denom === 0) { - return null; // No intersection - } - - const ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom; - const ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom; + let a = headA; + let b = headB; - // Check if intersection is within the segments - if (ua < 0 || ua > 1 || ub < 0 || ub > 1) { - return null; // Intersection not within the segments + // 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 } - // Calculate the intersection point - const intersectionX = x1 + ua * (x2 - x1); - const intersectionY = y1 + ua * (y2 - y1); + return a; // This will be either the intersection node or null +} - return { x: intersectionX, y: intersectionY }; -} \ No newline at end of file +export { ListNode, findIntersection }; // Ensure ListNode is exported diff --git a/Data-Structures/Linked-List/SlowFast.js b/Data-Structures/Linked-List/SlowFast.js index d16f7ae3e0..001de0579e 100644 --- a/Data-Structures/Linked-List/SlowFast.js +++ b/Data-Structures/Linked-List/SlowFast.js @@ -1,4 +1,4 @@ -// slowFast.js +// SlowFast.js // Definition for singly-linked list node class ListNode { @@ -13,7 +13,7 @@ class ListNode { * @param {ListNode} head - The head of the linked list. * @returns {boolean} - True if there's a cycle, false otherwise. */ -export function hasCycle(head) { +function hasCycle(head) { let slow = head; let fast = head; @@ -29,49 +29,21 @@ export function hasCycle(head) { } /** - * Finds the middle element of a linked list. - * @param {ListNode} head - The head of the linked list. - * @returns {ListNode|null} - The middle node or null if the list is empty. + * Creates a linked list from an array of values. + * @param {Array} values - The values to create the linked list from. + * @returns {ListNode|null} - The head of the created linked list. */ -export function findMiddle(head) { - if (!head) return null; - - let slow = head; - let fast = head; +function createLinkedList(values) { + const dummyHead = new ListNode(0); + let current = dummyHead; - while (fast && fast.next) { - slow = slow.next; // Move slow pointer one step - fast = fast.next.next; // Move fast pointer two steps + for (const value of values) { + current.next = new ListNode(value); + current = current.next; } - return slow; // Slow pointer is at the middle -} - -/** - * Detects the start of the cycle in a linked list. - * @param {ListNode} head - The head of the linked list. - * @returns {ListNode|null} - The node where the cycle starts or null if there is no cycle. - */ -export function detectCycle(head) { - let slow = head; - let fast = head; - // First phase: determine if a cycle exists - while (fast && fast.next) { - slow = slow.next; - fast = fast.next.next; - - if (slow === fast) { - // Cycle detected - let entry = head; - while (entry !== slow) { - entry = entry.next; // Move entry pointer - slow = slow.next; // Move slow pointer - } - return entry; // Start of the cycle - } - } - return null; // No cycle + return dummyHead.next; // Return the head of the created linked list } -// Exporting the ListNode class for testing -export { ListNode }; +// Exporting the ListNode class and functions for testing +export { ListNode, hasCycle, createLinkedList }; // Ensure ListNode is exported diff --git a/Data-Structures/Linked-List/test/FindIntersectionpoint.test.js b/Data-Structures/Linked-List/test/FindIntersectionpoint.test.js index 305f2596ad..5ee820f8f8 100644 --- a/Data-Structures/Linked-List/test/FindIntersectionpoint.test.js +++ b/Data-Structures/Linked-List/test/FindIntersectionpoint.test.js @@ -1,44 +1,25 @@ +// FindIntersectionPoint.test.js -import { findIntersection } from '../FindIntersectionPoint'; +import { ListNode, findIntersection } from '../FindIntersectionPoint.js'; // Ensure the path is correct +import { createLinkedList } from '../SlowFast.js'; // Ensure the path is correct -function runTests() { - const tests = [ - { - desc: 'Intersecting lines', - input: [0, 0, 2, 2, 0, 2, 2, 0], - expected: { x: 1, y: 1 } - }, - { - desc: 'Parallel lines (no intersection)', - input: [0, 0, 2, 2, 0, 1, 2, 3], - expected: null - }, - { - desc: 'Overlap lines (fully overlapping)', - input: [0, 0, 2, 2, 1, 1, 3, 3], - expected: { x: 1, y: 1 } - }, - { - desc: 'Non-intersecting lines (far apart)', - input: [0, 0, 1, 1, 2, 2, 3, 3], - expected: null - }, - { - desc: 'Intersecting at an endpoint', - input: [0, 0, 2, 2, 2, 0, 0, 2], - expected: { x: 2, y: 2 } - } - ]; +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 - tests.forEach(({ desc, input, expected }, index) => { - const result = findIntersection(...input); - const isPassed = JSON.stringify(result) === JSON.stringify(expected); - console.log(`Test ${index + 1}: ${desc} - ${isPassed ? 'Passed' : 'Failed'}`); - if (!isPassed) { - console.log(` Expected: ${JSON.stringify(expected)}, Got: ${JSON.stringify(result)}`); - } - }); -} + // Create linked list 2: 4 -> 5 -> 6 -> 7 + const list2 = createLinkedList([4, 5]); + list2.next.next = intersection; // Connect 5 -> 6 -// Run the tests -runTests(); + 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 +}); diff --git a/Data-Structures/Linked-List/test/slowfast.test.js b/Data-Structures/Linked-List/test/slowfast.test.js index 37b4fd2117..82fa69b78a 100644 --- a/Data-Structures/Linked-List/test/slowfast.test.js +++ b/Data-Structures/Linked-List/test/slowfast.test.js @@ -1,49 +1,32 @@ -// test.js +// 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 + }); +}); -import { ListNode, hasCycle, findMiddle, detectCycle } from '../SlowFast.js'; - -function createLinkedList(arr) { - let head = null; - let current = null; - - for (let value of arr) { - const newNode = new ListNode(value); - if (!head) { - head = newNode; - current = newNode; - } else { - current.next = newNode; - current = newNode; - } - } - - return head; -} - -function runTests() { - // Test Case 1: Cycle detection - const cycleList = createLinkedList([1, 2, 3]); - cycleList.next.next.next = cycleList.next; // Creates a cycle (3 -> 2) - console.log(`Test 1: Cycle exists - ${hasCycle(cycleList) ? 'Passed' : 'Failed'}`); - - // Test Case 2: No cycle - const noCycleList = createLinkedList([1, 2, 3]); - console.log(`Test 2: No cycle - ${!hasCycle(noCycleList) ? 'Passed' : 'Failed'}`); - - // Test Case 3: Finding the middle element - const midList = createLinkedList([1, 2, 3, 4, 5]); - const midNode = findMiddle(midList); - console.log(`Test 3: Middle element - Expected: 3, Got: ${midNode.value} - ${midNode.value === 3 ? 'Passed' : 'Failed'}`); - - // Test Case 4: Finding the start of the cycle - const cycleStartList = createLinkedList([1, 2, 3]); - cycleStartList.next.next.next = cycleStartList.next; // Creates a cycle (3 -> 2) - const startNode = detectCycle(cycleStartList); - console.log(`Test 4: Start of cycle - Expected: 2, Got: ${startNode ? startNode.value : 'null'} - ${startNode && startNode.value === 2 ? 'Passed' : 'Failed'}`); - - // Test Case 5: No cycle in detectCycle - console.log(`Test 5: No cycle - Expected: null, Got: ${detectCycle(noCycleList) ? detectCycle(noCycleList).value : 'null'} - ${detectCycle(noCycleList) === null ? 'Passed' : 'Failed'}`); -} - -// Run the tests -runTests(); From fc568192e1452f3c73f1e1f064c9164409a633e6 Mon Sep 17 00:00:00 2001 From: karan1_2 Date: Sun, 6 Oct 2024 17:51:01 +0530 Subject: [PATCH 3/4] fix three lines --- Data-Structures/Array/2Sum.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data-Structures/Array/2Sum.js b/Data-Structures/Array/2Sum.js index cab05cc368..ae7105ad87 100644 --- a/Data-Structures/Array/2Sum.js +++ b/Data-Structures/Array/2Sum.js @@ -22,7 +22,7 @@ function twoSum(nums, target) { map.set(nums[i], i); } - return null; // No two sum solution + return []; // Return an empty array when no solution is found } export { twoSum } \ No newline at end of file From 2029064a206e5252d303e7476f0025c173f4535d Mon Sep 17 00:00:00 2001 From: karan1_2 Date: Sun, 6 Oct 2024 17:54:10 +0530 Subject: [PATCH 4/4] fix three lines --- Data-Structures/Array/2Sum.js | 28 ------------------------- Data-Structures/Array/test/2sum.test.js | 13 ------------ 2 files changed, 41 deletions(-) delete mode 100644 Data-Structures/Array/2Sum.js delete mode 100644 Data-Structures/Array/test/2sum.test.js diff --git a/Data-Structures/Array/2Sum.js b/Data-Structures/Array/2Sum.js deleted file mode 100644 index ae7105ad87..0000000000 --- a/Data-Structures/Array/2Sum.js +++ /dev/null @@ -1,28 +0,0 @@ -// twoSum.js - -/** - * - * Time Complexity: O(n) — We traverse the list once while storing elements in a hash map. -Space Complexity: O(n) — In the worst case, we store all elements in the hash map. - - - * Finds indices of the two numbers such that they add up to a specific target. - * @param {number[]} nums - An array of numbers. - * @param {number} target - The target sum. - * @returns {number[]|null} - Indices of the two numbers or null if not found. - */ -function twoSum(nums, target) { - const map = new Map(); - - for (let i = 0; i < nums.length; i++) { - const complement = target - nums[i]; - if (map.has(complement)) { - return [map.get(complement), i]; - } - map.set(nums[i], i); - } - - return []; // Return an empty array when no solution is found -} - -export { twoSum } \ No newline at end of file diff --git a/Data-Structures/Array/test/2sum.test.js b/Data-Structures/Array/test/2sum.test.js deleted file mode 100644 index ad23e831c6..0000000000 --- a/Data-Structures/Array/test/2sum.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import { twoSum } from '../2Sum.js'; // Adjust the path as necessary - -describe('Two Sum', () => { - it('should return indices of the two numbers such that they add up to a specific target', () => { - const nums = [2, 7, 11, 15]; - const target = 9; - const expected = [0, 1]; - const result = twoSum(nums, target); - expect(result).toEqual(expected); - }); - - // Add more test cases as needed -});