前端部分算法的实现
2021/10/20 17:09:47
本文主要是介绍前端部分算法的实现,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1. 通过快慢指针寻找链表中点
function findCenter(head) { let slower = head, faster = head; while (faster && faster.next != null) { slower = slower.next; faster = faster.next.next; } // 如果 faster 不等于 null,说明是奇数个,slower 再移动一格 if (faster != null) { slower = slower.next; } return slower; }
2. 前序遍历判断回文链表
var isPalindrome = function(head) { let left = head; function traverse(right) { if (right == null) return true; let res = traverse(right.next); res = res && (right.val === left.val); left = left.next; return res; } return traverse(head); };
3.反转链表
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {ListNode} */ var reverseList = function(head) { if (head == null || head.next == null) return head; let last = reverseList(head.next); head.next.next = head; head.next = null; return last; };
4. 合并K个升序链表(困难)
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode[]} lists * @return {ListNode} */ var mergeKLists = function(lists) { if (lists.length === 0) return null; return mergeArr(lists); }; function mergeArr(lists) { if (lists.length <= 1) return lists[0]; let index = Math.floor(lists.length / 2); const left = mergeArr(lists.slice(0, index)) const right = mergeArr(lists.slice(index)); return merge(left, right); } function merge(l1, l2) { if (l1 == null && l2 == null) return null; if (l1 != null && l2 == null) return l1; if (l1 == null && l2 != null) return l2; let newHead = null, head = null; while (l1 != null && l2 != null) { if (l1.val < l2.val) { if (!head) { newHead = l1; head = l1; } else { newHead.next = l1; newHead = newHead.next; } l1 = l1.next; } else { if (!head) { newHead = l2; head = l2; } else { newHead.next = l2; newHead = newHead.next; } l2 = l2.next; } } newHead.next = l1 ? l1 : l2; return head; }
5. K 个一组翻转链表(困难)
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @param {number} k * @return {ListNode} */ var reverseKGroup = function(head, k) { let a = head, b = head; for (let i = 0; i < k; i++) { if (b == null) return head; b = b.next; } const newHead = reverse(a, b); a.next = reverseKGroup(b, k); return newHead; }; function reverse(a, b) { let prev = null, cur = a, nxt = a; while (cur != b) { nxt = cur.next; cur.next = prev; prev = cur; cur = nxt; } return prev; }
5. 环形链表(简单)
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {boolean} */ var hasCycle = function(head) { if (head == null || head.next == null) return false; let slower = head, faster = head; while (faster != null && faster.next != null) { slower = slower.next; faster = faster.next.next; if (slower === faster) return true; } return false; };
6. 排序链表(中等)
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} head * @return {ListNode} */ var sortList = function(head) { if (head == null) return null; let newHead = head; return mergeSort(head); }; function mergeSort(head) { if (head.next != null) { let slower = getCenter(head); let nxt = slower.next; slower.next = null; console.log(head, slower, nxt); const left = mergeSort(head); const right = mergeSort(nxt); head = merge(left, right); } return head; } function merge(left, right) { let newHead = null, head = null; while (left != null && right != null) { if (left.val < right.val) { if (!head) { newHead = left; head = left; } else { newHead.next = left; newHead = newHead.next; } left = left.next; } else { if (!head) { newHead = right; head = right; } else { newHead.next = right; newHead = newHead.next; } right = right.next; } } newHead.next = left ? left : right; return head; } function getCenter(head) { let slower = head, faster = head.next; while (faster != null && faster.next != null) { slower = slower.next; faster = faster.next.next; } return slower; }
7. 相交链表(简单)
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * @param {ListNode} headA * @param {ListNode} headB * @return {ListNode} */ var getIntersectionNode = function(headA, headB) { let lastHeadA = null; let lastHeadB = null; let originHeadA = headA; let originHeadB = headB; if (!headA || !headB) { return null; } while (true) { if (headB == headA) { return headB; } if (headA && headA.next == null) { lastHeadA = headA; headA = originHeadB; } else { headA = headA.next; } if (headB && headB.next == null) { lastHeadB = headB headB = originHeadA; } else { headB = headB.next; } if (lastHeadA && lastHeadB && lastHeadA != lastHeadB) { return null; } } return null; };
8. 最长回文子串(中等)
/** * @param {string} s * @return {string} */ var longestPalindrome = function(s) { if (s.length === 1) return s; let maxRes = 0, maxStr = ''; for (let i = 0; i < s.length; i++) { let str1 = palindrome(s, i, i); let str2 = palindrome(s, i, i + 1); if (str1.length > maxRes) { maxStr = str1; maxRes = str1.length; } if (str2.length > maxRes) { maxStr = str2; maxRes = str2.length; } } return maxStr; }; function palindrome(s, l, r) { while (l >= 0 && r < s.length && s[l] === s[r]) { l--; r++; } return s.slice(l + 1, r); }
9. 最长公共前缀(简单)
/** * @param {string[]} strs * @return {string} */ var longestCommonPrefix = function(strs) { if (strs.length === 0) return ""; let first = strs[0]; if (first === "") return ""; let minLen = Number.MAX_SAFE_INTEGER; for (let i = 1; i < strs.length; i++) { const len = twoStrLongestCommonPrefix(first, strs[i]); minLen = Math.min(len, minLen); } return first.slice(0, minLen); }; function twoStrLongestCommonPrefix (s, t) { let i = 0, j = 0; let cnt = 0; while (i < s.length && j < t.length) { console.log(s[i], t[j], cnt) if (s[i] === t[j]) { cnt++; } else { return cnt; } i++; j++; } return cnt; }
10. 无重复字符的最长子串(中等))
/** * @param {string} s * @return {number} */ var lengthOfLongestSubstring = function(s) { let window = {}; let left = 0, right = 0; let maxLen = 0, maxStr = ''; while (right < s.length) { let c = s[right]; right++; if (window[c]) window[c]++; else window[c] = 1 while (window[c] > 1) { let d = s[left]; left++; window[d]--; } if (maxLen < right - left) { maxLen = right - left; } } return maxLen; };
11. 最小覆盖子串(困难)
/** * @param {string} s * @param {string} t * @return {string} */ var minWindow = function(s, t) { let need = {}, window = {}; for (let c of t) { if (!need[c]) need[c] = 1; else need[c]++; } let left = 0, right = 0; let valid = 0, len = Object.keys(need).length; let minLen = s.length + 1, minStr = ''; while (right < s.length) { const d = s[right]; right++; if (!window[d]) window[d] = 1; else window[d]++; if (need[d] && need[d] === window[d]) { valid++; } console.log('left - right', left, right); while (valid === len) { if (right - left < minLen) { minLen = right - left; minStr = s.slice(left, right); } console.lo let c = s[left]; left++; window[c]--; if (need[c] && window[c] < need[c]) { valid--; } } } return minStr; };
12. 俄罗斯套娃信封问题(困难)
/** * @param {number[][]} envelopes * @return {number} */ var maxEnvelopes = function(envelopes) { if (envelopes.length === 1) return 1; envelopes.sort((a, b) => { if (a[0] !== b[0]) return a[0] - b[0]; else return b[1] - a[1]; }); let LISArr = []; for (let [key, value] of envelopes) { LISArr.push(value); } console.log( LISArr); return LIS(LISArr); }; function LIS(arr) { let dp = []; let maxAns = 0; for (let i = 0; i < arr.length; i++) { dp[i] = 1; } for (let i = 1; i < arr.length; i++) { for (let j = i; j >= 0; j--) { if (arr[i] > arr[j]) { dp[i] = Math.max(dp[i], dp[j] + 1) } maxAns = Math.max(maxAns, dp[i]); } } return maxAns; }
13. 最长连续递增序列(简单)
/** * @param {number[]} nums * @return {number} */ var findLengthOfLCIS = function(nums) { if (nums.length === 0) return 0; const n = nums.length; let left = 0, right = 1; let globalMaxLen = 1, maxLen = 1; while (right < n) { if (nums[right] > nums[left]) maxLen++; else { maxLen = 1; } left++; right++; globalMaxLen = Math.max(globalMaxLen, maxLen); } return globalMaxLen; };
14. 最长连续序列(困难)
/** * @param {number[]} nums * @return {number} */ var longestConsecutive = function(nums) { if (nums.length === 0) return 0; const set = new Set(nums); const n = nums.length; let globalLongest = 1; for (let i = 0; i < n; i++) { if (!set.has(nums[i] - 1)) { let longest = 1; let currentNum = nums[i]; while (set.has(currentNum + 1)) { currentNum += 1; longest++; } globalLongest = Math.max(globalLongest, longest); } } return globalLongest; };
15. 盛最多水的容器(中等)
/** * @param {number[]} height * @return {number} */ var maxArea = function(height) { let n = height.length; let left = 0, right = n - 1; let maxOpacity = 0; while (left < right) { let res = Math.min(height[left], height[right]) * (right - left); maxOpacity = Math.max(maxOpacity, res); if (height[left] < height[right]) left++ else right--; } return maxOpacity; };
16. 寻找两个正序数组的中位数(困难)
/** * @param {number[]} nums1 * @param {number[]} nums2 * @return {number} */ var findMedianSortedArrays = function(nums1, nums2) { let m = nums1.length, n = nums2.length; let i = 0, j = 0; let newArr = []; while (i < m && j < n) { if (nums1[i] < nums2[j]) { newArr.push(nums1[i++]); } else { newArr.push(nums2[j++]); } } newArr = newArr.concat(i < m ? nums1.slice(i) : nums2.slice(j)); const len = newArr.length; console.log(newArr) if (len % 2 === 0) { return (newArr[len / 2] + newArr[len / 2 - 1]) / 2; } else { return newArr[Math.floor(len / 2)]; } };
17. 删除有序数组中的重复项(简单)
/** * @param {number[]} nums * @return {number} */ var removeDuplicates = function(nums) { if (nums.length <= 1) return nums.length; let lo = 0, hi = 0; while (hi < nums.length) { while (nums[lo] === nums[hi] && hi < nums.length) hi++; if (nums[lo] !== nums[hi] && hi < nums.length) { lo++; nums[lo] = nums[hi]; } hi++; } return lo + 1; };
18. 岛屿的最大面积(中等)
/** * @param {number[][]} grid * @return {number} */ let maxX, maxY;let visited;let globalMaxArea; var maxAreaOfIsland = function(grid) { visited = new Set(); maxX = grid.length; maxY = grid[0].length; globalMaxArea = 0; for (let i = 0; i < maxX; i++) { for (let j = 0; j < maxY; j++) { if (grid[i][j] === 1) { visited.add(`(${i}, ${j})`); globalMaxArea = Math.max(globalMaxArea, dfs(grid, i, j)); } visited.clear(); } } return globalMaxArea; }; function dfs(grid, x, y) { let res = 1; for (let i = -1; i <= 1; i++) { for (let j = -1; j <= 1; j++) { if (Math.abs(i) === Math.abs(j)) continue; const newX = x + i; const newY = y + j; if (newX >= maxX || newX < 0 || newY >= maxY || newY < 0) continue; if (visited.has(`(${newX}, ${newY})`)) continue; visited.add(`(${newX}, ${newY})`); const areaCnt = grid[newX][newY] if (areaCnt === 1) { const cnt = dfs(grid, newX, newY); res += cnt; } } } return res; }
19. 和为K的子数组(中等)
/** * @param {number[]} nums * @param {number} k * @return {number} */ var subarraySum = function(nums, k) { let cnt = 0; let sum0_i = 0, sum0_j = 0; let map = new Map(); map.set(0, 1); for (let i = 0; i <= nums.length; i++) { sum0_i += nums[i]; sum0_j = sum0_i - k; console.log('map', sum0_j, map.get(sum0_j)) if (map.has(sum0_j)) { cnt += map.get(sum0_j); } let sumCnt = map.get(sum0_i) || 0; map.set(sum0_i, sumCnt + 1); } return cnt; };
nSum问题【哈希表】【系列】
1. 两数之和(简单)
/** * @param {number[]} nums * @param {number} target * @return {number[]} */ var twoSum = function(nums, target) { let map2 = new Map(); for (let i = 0; i < nums.length; i++) { map2.set(nums[i], i); } for (let i = 0; i < nums.length; i++) { if (map2.has(target - nums[i]) && map2.get(target - nums[i]) !== i) return [i, map2.get(target - nums[i])] } };
2. 接雨水(困难)
/** * @param {number[]} height * @return {number} */ var trap = function(height) { let l_max = [], r_max = []; let len = height.length; let maxCapacity = 0; for (let i = 0; i < len; i++) { l_max[i] = height[i]; r_max[i] = height[i]; } for (let i = 1; i < len; i++) { l_max[i] = Math.max(l_max[i - 1], height[i]); } for (let j = len - 2; j >= 0; j--) { r_max[j] = Math.max(r_max[j + 1], height[j]); } for (let i = 0; i < len; i++) { maxCapacity += Math.min(l_max[i], r_max[i]) - height[i]; } return maxCapacity; };
跳跃游戏【贪心算法】【系列】
1. 跳跃游戏(中等)
/** * @param {number[]} nums * @return {boolean} */ var canJump = function(nums) { let faster = 0; for (let i = 0; i < nums.length - 1; i++) { faster = Math.max(faster, i + nums[i]); if (faster <= i) return false; } return faster >= nums.length - 1; };
【二叉树】【系列】
1. 二叉树的最近公共祖先(简单)
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; * } */ /** * @param {TreeNode} root * @param {TreeNode} p * @param {TreeNode} q * @return {TreeNode} */ let visited;let parent; var lowestCommonAncestor = function(root, p, q) { visited = new Set(); parent = new Map(); dfs(root); while (p != null) { visited.add(p.val); p = parent.get(p.val); } while (q != null) { if (visited.has(q.val)) { return q; } q = parent.get(q.val); } return null; }; function dfs(root) { if (root.left != null) { parent.set(root.left.val, root); dfs(root.left); } if (root.right != null) { parent.set(root.right.val, root); dfs(root.right); } }
2. 二叉搜索树中的搜索(简单)
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; * } */ /** * @param {TreeNode} root * @param {number} val * @return {TreeNode} */ var searchBST = function(root, val) { if (root == null) return null; if (root.val === val) return root; if (root.val > val) { return searchBST(root.left, val); } else if (root.val < val) { return searchBST(root.right, val); } };
3. 删除二叉搜索树中的节点(中等)
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; * } */ /** * @param {TreeNode} root * @param {number} key * @return {TreeNode} */ var deleteNode = function(root, key) { if (root == null) return null; if (root.val === key) { if (root.left == null && root.right == null) return null; if (root.left == null) return root.right; if (root.right == null) return root.left; if (root.left != null && root.right != null) { let target = getMinTreeMaxNode(root.left); root.val = target.val; root.left = deleteNode(root.left, target.val); } } if (root.val < key) { root.right = deleteNode(root.right, key); } else if (root.val > key) { root.left = deleteNode(root.left, key); } return root; }; function getMinTreeMaxNode(root) { if (root.right == null) return root; return getMinTreeMaxNode(root.right); }
4. 完全二叉树的节点个数(中等)
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; * } */ /** * @param {TreeNode} root * @return {number} */ var countNodes = function(root) { if (root == null) return 0; let l = root, r = root; let lh = 0, rh = 0; while (l != null) { l = l.left; lh++; } while (r != null) { r = r.right; rh++; } if (lh === rh) { return Math.pow(2, lh) - 1; } return 1 + countNodes(root.left) + countNodes(root.right); };
5. 二叉树的锯齿形层序遍历(中等)
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; * } */ /** * @param {TreeNode} root * @return {number[][]} */ let res; var zigzagLevelOrder = function(root) { if (root == null) return []; res = []; BFS(root, true); return res; }; function BFS(root, inOrder) { let arr = []; let resItem = []; let node; let stack1 = new Stack(); let stack2 = new Stack(); // 判断交换时机 let flag; stack1.push(root); res.push([root.val]); inOrder = !inOrder; while (!stack1.isEmpty() || !stack2.isEmpty()) { if (stack1.isEmpty()) { flag = 'stack1'; } else if (stack2.isEmpty()) { flag = 'stack2'; } // 决定取那个栈里面的元素 if (flag === 'stack2' && !stack1.isEmpty()) node = stack1.pop(); else if (flag === 'stack1' && !stack2.isEmpty()) node = stack2.pop(); if (inOrder) { if (node.left) { if (flag === 'stack1') { stack1.push(node.left); } else { stack2.push(node.left); } resItem.push(node.left.val); } if (node.right) { if (flag === 'stack1') { stack1.push(node.right); } else { stack2.push(node.right); } resItem.push(node.right.val); } } else { if (node.right) { if (flag === 'stack1') { stack1.push(node.right); } else { stack2.push(node.right); } resItem.push(node.right.val); } if (node.left) { if (flag === 'stack1') { stack1.push(node.left); } else { stack2.push(node.left); } resItem.push(node.left.val); } } // 判断下次翻转的时机 if ((flag === 'stack2' && stack1.isEmpty()) || (flag === 'stack1' && stack2.isEmpty())) { inOrder = !inOrder; // 需要翻转了,就加一轮值 if (resItem.length > 0) { res.push(resItem); } resItem = []; } } } class Stack { constructor() { this.count = 0; this.items = []; } push(element) { this.items[this.count] = element; this.count++; } pop() { if (this.isEmpty()) return undefined; const element = this.items[this.count - 1]; delete this.items[this.count - 1]; this.count--; return element; } size() { return this.count; } isEmpty() { return this.size() === 0; } }
【排序算法】【系列】
1. 用最少数量的箭引爆气球(中等)
/** * @param {number[][]} points * @return {number} */ var findMinArrowShots = function(points) { if (points.length === 0) return 0; points.sort((a, b) => a[1] - b[1]); let cnt = 1; let resArr = [points[0]]; let curr, last; for (let i = 1; i < points.length; i++) { curr = points[i]; last = resArr[resArr.length - 1]; if (curr[0] > last[1]) { resArr.push(curr); cnt++; } } return cnt; };
2. 合并区间(中等)
/** * @param {number[][]} intervals * @return {number[][]} */ var merge = function(intervals) { if (intervals.length === 0) return []; intervals.sort((a, b) => a[0] - b[0]); let mergeArr = [intervals[0]]; let last, curr; for (let j = 1; j < intervals.length; j++) { last = mergeArr[mergeArr.length - 1]; curr = intervals[j]; if (last[1] >= curr[0]) { last[1] = Math.max(curr[1], last[1]); } else { mergeArr.push(curr); } } return mergeArr; };
【 二分查找 】
1. 寻找两个正序数组的中位数(困难)
/** * @param {number[]} nums1 * @param {number[]} nums2 * @return {number} */ var findMedianSortedArrays = function(nums1, nums2) { let m = nums1.length, n = nums2.length; let i = 0, j = 0; let newArr = []; while (i < m && j < n) { if (nums1[i] < nums2[j]) { newArr.push(nums1[i++]); } else { newArr.push(nums2[j++]); } } newArr = newArr.concat(i < m ? nums1.slice(i) : nums2.slice(j)); const len = newArr.length; console.log(newArr) if (len % 2 === 0) { return (newArr[len / 2] + newArr[len / 2 - 1]) / 2; } else { return newArr[Math.floor(len / 2)]; } };
2. 判断子序列(简单)
/** * @param {string} s * @param {string} t * @return {boolean} */ var isSubsequence = function(s, t) { let hash = {}; for (let i = 0; i < t.length; i++) { if (!hash[t[i]]) hash[t[i]] = []; hash[t[i]].push(i); } let lastMaxIndex = 0; for (let i = 0; i < s.length; i++) { if (hash[s[i]]) { const index = binarySearch(hash[s[i]], lastMaxIndex); console.log('index', index, hash[s[i]]); if (index === -1) return false; lastMaxIndex = hash[s[i]][index] + 1; } else return false; } return true; }; function binarySearch(array, targetIndex) { let left = 0, right = array.length; while (left < right) { let mid = left + Math.floor((right - left) / 2); if (array[mid] >= targetIndex) { right = mid; } else if (array[mid] < targetIndex) { left = mid + 1; } } if (left >= array.length || array[left] < targetIndex) return -1; return left; }
3. 在排序数组中查找元素的第一个和最后一个位置(中等)
/** * @param {number[]} nums * @param {number} target * @return {number[]} */ var searchRange = function(nums, target) { const left = leftBound(nums, target); const right = rightBound(nums, target); return [left, right]; }; function leftBound(nums, target) { let left = 0; let right = nums.length - 1; while (left <= right) { let mid = Math.floor(left + (right - left) / 2); if (nums[mid] === target) { right = mid - 1; } else if (nums[mid] < target) { left = mid + 1; } else if (nums[mid] > target) { right = mid - 1; } } if (left >= nums.length || nums[left] !== target) { return -1; } return left; } function rightBound(nums, target) { let left = 0; let right = nums.length - 1; while (left <= right) { let mid = Math.floor(left + (right - left) / 2); if (nums[mid] === target) { left = mid + 1; } else if (nums[mid] < target) { left = mid + 1; } else if (nums[mid] > target) { right = mid - 1; } } if (right < 0 || nums[right] !== target) { return -1; } return right; }
这篇关于前端部分算法的实现的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15AntDesign项目实战:新手入门与初级应用教程
- 2024-11-15AntDesign-Form-rules项目实战:新手指南
- 2024-11-14ESLint课程:初学者指南
- 2024-11-14Form.List 动态表单课程:新手入门教程
- 2024-11-14Redux课程:新手入门完全指南
- 2024-11-13MobX 使用入门教程:轻松掌握前端状态管理
- 2024-11-12前端编程资料:新手入门指南与初级教程
- 2024-11-12前端开发资料入门指南
- 2024-11-12前端培训资料:适合新手与初级用户的简单教程
- 2024-11-12前端入门资料:新手必读指南