算法练习day6

64 阅读2分钟

一、四数相加2

问题要点

把数组a和b的所有求和情况存入哈希表中,然后从c和d的所有求和情况中寻找是否有0 -(a+b),并累计总数

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number[]} nums3
 * @param {number[]} nums4
 * @return {number}
 */
var fourSumCount = function(nums1, nums2, nums3, nums4) {
    let map = new Map
    let count = 0
    for(let i of nums1) {
        for(let j of nums2) {
            let r = i + j 
            map.set(r, (map.get(r) || 0) + 1)
        }
    }
    for(let i of nums3) {
        for(let j of nums4) {
            let r = i + j 
            if(map.has(0 - r)) {
                count += map.get(0 - r)
            }
        }
    }
    return count
};

二、赎金信

问题要点

哈希法:用数组作为magazine字母的出现次数,然后减去ransomNote的字母,如果能完全通过,则证明可以覆盖

/**
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function(ransomNote, magazine) {
    let arr = new Array(26).fill(0)
    if(ransomNote.length > magazine.length) {
        return false
    }
    let base = 'a'.charCodeAt()
    for(let i of magazine) {
        arr[i.charCodeAt() - base]++
    }
    for(let i of ransomNote) {
        if(!arr[i.charCodeAt() - base]) {
            return false
        }
        arr[i.charCodeAt() - base]--
    }
    return true
};

三、三数之和

问题要点

先把数组排序,然后用双指针

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function (nums) {
    nums = nums.sort((x, y) => x - y)
    let res = []
    for (let i = 0; i < nums.length; i++) {
        if(nums[i] > 0) {
            return res
        }
        if (nums[i] === nums[i - 1]) {
            continue
        }
        let left = i + 1
        let right = nums.length - 1
        while (left < right) {
            let sum = nums[i] + nums[left] + nums[right]
            if(sum < 0) {
                left++
            } else if(sum > 0) {
                right--
            } else {
                res.push([nums[i], nums[left], nums[right]])
                while(left < right && nums[left] === nums[left+1]){
                    left++
                }
                while(left < right && nums[right] === nums[right - 1]) {
                    right--
                }
                left++
                right--
            }
        }
    }
    return res
};

四、四数之和

问题要点

和三数之和的思路一致,不同点在于这个需要双重循环,然后再用双指针,然后target也变为了任意值况

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function (nums, target) {
    nums.sort((x, y) => x - y)
    let res = []
    let len = nums.length
    for (let i = 0; i < len - 3; i++) {
        if (i > 0 && nums[i] === nums[i - 1]) {
            continue
        }
        for (let j = i + 1; j < len - 2; j++) {
            if (j > i + 1 && nums[j] === nums[j - 1]) {
                continue
            }
            let sum1 = nums[i] + nums[j]
            if (sum1 > target && sum1 >= 0) {
               break
            }
            let left = j + 1
            let right = len - 1
            while (left < right) {
                let sum2 = sum1 + nums[left] + nums[right]
                if (sum2 > target) {
                    right--
                } else if (sum2 < target) {
                    left++
                } else {
                    res.push([nums[i], nums[j], nums[left], nums[right]])
                    while (left < right && nums[left] === nums[left + 1]) {
                        left++
                    }
                    while (left < right && nums[right] === nums[right - 1]) {
                        right--
                    }
                    left++
                    right--
                }
            }
        }

    }
    return res
};