一些常见算法

71 阅读2分钟

寻找正序数组中位数

正则表达式匹配

盛最多水的容器

电话号码的字母组合

字母异位词分组

最大子数组和

螺旋矩阵

合并两个有序数组

二叉树的最大路径和

分发糖果

数组中第K个最大元素

超级回文数

最长公共子序列

acm模式

const rl = require("readline").createInterface({ input: process.stdin });var iter = rl[Symbol.asyncIterator]();const readline = async () => (await iter.next()).value;void async function () {    // Write your code here    while(line = await readline()){        let tokens = line.split(' ');        let a = parseInt(tokens[0]);        let b = parseInt(tokens[1]);        console.log(a + b);    }}()
  1. 寻找正序数组中位数

    var findMedianSortedArrays = function(nums1, nums2) {
        if (nums1.length > nums2.length) {
            [nums1, nums2] = [nums2, nums1];
        }
        
        const m = nums1.length;
        const n = nums2.length;
        let low = 0, high = m;
        
        while (low <= high) {
            const partitionX = Math.floor((low + high) / 2);
            const partitionY = Math.floor((m + n + 1) / 2) - partitionX;
            
            const maxX = (partitionX === 0) ? Number.MIN_SAFE_INTEGER : nums1[partitionX - 1];
            const maxY = (partitionY === 0) ? Number.MIN_SAFE_INTEGER : nums2[partitionY - 1];
            
            const minX = (partitionX === m) ? Number.MAX_SAFE_INTEGER : nums1[partitionX];
            const minY = (partitionY === n) ? Number.MAX_SAFE_INTEGER : nums2[partitionY];
            
            if (maxX <= minY && maxY <= minX) {
                if ((m + n) % 2 === 0) {
                    return (Math.max(maxX, maxY) + Math.min(minX, minY)) / 2;
                } else {
                    return Math.max(maxX, maxY);
                }
            } else if (maxX > minY) {
                high = partitionX - 1;
            } else {
                low = partitionX + 1;
            }
        }
        
        throw new Error("Input arrays are not sorted.");
    };
    
    
    
  2. 正则表达式匹配

    var isMatch = function(string, pattern) {
    
        if (!pattern) {
            return !string;
        }
       
        const hasFirstCharMatch = Boolean(string) && (pattern[0] === '.' || pattern[0] === string[0]);
    
        // track when the next character * is next in line in the pattern
        if (pattern[1] === '*') {
            return (
                isMatch(string, pattern.slice(2)) || 
                (hasFirstCharMatch && isMatch(string.slice(1), pattern))
            );
        }
        
      return hasFirstCharMatch ? isMatch(string.slice(1), pattern.slice(1)) : false;
    };
    
    
    

3. 盛最多水的容器

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
  const n = height.length
  let max = 0
  let i = 0
  let j = n - 1
  while(i < j) {
    const tmp = (j - i) * Math.min(height[i], height[j])
    if(tmp > max) {
      max = tmp
    }
    if(height[i] < height[j]) {
      i++
    } else {
      j--
    }
  }
  return max
};


4. 电话号码的字母组合

/**
 * @param {string} digits
 * @return {string[]}
 */
var letterCombinations = function (digits) {
    if (!digits) {
    return [];
  }

  const phoneMap = {
    '2': 'abc',
    '3': 'def',
    '4': 'ghi',
    '5': 'jkl',
    '6': 'mno',
    '7': 'pqrs',
    '8': 'tuv',
    '9': 'wxyz'
  };

  let combinations = [''];

  for (const digit of digits) {
    const newCombinations = [];
    for (const combination of combinations) {
      for (const letter of phoneMap[digit]) {
        newCombinations.push(combination + letter);
      }
    }
    combinations = newCombinations;
  }

  return combinations;
};

5. 字母异位词分组

/**
 * @param {string[]} strs
 * @return {string[][]}
 */
var groupAnagrams = function(strs) {
    const mp = new Map();
    const ans = [];

    for (const str of strs) {
        const sortedStr = str.split('').sort().join('');
        if (mp.has(sortedStr)) {
            ans[mp.get(sortedStr)].push(str);
        } else {
            mp.set(sortedStr, ans.length);
            ans.push([str]);
        }
    }

    return ans;
};

6. 最大子数组和

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    // Initialize the max sum...
    let maxSum = nums[0];
    // Traverse all the element through the loop...
    for (let i = 1; i < nums.length; i++) {
        // nums[i] represents the largest sum of all subarrays ending with index i...
        // then its value should be the larger one between nums[i]...
        // nums[i-1] + nums[i] (largest sum plus current number with using prefix)...
        // calculate nums[0], nums[1]…, nums[n] while comparing each one with current largest sum...
        nums[i] = Math.max(0, nums[i - 1]) + nums[i];
        // if nums[i] > maxSum then maxSum = nums[i]...
        if (nums[i] > maxSum)
            maxSum = nums[i];
    }
    return maxSum;      // return the contiguous subarray which has the largest sum...
};

7. 螺旋矩阵

/**
 * @param {number[][]} matrix
 * @return {number[]}
 */
var spiralOrder = function(matrix) {
    const res = [];
    while (matrix.length) {
        // 取第一行
        const first = matrix.shift();
        res.push(...first);
        
        // 取每行的最后一个元素
        for (let i = 0; i < matrix.length; i++) {
            let val = matrix[i].pop();
            if (val !== undefined) res.push(val);
        }
        
        // 反转矩阵,准备下一轮遍历
        matrix.reverse();
        
        // 将矩阵每一行反转,以保持正确的遍历方向
        for (let i = 0; i < matrix.length; i++) {
            matrix[i].reverse();
        }
    }
    return res;
};

