蓝桥杯入门即劝退(二十四)重复的子字符串(被秒杀)

Posted kook小辉的进阶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯入门即劝退(二十四)重复的子字符串(被秒杀)相关的知识,希望对你有一定的参考价值。

欢迎===关注===点赞===评论,共同学习,共同进步!

------持续更新蓝桥杯入门系列算法实例--------

如果你也喜欢Java和算法,欢迎订阅专栏共同学习交流!

你的点赞、关注、评论、是我创作的动力!

-------希望我的文章对你有所帮助--------

专栏蓝桥杯系列

目录

 一、题目描述

二、解题思路

三、代码实现

四、秒杀算法 !

 代码实现


 一、题目描述

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。

示例 2:

输入: s = "aba"
输出: false

示例 3:

输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)

二、解题思路

1、首先题目意思很简单,即判断是否是由子串重复构成,常规思路是进行枚举遍历。

2、注意其最大子字符串为length/2,即一半,因此我们在寻找其可行的子字符串时范围设置为一半即可。

3、进行遍历,确定一个初始子串长度为L、

4、再次判断是否能被子串整除,可以则开始二重循环,逐个字母判断是否相同。

5、一旦出现某个长度的子字符串可以进行重构即返回true,否则如果最后仍没有符合条件的即false。

三、代码实现

 public boolean repeatedSubstringPattern(String s) 
          int  Len=s.length();
        for (int i=1;i*2<=Len;i++)
        
            if (Len%i==0) 
                boolean match=true;
                for (int j=i;j<Len;j++)//从最靠近的字符开始逐一比对
                    if (s.charAt(j)!=s.charAt(j-i))
                    match=false;
                    break;
                    
                
                if (match==true)
                return true;
            
            
        
        return false;
    

四、秒杀算法 !

1、假设字符串s是由重复字符串构成的,那么把s加倍,即s+s

2、令S=s+s,去掉S的头字母以及尾字母,如果其中包含S即说明s是符合条件的。

3、因此只需要一行代码即可!!

4、indexOf()方法是求字符串某个位置开始匹配目标串的第一个字符的索引值

5、例如s=abbcbba,

  indexOf(bc,3)的值为4

 代码实现

class Solution 
    public boolean repeatedSubstringPattern(String s) 
        return (s + s).indexOf(s, 1) != s.length();
    

 

发文不易,恳请大佬们高抬贵手!


点赞:随手点赞是种美德,是大佬们对于本人创作的认可!


评论:往来无白丁,是你我交流的的开始!


收藏:愿君多采撷,是大佬们对在下的赞赏!

蓝桥杯Web第十四届蓝桥杯(Web 应用开发)模拟赛 1 期-大学组 | 精品题解


🧑‍💼 个人简介:一个不甘平庸的平凡人🍬
🖥️ Nodejs专栏:Node.js从入门到精通
🖥️ TS知识总结:十万字TS知识点总结
👉 你的一键三连是我更新的最大动力❤️!
📢 欢迎私信博主加入前端交流群🌹


📑 目录


🔽 前言


新一期的蓝桥杯大赛开始报名已经有一段时间了,最近博主的粉丝朋友们有很多都已经在积极备考了,也有很多朋友私信我说让我多发发题解,于是我就去蓝桥杯官网碰碰运气,看能不能找到好的题目(因为今年是蓝桥杯开放Web应用开发方向的第二年,官网上的备赛题目比较少),正巧发现蓝桥杯正在举行线上模拟赛,我便花了一些时间做题、总结、写作,于是这篇文章就诞生了。

如标题所见,这是 Web 应用开发模拟赛 1 期大学组 的题解,关于蓝桥杯更多的题解博主会在之后的文章中陆续更新,欢迎大家关注订阅!

话不多说,开撕!

本篇只会大概提出题目要求,关于题目的更多细节可自行去模拟赛主页查询:Web 应用开发模拟赛 1 期大学组

1️⃣ 数据类型检测

这一题大致的意思就是写一个能够判断参数数据类型的函数,咋一看感觉非常的简单,可再仔细一看题目要求,足足需要判断14种类型!如果你的基础知识不牢固是有很大机率通不过这题的,从题目的通过率就可以看出:

作为第一题,虽然只有5分,并且挑战人数是10道题中最多的,但通过率确是10道题中最低的,这恰恰反应了大家的基础核心知识不牢固,所以还是简易大家多补补基础核心知识。

