算法学习记录(三十三)

126 阅读1分钟

问:

  1. 给定数转为字符串对应规则,为26个数字对应26个字母。可以1个数转也可以2个数转。例如11,可以转为aa,可以转为k。给一个串数字,请返回能转为不同字符串的个数
  2. 剑指 Offer 04. 二维数组中的查找
  3. 超级洗衣机
  4. 螺旋矩阵

解: 1.

function getChangeNums(str) {
    const N = str.length
    function getRes(cur) {
        if (cur > N) {
            return 0
        }
        if (cur === N) {
            return 1
        }
        if (str[cur] === '0') {
            return 0
        }
        if (str[cur] === '1') {
            return getRes(cur+1) + getRes(cur+2)
        }
        if (str[cur] === '2') {
            if (Number(str[cur+1]) <= 6) {
                return getRes(cur+1)+getRes(cur+2)
            }
        }
        return getRes(cur+1)
    }
    return getRes(0)
}
const findNumberIn2DArray = function(matrix, target) {
    if (!matrix.length) return false
    let x = 0
    let y = matrix[0].length - 1
    while(x < matrix.length && y >=0) {
        const cur = matrix[x][y]
        if (cur > target) {
            y--
        }
        if (cur < target) {
            x++
        }
        if (cur === target ) {
            return true
        }
    }
    return false
};
function findMinMoves(arr) {
    // 假设对于第i个洗衣机来说
    // 若规定正数为抛出衣服,负数为需要衣服
    // 分为以下四种情况
    // ①它的左边需要-20件衣服,它的右边需要+10件衣服。那么第i个洗衣机需要操作20次
    // ②左:10,右:-20。那么它需要操作20次
    // ②左:+10,右:+20。那么它需要操作20次
    // ④左:-10,右:-20。那么它需要操作30次
    // 由此可见,对于第i个洗衣机来说,当左右都是负数时,操作次数为两者绝对值的和。其余情况都是两者绝对值中更大的那个。
    // 需要哪些条件: 左边目前有多少件衣服,每个洗衣机需要多少衣服
    const N = arr.length
    const sum = arr.reduce((pre,item) => {
        return pre+item
    }, 0)
    // 首先如果无法被整除,那么平均不了
    if (sum % N !== 0) return false
    // 求平均值,即每个洗衣机需要多少件衣服
    const average = sum / N
    let preNums = 0
    let maxNum = 0
    for (let i = 0; i < N; i++) {
        // 计算出左侧和右侧需要多少衣服
        // 左侧需要衣服 = 左侧已有衣服 - 左侧最终衣服
        const leftNeed = preNums - i * average
        preNums += arr[i]
        // 右侧需要衣服 = 总衣服 - 左侧衣服 - 右侧最终衣服
        const rightNeed = sum - preNums - (N - i - 1) * average
        // 当前洗衣机需要进行多少操作
        const tempNum = (leftNeed < 0 && rightNeed < 0) ? Math.abs(leftNeed) + Math.abs(rightNeed) : Math.max(Math.abs(leftNeed), Math.abs(rightNeed))
        // 取操作次数最多的那个洗衣机
        maxNum = Math.max(maxNum, tempNum)
    }
    return maxNum
}
  1. 用(a,b),(x,y)两个点确定一个矩形。初始值为矩阵的最外层矩形。打印矩形的边,然后顶点向里层移动,打印第二层矩形,直到两个顶点错位为止。
function spiralOrder(arr) {
    const res = []
    // 设定两个顶点,确定一个矩形
    let a = 0
    let b = 0
    let x = arr.length - 1
    let y = arr[0].length - 1
    // 打印矩形的边
    while (a <= x && b <= y) {
        print(a, b, x, y)
        a++
        b++
        x--
        y--
    }
    function print(a,b,x,y) {
        let row = a
        let col = b
        // 同一行
        if (a === x) {
            for (let i = b; i <= y; i++) {
                res.push(arr[a][i])
            }
        }
        // 同一列
        else if (b === y) {
            for (let i = a; i <= x; i++) {
                res.push(arr[i][b])
            }
        } else {
            // 不同行同列
            while (col < y) {
                res.push(arr[row][col])
                col++
            }
            while (row < x) {
                res.push(arr[row][col])
                row++
            }
            while (col > b) {
                res.push(arr[row][col])
                col--
            }
            while (row > a) {
                res.push(arr[row][col])
                row--
            }
        }
    }
    return res
}