iliuyt / blog

1 stars 0 forks source link

面试题整理 #30

Open iliuyt opened 5 years ago

iliuyt commented 5 years ago

// 第一题 // 思路 // 截断2部分需要一个节点,截断三部分需要两个节点,依次类推,N个部分需要N-1个节点 // 成本等于节点的值相加,那么只要找到所有节点的值进行排序,取最小的N-1数量个便是最小成本 // 题目指出两个节点相减大于1 我们把这个值设为M,也就是说两个节点不是紧连着的,那么要排除N-1个节点中有相连的节点 // 那么我们最多找出 (N-1)(1+M)的最小节点,然后排除两个连续值之间的间距大于M,也就是数组的下标相减绝对值大于M // 从(N-1)(1+M)个最小节点中找出N-1个值即完成

function demo1(numbers, count) { let newNums = numbers.slice(1, numbers.length - 1);

let minNumCount = (count - 1) * 2
let minNums = new Array(minNumCount).fill({
    index: -1,
    value: 1000000
})
newNums.map((value, index) => {
    for (let minIndex in minNums) {
        let minVal = minNums[minIndex];

        if (minVal.value >= value) {
            minNums.splice(minIndex, 0, {
                value,
                index
            })
            break;
        }
    }

    if (minNums.length > minNumCount) {
        minNums = minNums.slice(0, minNumCount)
    }
})

let indexs = []
let values = []

for (let index in minNums) {
    let item = minNums[index]
    if (index == 0 || Math.abs(item.index - indexs[indexs.length - 1]) > 1) {
        // 因为之前去掉了第一个元素,所以下标要加一才能对应上原来的数组下标
        indexs.push(item.index + 1)
        values.push(item.value)
    }
    if (values.length >= (count - 1)) {
        break;
    }
}

console.log(`成本最低断开方案 (${indexs.join(',')}):成本是 ${values.join('+')}=${eval(values.join("+"))}`)

}

// 第二题 function demo2(numbers, count) { // 参数判断 if (count <= 0) return; if (Array.isArray(numbers) && numbers.length < 2) return;

numbers.sort(function (a, b) {
    if (!Number.isInteger(a) || !Number.isInteger(b)) throw '数组元素必须为数字'
    return a - b;
});

let maxNums = numbers.slice(-count).reverse();
console.log(`最大的${count}个元素为 ${maxNums.join(',')}`);

}

// 第三题 // 思路 // 找到最大的正方形,找不到正方形,返回0 // 移动,否则回滚 // 判断是否到底部,到底部返回 function demo3() {

function formatData(list) {
    let newList = [];
    list.map((item, y) => {
        let xList = []
        item.map((subitem, x) => {
            let xx = (subitem ? '1' : '0');
            let yy = xx;
            if (newList.length > 0) {
                if (newList[y - 1]) {
                    yy = newList[y - 1][x].yy + yy;
                }
                if (xList[x - 1]) {
                    xx = xList[x - 1].xx + xx;
                }
            }
            xList.push({
                xx,
                yy
            })
        })

        newList.push(xList)
    })

    return newList;
}

function getMaxLen() {
    let width = list[0].length;
    let height = list.length;
    return width >= height ? height : width;

}

let list = [
    [1, 1, 1, 1],
    [1, 1, 1, 1],
    [1, 1, 1, 1],
    [1, 1, 1, 1],
];
let newList = formatData(list);
let maxLen = getMaxLen(list);

function exec() {
    // 获取最大的正方形
    let isSuccess = getMaxSquare();
    if (!isSuccess) {
        console.log('没有可以移动到右下角的正方形', maxLen)
        return maxLen;
    }

    let isMv = mvTo(0, 0);
    if (!isMv) {
        // 缩减正方形大小
        maxLen--;
        return exec()
    }
    console.log('success', maxLen)
    return maxLen;
}

// 移动正方形
function mvTo(x, y) {

    if (maxLen === 1) {
        console.log('记录', x, y)
    }

    if (x == 2 && y == 3) {
        console.log('记录', x, y)
    }

    // 判断是否移动到右下角
    if (y + maxLen >= newList.length && x + maxLen >= newList[0].length) {
        return true
    }

    let downMv = function () {
        if (isSquare(x, y + 1)) {
            return mvTo(x, y + 1);
        }
        return false;
    }

    let rightMv = function () {
        if (isSquare(x + 1, y)) {
            return mvTo(x + 1, y);
        }
        return false;
    }

    if (downMv()) {
        console.log('向下移动')
        return true;
    } else if (rightMv()) {
        console.log('向右移动')
        return true;
    } else {
        return false;
    }

}