要求:

虽然有14种类型需要判断,但其实只需要一行代码就能通过这题:

/**
 * @description: 数据类型检测
 * @param * data 传入的待检测数据
 * @return * 返回数据类型
 */
function getType(data) 
  // TODO:待补充代码
 return Object.prototype.toString.call(data).slice(8,-1)

JavaScript中判断数据类型主要有以下几种方式:

  • typeof 可以用来区分除了null类型以外的原始数据类型undefinednumberstringsymbolboolean)和对象类型中的函数,针对其它类型时typeof一律返回object类型。

  • instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上,所以它不能用来判断原始数据类型的数据

    并且instanceof的结果并不一定是可靠,因为在ES7的规范中可以通过自定义Symbol.hasInstance方法来覆盖insanceof的默认行为

  • Object.prototype.toString.call 能够满足大部分场景下的需求,但它无法区分数字类型和数字对象类型(同理还有字符串类型和字符串对象类型等,)

    Object.prototype.toString.call(2).slice(8,-1) // "Number"
    // new Number(2)实际是一个数字对象类型
    Object.prototype.toString.call(new Number(2)).slice(8,-1) // "Number"
    

    ES7规范中可以使用Symbol.toStringTag自定义Object.prototype.toString方法的行为,所以该方法判断数据类型也不一定是完全可靠的。

  • Array.isArray 用来判断是否是数组

所以这题对于知道Object.prototype.toString.call方法的同学来说,几乎就是秒解!

2️⃣ 渐变色背景生成器

这题所实现的渐变色背景生成器还是非常有意思的,推荐大家去看一下它完整的源码(代码非常少):

主要考察的就是通过JavaScript来修改自定义的 CSS 变量,题中主要的代码如下(并不是全部代码,不需要我们了解与实现的代码这里就没有贴出,原题可自行查阅蓝桥官网)

HTML:

 <div class="controls">
   <input id="color1" type="color" name="color1" value="#00dbde" />
   <input id="color2" type="color" name="color2" value="#fc00ff" />
 </div>

CSS:

/* 注意这里定义的 CSS 变量,它们会用于生成渐变色背景 */
:root 
  --color1: #00dbde;
  --color2: #fc00ff;

const inputs = document.querySelectorAll(".controls input");

/**
 * 上面已经选取了两个取色器
 * 请添加相应的 JS 事件处理函数并绑定到合适的事件监听器上(提示:change 事件)
 * 这样我们就可以用取色器选取颜色来生成下方的渐变色背景啦
 *  */

 inputs.forEach((item)=>
    item.addEventListener("change",function (e) 
        document.querySelector("html").style.setProperty(`--$e.target.id`, e.target.value);
    )
 )

遍历获取到的两个取色盘元素(input.color),分别对其添加change事件,然后通过document.querySelector("html").style.setProperty方法修改html元素(根元素,也即是:root)上css变量的值即可。

这一题题目参考信息中给出了如何使用CSS变量的介绍,根据这个提示来做这题还是非常简单的。

3️⃣ 水果叠叠乐

这简直就是简易般的羊了个羊:

这一题有个坑,就是点击元素时是需要将这个被点击的元素克隆一份添加到下方的栏中,而不是直接将被点击的元素移动到下方的栏中。

具体实现代码如下

HTML:

<ul id="card">
  <li data-id="1" id="fruit-one">
    <img src="./images/pineapple.svg" alt="" />
  </li>
  <!-- 多个li... -->
</ul>
<!-- 图片位置 -->
<!-- 卡槽位置 -->
<div class="fixed">
  <div class="gradient-border" id="box"></div>
</div>

JavaScript:

$("#card li").on("click", function (e) 
  // TODO: 待补充代码
  if($("#box li").length===7) return;

  // 向box中添加当前点击元素的克隆
  $("#box").append($(this).clone());
  // 隐藏当前点击元素
  $(this).hide();
 
  // 找到与当前点击元素类别一样的其它所有元素
  const list=$(`#box li[data-id=$this.getAttribute('data-id')]`);

  if (list.length>=3) 
    // each是jQuery遍历元素的方法
    list.each((i,item)=>
      // 移除元素
      item.remove()
    )
  
);

我们知道DOM的事件处理函数中的this指的是触发事件的DOM元素,我这里使用$()包裹this$(this))的目的是使this变成JQ对象,从而能够使用jQuery提供的方法,如clone克隆元素。