8. 合并两个有序数组

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
    let i = 0
    let j = 0
    let res = []
    while(i<m && j<n){
      if(nums1[i] <= nums2[j]) {
        res.push(nums1[i])
        i++
      } else {
        res.push(nums2[j])
        j++
      }
    }
    while(i<m) {
      res.push(nums1[i])
        i++
    }
    while(j<n) {
      res.push(nums2[j])
      j++
    }
    nums1.splice(0, m+n, ...res)
};

二叉树的最大路径和

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
const maxPathSum = (root) => {
	let max = -Infinity;

	const findSums = (node) => {
		// Base case / hit a null
		if (!node) return 0;

		let left = findSums(node.left),
			right = findSums(node.right),
			allSum = left + right + node.val,
			leftNodeSum = left + node.val,
			rightNodeSum = right + node.val;

		// Max is all possible combinations
		max = Math.max(max, node.val, allSum, leftNodeSum, rightNodeSum);
		
		// Return the MAX path, which can be node.val, left + node.val, or right + node.val
		return Math.max(leftNodeSum, rightNodeSum, node.val);
	};

	findSums(root);

	return max;
};

分发糖果

/**
 * @param {number[]} ratings
 * @return {number}
 */
var candy = function(ratings) {
    if (ratings.length === 0) {
        return 0;
    }
    let ret = 1, up = 0, down = 0, peak = 0;
    for (let i = 0; i < ratings.length - 1; i++) {
        const prev = ratings[i], curr = ratings[i + 1];
        if (prev < curr) {
            up++;
            down = 0;
            peak = up;
            ret += 1 + up;
        } else if (prev === curr) {
            up = 0;
            down = 0;
            peak = 0;
            ret += 1;
        } else {
            up = 0;
            down++;
            ret += 1 + down;
            if (peak >= down) {
                ret--;
            }
        }
    }
    return ret;
};

数组中第K个最大元素

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findKthLargest = function(nums, k) {
    return quickSelect(nums, 0, nums.length - 1, nums.length - k);
};

function quickSelect(nums, left, right, k) {
    while (left <= right) {
        const pivotIndex = partition(nums, left, right);
        if (k === pivotIndex) {
            return nums[k];
        } else if (k < pivotIndex) {
            right = pivotIndex - 1;
        } else {
            left = pivotIndex + 1;
        }
    }
    return -1; // 应该不会到达这里
}

function partition(nums, left, right) {
    const pivotIndex = medianOfThree(nums, left, right);
    const pivot = nums[pivotIndex];
    swap(nums, pivotIndex, right); // 把枢轴移到末尾
    let i = left;
    for (let j = left; j < right; j++) {
        if (nums[j] < pivot) {
            swap(nums, i++, j);
        }
    }
    swap(nums, i, right); // 把枢轴移到最终位置
    return i;
}

function medianOfThree(nums, left, right) {
    const mid = left + ((right - left) >> 1);
    if (nums[left] > nums[mid]) swap(nums, left, mid);
    if (nums[left] > nums[right]) swap(nums, left, right);
    if (nums[mid] > nums[right]) swap(nums, mid, right);
    return mid;
}

function swap(nums, i, j) {
    [nums[i], nums[j]] = [nums[j], nums[i]];
}

超级回文数

/**
 * @param {string} left
 * @param {string} right
 * @return {number}
 */
var superpalindromesInRange = function(left, right) {
    let ans = 9 >= left && 9 <= right ? 1 : 0

    const isPal = str => {
        for (let i = 0, j = str.length - 1; i < j; i++, j--)
            if (str.charAt(i) !== str.charAt(j)) return false
        return true
    }

    for (let dig = 1; dig < 10; dig++) {
        let isOdd = dig % 2 && dig !== 1,
            innerLen = (dig >> 1) - 1, innerLim = Math.max(1, 2 ** innerLen),
            midPos = dig >> 1, midLim = isOdd ? 3 : 1
        for (let edge = 1; edge < 3; edge++) {
            let pal = new Uint8Array(dig)
            pal[0] = edge, pal[dig-1] = edge
            if (edge === 2) innerLim = 1, midLim = Math.min(midLim, 2)
            for (let inner = 0; inner < innerLim; inner++) {
                if (inner > 0) {
                    let innerStr = inner.toString(2).padStart(innerLen, '0')
                    for (let i = 0; i < innerLen; i++)
                        pal[1+i] = innerStr[i], pal[dig-2-i] = innerStr[i]
                }
                for (let mid = 0; mid < midLim; mid++) {
                    if (isOdd) pal[midPos] = mid
                    let palin = ~~pal.join(""),
                        square = BigInt(palin) * BigInt(palin)
                    if (square > right) return ans
                    if (square >= left && isPal(square.toString())) ans++
                }
            }
        }
    }
    return ans
};

最长公共子序列

/**
 * @param {string} text1
 * @param {string} text2
 * @return {number}
 */
var longestCommonSubsequence = function(text1, text2) {
    // Lengths of the input strings
    const length1 = text1.length;
    const length2 = text2.length;

    // Create a 2D array to store the lengths of longest common subsequences
    // for all subproblems, initialized with zero
    const dp = new Array(length1 + 1).fill(0).map(() => new Array(length2 + 1).fill(0));

    // Build the dp array from the bottom up
    for (let i = 1; i <= length1; ++i) {
        for (let j = 1; j <= length2; ++j) {
            // If characters match, take diagonal value and add 1
            if (text1.charAt(i - 1) === text2.charAt(j - 1)) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            }
            // If characters do not match, take the maximum value from 
            // the left (dp[i][j-1]) or above (dp[i-1][j])
            else {
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    // The bottom-right cell contains the length of the longest
    // common subsequence of text1 and text2
    return dp[length1][length2];
};