// 获取最大正方形
function getMaxSquare() {
    // 长度小于0,返回false
    if (maxLen <= 0) {
        return false
    }

    // 正方形返回true
    if (isSquare(0, 0)) {
        return true;
    }

    // 减小宽度
    maxLen--;
    return getMaxSquare()
}

// x,y为正方形右上角位置
function isSquare(x, y) {
    // 标识符
    let tag = ''.padEnd(maxLen, '1')
    // 获取右下角元素
    x = maxLen + x - 1;
    y = maxLen + y - 1;

    // 判断右下角是否存在,不存在返回false
    if (!newList[y] || !newList[y][x]) {
        return false;
    }

    // 获取x,y字符串进行对比
    let { xx, yy } = newList[y][x];
    // 获取元素
    xx = xx.slice(-maxLen)
    yy = yy.slice(-maxLen)

    // 判断是否为长度为width的正方形
    return xx === yy && xx === tag;
}

exec();

}

// 第四题 function demo4() { let list = [ [1, 2, 3, 4], [14, 15, 16, 5], [13, 20, 17, 6], [12, 19, 18, 7], [11, 10, 9, 8], ];

let width = list[0].length;
let height = list.length;
let DIR = {
    RIGHT: 0,
    DOWN: 1,
    LEFT: 2,
    UP: 3
};

// 设置起始坐标为-1,0
let x = -1;
let y = 0;
let currentDir = DIR.RIGHT;

// 转向获取数字
function turn() {
    if ([DIR.RIGHT, DIR.LEFT].includes(currentDir)) {
        height--;
    } else {
        width--;
    }
    if (currentDir === DIR.UP) {
        currentDir = DIR.RIGHT
    }
    currentDir++;
}

// 获取数字
function getNum() {
    let len = 0;

    // 根据方向获取长度
    if ([DIR.RIGHT, DIR.LEFT].includes(currentDir)) {
        len = width;
    } else {
        len = height;
    }
    // 根据长度判断是否结束
    if (len == 0) {
        return;
    }
    // 循环长度
    for (let i = 0; i < len; i++) {
        switch (currentDir) {
            case DIR.RIGHT:
                x++;
                break;
            case DIR.LEFT:
                x--;
                break;
            case DIR.DOWN:
                y++;
                break;
            case DIR.UP:
                y--;
                break;
            default:
                break;
        }
        console.log(list[y][x])
    }
    // 转向,缩减长度
    turn();
    // 回调获取数字
    getNum();
}

getNum();

}

// 第五题 function demo5() { console.log( 第一个手机确定范围,第二个手机确定精度, 假如总次数N不变,那么第一个手机第一次扔N层,如果碎了,第二个手机从1开始扔到N-1层找出破碎的楼层 如果第一个手机第一次没碎,那么第一个手机第二次扔N+(N-1)层, 如果还没碎,那么第三次扔N+(N-1)+(N-2)层, 因为总次数不变,为了保证第二个手机的精确度,所以第一个手机每扔一次,下一次的要增加的楼层就减少一层。 那么如果第一个手机扔了N次都没有碎,那么也就是N+(N-1)+(N-2)+...+(N-N)>=100 等差数列求和N(N+1)/2>=100,通过计算最优解N=14 ) }

iliuyt commented 5 years ago

vue部分 1、vue的生命周期,简单描述每个周期 2、vue的双向绑定原理,简单实现输入框的双向数据绑定 3、vue组件传递信息的方式有哪些,分别描述 4、vue的路由方式有几种,分别描述 5、vue和ng、react的区别,优缺点 6、vuex 是什么?怎么使用? 7、keep-alive简单描述,如何使用,生命周期是什么? 8、css 只在当前组件起作用 9、v-if 和 v-show的区别 10、常用修饰符有哪些 11、vue的key作用是啥 12、描述下计算属性的作用 其他 1、form表单可以跨域吗?为什么? 2、如何实现跨域访问。

nodejs 1、Koa-body原理