4️⃣ element-ui 组件二次封装

需要封装element-ui 的表格组件,实现点击表格组件左侧radio时选中该行,题目要求说了一大堆,其实实际实现只需修改两行代码就行:

<!-- TODO:完善单选按钮组件,实现需求(DOM 结构不能修改) -->
<template slot-scope="scope">
   <el-radio v-model="currentRow" :label="scope.$index">&nbsp;</el-radio>
</template>

5️⃣ http 模块应用

要求就是使用原生http模块,搭建起来一个简单的Node服务器,并返回 “hello world” ,考察的就是基础的原生知识,如果你对Node还不了解,可以订阅我的
Node.js从入门到精通专栏(私信进群能够享返现活动)。

// TODO: 待补充代码
const http = require("http");

const app = http.createServer();

app.on("request",function (req,res) 
    res.end("hello world")
)

app.listen(8080)

6️⃣ 新课上线啦

就是按照官方给的最终效果图,去实现下面这个页面:

没啥技术含量,全靠堆HTML和CSS,这里就不放代码了。

但这个题是我认为是整场模拟赛里最坑人的题,特别废时间,我建议这个题要么放到最后再写(因为完成度50%以上就能得到分,其它题不行),要么完成差不多后就直接去做下面的题,别死扣细节,不然吃亏的都是你!

7️⃣ 成语学习

这个题也是非常的有意思,不过需要我们写的代码并不多,大多都是官方已经给出了。

//TODO 点击文字后,在idiom从左到右第一个空的位置加上改文字
getSingleWord(val) 
  for (let i = 0; i < this.idiom.length; i++) 
    if (!this.idiom[i]) 
      this.idiom[i] = val
      this.$set(this.idiom, i, val)
      return
    
  


// TODO 校验成语是否输入正确答案
// 猜中成语 result 为 true;
// 猜错成语 result 为 false;
// 例1:tip=‘形容非常感激或高兴’,idiom=["热","泪","盈","眶"],则result返回true
// 例2:tip=‘形容非常感激或高兴’,idiom=["泪","眼","盈","眶"],则result返回false
// 例3:tip=‘在繁忙中抽出空闲来’,idiom=["忙","里","偷","闲"],则result返回true
confirm() 
  const target = this.arr.find(item => item.tip === this.tip);
  if (target.word === this.idiom.join('')) 
      this.result = true
  else 
      this.result = false
  

这里使用的是vue2,需要注意的一点就是当我们直接修改data里的数组中的元素时,视图并不会响应式更新,如果你了解vue2的响应式原理,应该明白这是vue2响应式的一个缺陷所在,我们必须使用$set来修改触发从而引发视图更新。

其实题中原有的代码已经显示了这一点,如clear函数:

clear(i) 
  this.idiom[i] = ""
  this.$set(this.idiom, i, "")
,

8️⃣ 学海无涯

这一题稍微有点复杂,但只要自己理清楚思路,还是能够做出来的,先看一下效果:

题中使用了Echarts,了解Echarts的朋友知道 Echarts 的表格有x轴和y轴的数据(都是数组形式),所以我们知道只要将题中给我们的数据转换成对应的格式就行了。

复杂的地方在于数据处理,原数据如下:

"data": 
 "2月": [
   30, 40, 30, 20, 10, 20, 30, 69, 86, 12, 32, 12, 23, 40, 50, 61, 39, 28,
   20, 35, 20, 38, 43, 52, 30, 39, 52, 70
 ],
 "3月": [
   36, 48, 52, 30, 39, 52, 20, 18, 25, 33, 21, 36, 44, 63, 32, 89, 98, 23,
   25, 36, 29, 31, 42, 23, 45, 56, 98, 83, 25, 28, 48
 ]

我的思路就是将原数据转换成两个对象,一个代表周的x轴y轴数据,一个代表月的x轴y轴数据,所以两个对象的结构是一模一样,转成后的两个对象如下:

// 周数据
weekData = 
  x: ['2月第1周', '2月第2周', '2月第3周', '2月第4周', '3月第1周', '3月第2周', '3月第3周', '3月第4周', '3月第5周'],
  y: [180, 274, 253, 324, 277, 240, 332, 378, 101]

// 月数据
monthData = 
  x: ['2月', '3月'],
  y: [1031, 1328]

