算法学习记录(三十六)

262 阅读2分钟

问:

  1. 给定一个数组长度为N,可以把任意长度大于0且小于N的前缀作为左部分,剩下的作为右部分。划分后,有一个值K为左部分最大值减去右部分最大值的绝对值。求最大的K是多少。
  2. 如果一个字符串str。把str前面任意部分挪到后面形成的字符串叫做str的旋转词,比如str='1234',它的旋转词有:'1234'、'2341'、'3412','4123'。给定两个字符串,判断是否为旋转词
  3. 给定一个数组arr,如果通过调整元素位置可以做到arr中任意两个相邻的数字相乘是4的倍数,返回true,否则false。

解:

function getMaxK(arr) {
    // 对于这个数组来说,找到其中的最大值
    // 两种情况,这个最大值分在左边、这个最大值分在右边
    // 那么假设这个最大值在左边。右边一定包含数组最后一个数。
    // 那么分析数组最后一个数,如果还有比它大的数,那最大值-比它大的数的绝对值会变小。如果没有比它大的数,那么最大值-它就是最大。
    // 得出结论,当最大值在左边时,想得到的K就是最大值-数组最后一个数。同理最大值在右边时,K就是最大值-数组第一个数
    // 那么取两种情况中更大的一个就是结果

    // 找到最大值
    let max = -Infinity
    for (let i of arr) {
        max = Math.max(i, max)
    }
    // 返回两种情况中的较大的一个
    return Math.max(Math.abs(max-arr[0]), Math.abs(max-arr[arr.length - 1]))
}
function isRotate(str, str2) {
    if (str.length !== str2.length) return false
    // 旋转词的所有可能都包含在这个字符串中
    str = str + str
    // 判断str2是否在str1中即可
    // 若考察点为kmp算法,那么手写并代替inclueds方法
    return str.includes(str2)
}
function isQualified(arr) {
    if (arr.length <= 1) return false
    // 奇数需要乘以含有4因子的数才能达标。
    // 所以先找到数组中所有奇数,所有含有4因子的数和2。
    const oddNums = []
    const fourNums = []
    const twoNums = []
    for (let i of arr) {
        if (i % 2 !== 0) {
            oddNums.push(i)
        } else if (i % 4 === 0) {
            fourNums.push(i)
        } else if (i % 2 === 0) {
            twoNums.push(i)
        }
    }
    // 假设没有奇数
    if (!oddNums.length) return true
    // 假如有奇数
    if (oddNums.length) {
        // 如果没有2,有以下两种摆放方式
        // 奇 4n 奇 4n 奇
        // 4n 奇 4n 奇
        // 4因子的数量大于等于奇数的数量 - 1即可
        if (!twoNums.length) {
            return fourNums.length >= oddNums.length - 1;
        }
        // 如果有2
        // 因为2不能和奇相邻,如果2是穿插着放,会消耗4n。所以最好情况是把2全部放在边界。
        // 2 2 4n 奇 4n 奇
        // 4因子的数量大于等于奇数的数量即可
        if (twoNums.length) {
            return fourNums.length >= oddNums.length;
        }
    }
}