CSS面试题+大厂算法面试题(合集)

230 阅读6分钟

面试题合集

话不多说,直接看样式。面试官上来就问你这个模拟手风琴如何实现,你会如何做呢?

屏幕录制 2024-06-01 221419.gif

模拟手风琴

其实很简单,从结构上,很容易分析出有一个大盒子装着六个小盒子,六个盒子都摆在同一行。这里我们可用div大盒子包裹六个div小盒子,也可以直接用ul包裹六个li,组成一个无序列表, 像下面这样:

image.png

这里我们顺带提一下CSS reset,代表初始化css,其目的是消除不同浏览器对于HTML元素的默认样式差异,确保在各种浏览器中元素的呈现效果一致,为网站或应用程序创建一个干净、统一的起点,通常我们都会在css前面加上如下样式:

image.png

然后给消除默认li前面的小圆点设置:

image.png

并且将ul设为宽度600px,高度200px,的弹性容器。接下来就是对每一个li进行样式设定。如下所示:

image.png

重点:

这里将li设为 flex: 1;主要是让六个li盒子占据ul的六分之一,也就是让li均分ul600px宽度 所以每个盒子大概就是100×200 px的像素:

image.png 这个 cursor:pointer; cursor 是一个CSS属性,用于改变鼠标指针在悬停于特定元素上时的形状。当设置为pointer值时,鼠标指针会变成一只手形(通常表示为一个指向的手指图标),这通常用来指示该元素是可以点击的,比如链接、按钮或者是可交互的元素。这个只是细节处理,无关紧要。

text-aline:center 主要是将内部的文本水面居中,他常用的属性值是leftright,center,分别是向左,居中,向右靠近。而line-height,主要是用于设置行间距,也就是文本行基线之间的垂直距离。当line-height等于hight行高时,可以达到文本垂直居中的效果。

没加line-height前: image.png

添加line-height后:

image.png

transition较为特殊是一个过渡动画的特性,它有三个属性值:

  • property: 定义应用过渡效果的CSS属性名称。如果想要对所有可过渡的属性应用效果,可以使用all
  • duration: 定义过渡效果需要多少秒或毫秒完成。例如,0.5s 表示半秒。
  • timing-function: 定义过渡效果的时间曲线,默认是ease。其他常用值包括linear(匀速)、ease-in(加速)、ease-out(减速)和ease-in-out(先加速后减速)。

至此,我们将手风琴页面结构完成了,剩下就是选中这些li实现样式的改变了。这里使用css的伪类选择器去选定每一个li的背景颜色。 image.png

image.png

最后写入li:hover当鼠标移动到li的区域内发生反应,使得li的样式改为flex: 2,为什么是这样呢?当我们鼠标移动到第一张图片时,它所占的整体的两份。前面总共有六个li,都为flex:1意思是占ul的1/6,刚好均分,现在有一个li变为占两份了,那就是现在鼠标指向的这个li占2/7。很容易看到其它的li都会缩小一点,写到这你的手风琴就写完了!

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>手风琴</title>
    <!-- <link rel="stylesheet" href="common.css"> -->
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        ul{
            list-style-type: none;
        } 
        .accordion {
            display: flex;
            width: 600px;
            height: 200px;
        }
        .accordion li {
            flex: 1;
            cursor: pointer;
            line-height: 200px;
            text-align:center;
            color: #fff;
            transition: flex 500ms;
        }
        .accordion li:nth-child(1) {
            background-color: #f66;
        }
        .accordion li:nth-child(2) {
            background-color: #66f;
        }
        .accordion li:nth-child(3) {
            background-color: #f90;
        }
        .accordion li:nth-child(4) {
            background-color: #09f;
        }
        .accordion li:nth-child(5) {
            background-color: #9c3;
        }
        .accordion li:nth-child(6) {
            background-color: #3c9;
        }
        .accordion li:hover {
            flex: 2;
        } 
    </style>
</head>
<body>
    <ul class="accordion">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
    </ul>
</body>
</html>

发红包算法

最近在和一些参加了春季招聘的学长们聊天的时候聊到他们的面试经历,光听那个过程就感觉汗流浃背了,想想再过一段时间自己也要和他们一样,经历面试官的"严刑拷打",所以我选择提前适应,哈哈哈哈。话不多说,还是先来看看这道问的很多的发红包算法吧!

红包算法其实很简单,就是让你去模拟一下发红包的那个过程,但是需要满足几个要求:

  1. 随机
  2. 保证公平有趣

在这里我们有一个简单易理解的版本,可以让我们更好的理解这个分发过程了。 首先分析一下,为了公平公正,我们要看有多少个红包,total金额是多少,尽可能少的0.01元,每个加起来总共等于total金额等问题。

好,那么我们现在可以这样做,为了保证随机的红包金额总共可以等于total总金额。让最后一个人领取的红包金额等于总共金额减去每次随机后的金额,也就可以保证金额的随机且不超出。

代码如下,稍后我们来解释:

function hongbao(total,num){
    // 发红包的那一刻已经决定了
    const arr = [];
    //余额
    let restAmout = total;
    // 未领取人数
    let restNum = num;
    for(let i = 0; i< num -1;i++){  //num-1次
        let amount = parseFloat(Math.random()*(restAmout/restNum*2)).toFixed(2); //金额到小数点后两位
        restAmout -= amount;
        restNum--;
        arr.push(amount)
    }
    //最后一人的金额
    arr.push(restAmout.toFixed(2))
    return arr;
}

这里创建一个红包随机算法,传入参数总金额红包数,然后定义一个数组arr作为返回值,即每个红包金额,先初始化剩余金额restAmout未领取人数restNum,循环num-1次,也就是前num-1次随机金额,最后一人固定拿restAmout金额,在定义amount时,我们看代码,为什么要(restAmout/restNum*2)这样?

主要还是公平随机金额,Math.random()会产生0-1的随机数,当产生的随机数和这个式子相乘,如果传入20元总金额,20个红包,则随机金额最大也就是一块左右,再乘2加大随机金额,保证每个红包最大随机不超过2元。这也就使得随机红包更加公平了!我们后面再看看有没有更好,更公平的算法吧(等找到了就下次分享)。

今天的内容就分享到这吧,学习的面试题后面都会有持续更新,请点赞关注,观看后续的内容吧!