现在我们根据代码来一点点了解我是如何转换的:

// TODO:待补充代码
let weekData =
  x:[],
  y:[]
, monthData =
  x:[],
  y:[]


// 定义一个函数:用来修改option对象并重置Echarts图标
function mySetOption(data) 
  // 修改x轴数据
  option.xAxis.data = data.x;
  // 修改y轴数据
  option.series[0].data = data.y;
  // 重置图表
  myChart.setOption(option);


// 添加点击事件
document.querySelector(".tabs").addEventListener("click",function (e) 
  if (e.target.id==="week") 
    mySetOption(weekData)
  else if(e.target.id==="month") 
    mySetOption(monthData)
  
)

// 获取数据
axios.get('./data.json').then(res=>
  const data = res.data.data

  for (const key in data) 
  	// weekCount代表一周数据的和,monthCount代表一月数据的和,weekNum代表第几周
    let weekCount = monthCount =0,
        weekNum = 1;
        
    for (let i = 0; i < data[key].length; i++) 
      // 数据累加
      weekCount += data[key][i];
      monthCount += data[key][i];
      
      // 每一周的最后一天或不足一周的最后一天进行push数据
      if ((i+1) % 7 === 0 || ((data[key].length - i <= 7) && (i === data[key].length - 1))) 
        weekData.x.push(`$key$weekNum++`)
        weekData.y.push(weekCount)
        // 重置周数据的和为0
        weekCount = 0
      
    
    monthData.x.push(key)
    monthData.y.push(monthCount)
  
  // 获取到数据后调用一次mySetOption重置图表
  mySetOption(weekData)
)

代码不算难,相信大家根据代码里的注释都能够理解,着重说一下上面我使用的 if 表达式:

(i+1) % 7 === 0 || ((data[key].length - i <= 7) && (i === data[key].length - 1))

要明白我们求每一周的总数居时需要在第二周开始前将weekCount归零,我选择了在每周的最后一天(且已经push了数据)重置weekCount,而不是在每周的第一天(计算数据之前)重置weekCount,是因为我感觉这样做判断比较好写。

首先(i+1) % 7 === 0判断了是每星期的最后一天,如:第一周的星期日,在数组中下标为6,加上1对7取余就得0。

((data[key].length - i <= 7) && (i === data[key].length - 1)data[key].length - i <= 7代表剩余的数据不足7条,i === data[key].length - 1代表到了数组最后一项。之所以做这么一个判断,是为了适配天数不是7的倍数的情况,如3月31天,计算完前4周的数据后剩余3天的数据(31-4x7),这3天也要求和作为第5周的数据,所以需要在最后一天结算这三天。

9️⃣ 逃离二向箔

这个题目很有意思,让我瞬间想起了三体宇宙,顿时感觉这题不简单,结果还正如我所想,题中考察的是promise以及JavaScript中的事件执行机制(先执行同步代码再执行异步代码),对于promise,相信大多数人都会比较头疼,这一题考察的角度也比较刁钻,让我们一起来看一看吧!

题目的大致要求就是有一个数组,里面存放了很多需要发射的飞船(一个返回promise对象的函数),然后给了我们一个最大数量,我们只能一次性发送这个最大数量的飞船,当有一个飞船发射成功(promise执行结束),我们才能继续发射下一个飞船。


完整代码:

// 使用 promise 模拟请求 + 3000ms后完成得到发射后结果
function createRequest(i) 
  return function () 
    return new Promise((resolve, reject) => 
      const start = Date.now();
      setTimeout(() => 
        if (Math.random() >= 0.05) 
          resolve(
            `$i + 1艘曲率飞船达到光速,成功逃离,用时$Date.now() - start`
          );
         else 
          reject(
            `$i + 1艘曲率飞船出现故障,无法达到光速,用时$
              Date.now() - start
            `
          );
        
      , 3000 + i * 100);
    );
  ;


class RequestControl 
  constructor(蓝桥杯Web第十四届蓝桥杯(Web 应用开发)模拟赛 1 期-大学组 | 精品题解

蓝桥杯Web第十四届蓝桥杯(Web 应用开发)模拟赛 1 期-职业院校组 | 精品题解

2023年第十四届蓝桥杯JAVA B组题目

Redis(二十四)-秒杀案例之库存遗留问题解决

Redis(二十四)-秒杀案例之库存遗留问题解决

第十四届蓝桥杯python第一期模拟赛