前言
官方地址https://edu.csdn.net/skill/algorithm
蓝桥杯算法,博主以js方式实现,方便前端、及node开发的同学们参考。交流
近期陆续更新…你们当提刷吧,前端工作用的到的,看过去一遍,以后碰到类似需求回来ctrl+f关键字查
2022/05/12博主:知道了,我更新,别私信催别催。。。。
一、基础算法
1.切面条
一根高筋拉面,中间切一刀,可以得到2根面条。
如果先对折1次,中间切一刀,可以得到3根面条。
如果连续对折2次,中间切一刀,可以得到5根面条。
那么,连续对折10次,中间切一刀,会得到多少面条呢?
1+Math.pow(2,n) // 2的n次方
2.大衍数列
中国古代文献中,曾记载过“大衍数列”, 主要用于解释中国传统文化中的太极衍生原理。它的前几项是:0、2、4、8、12、18、24、32、40、50 …其规律是:对偶数项,是序号平方再除2,奇数项,是序号平方减1再除2。第100 项的值。
for(var i=1;i<100;i++){
if(i%2==0){
console.log(Math.pow(i,2)/2)
}else{
console.log((Math.pow(i,2)-1)/2)
}
}
3.门牌制作
1-2020有多少个2
//方法一2层for
var size=0
for(var i=1;i<=2020;i++){
(i+"").split("").forEach(val=>{
if(val=="2"){
size+=1
}
})
}
console.log(size)//624个
//for do while
var size=0
for(var i=1;i<=2020;i++){
var j=i
while(j>1){ //因为会有0.2020这种值
if(j%10==2){ //2020%10=2
size++
};
j=parseInt(j/10)//不然乎变成2.020
}
}
console.log(size)//624
3.方阵转置
[[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]
顺时针旋转90度变成
[[13,9,5,1],
[14,10,6,2],
[15,11,7,3],
[16,12,8,4]]
//新建二维数组
var Xsize=4;//几*几的矩阵,题目是4*4的矩阵
var Ysize=4;//几*几的矩阵,题目是4*4的矩阵
var arr=new Array();
var mun=1;
for(var i=0;i<Xsize;i++){
arr[i]=[]
for(var j=0;j<Ysize;j++){
arr[i][j]=mun;//二维数组赋值
mun++
}
}
//执行结果如下
// [
// [1,2,3,4],
// [5,6,7,8],
// [9,10,11,12],
// [13,14,15,16]
// ]
console.log(arr)
//方阵转置
var newArr=new Array();//用来存转置后的值的数组
for(var i=0;i<Ysize;i++){ //博主ps:这里注意,如果是4*3的矩阵,你还是一个变量,就会出现[undefined,undefined,undefined,undefined],因,这样,不管是正方形还是矩形,都没问题了。
newArr[i]=[]
for(var j=0;j<Xsize;j++){
newArr[i][j]=arr[j][i]
}
}
console.log(newArr)
//转置其实就是 arr[0,3]和arr[3,0]的值互换 也就是二维数组键名 [x,y]的键值等于[y,x]的键值。
//执行结果如下
// [
// [1,5,9,13],
// [2,6,10,14],
// [3,7,11,15],
// [4,8,12,16],
// ]
//接下去只要将每一行的数值头尾对换,也就是newArr的 [0,0]的值等于[3,0] 的,[1,0]等于[2,0]的值以此类推
var lastArr=[];
for(var i=0;i<Ysize;i++){
lastArr[i]=[]
for(var j=0;j<Xsize;j++){
lastArr[i][j]=newArr[i][Xsize-j-1]
}
}
console.log(lastArr)
4.微生物增殖
假设有两种微生物 X 和 Y
X出生后每隔3分钟分裂一次(数目加倍),Y出生后每隔2分钟分裂一次(数目加倍)
一个新出生的X,半分钟之后吃掉1个Y,并且,从此开始,每隔1分钟吃1个Y。
现在已知有新出生的 X=10,Y=90,求60分钟后Y的数目。
time | m个0.5分 | x | y |
---|---|---|---|
0 | 0 | 10 | 90 |
0.5 | 1 | 10 | 90-10=80 |
1 | 2 | 10 | 80 |
1.5 | 3 | 10 | 80-10=70 |
2 | 4 | 10 | 70*2=140 |
2.5 | 5 | 10 | 140-10=130 |
3 | 6 | 10*2=20 | 130 |
3.5 | 7 | 20 | 130-20=110 |
4 | 8 | 20 | 110*2=220 |
//半分等于0.5分,循环时以0.5为统计单位,要统计120次。
var x=10;
var y=90;
for(var i=0;i<120;i++){
if(i%2==1){//x吃y
y-=x
}
if(i%4==0){//y分裂
y*=2
}
if(i%6==0){//x分裂
x*=2
}
}
console.log(y)//94371840
5.成绩统计(冒泡法)
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。
如果得分至少是 60 分,则称为及格。
如果得分至少为 85 分,则称为优秀。
7个同学成绩 80,92,56,74,88,100,0
请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整数。
单科
var arr=[
80,92,56,74,88,100,0
]
var mun60=0;
var mun85=0;
for(var i=0;i<arr.length;i++){
if(arr[i]>=60){
mun60++
}
if(arr[i]>=85){
mun85++
}
}
var mun60Val=Math.round(mun60*100/arr.length)//逢5进1
var mun85Val=Math.round(mun85*100/arr.length)
console.log("及格率:"+mun60Val+"%,优秀率:"+mun85Val+"%")//及格率:71%,优秀率:43%
多科 (本博主扩展) 以单向链表方法录入数据,以冒泡法求出全班平均分最高和最低的同学。
学号 | 姓名 | 数学 | 语文 | 英语 |
---|---|---|---|---|
1 | 小明 | 90 | 60 | 70 |
2 | 小红 | 70 | 80 | 85 |
3 | 小黄 | 70 | 70 | 99 |
4 | 小刚 | 100 | 85 | 60 |
5 | 小王 | 88 | 77 | 50 |
6 | 小李 | 60 | 75 | 100 |
//单向链表 方法(别纠结 不想写class)
function list(){
let m=this;
//节点
function Nodes(data){
this.data=data
this.next=null;
}
m.length=0;
m.head=null;
//新增
list.prototype.append=function(data){
let newNodes=new Nodes(data);
let nowData=m.head;
if(m.head){
while(nowData.next){
nowData=nowData.next//相当于指针
}
nowData.next=newNodes
}else{
m.head=newNodes
}
m.length++
}
//平均成绩最高的小朋友
list.prototype.maxminFun=function(callback){
callback=callback||function(){}
let nowData=m.head;//当前指针位置
let maxData=m.head;//最大值
let minData=m.head;//最小值
while(nowData.next){
let countA=nowData.data.shuxue+nowData.data.zn+nowData.data.en
let countB=maxData.data.shuxue+maxData.data.zn+maxData.data.en
let countC=minData.data.shuxue+minData.data.zn+minData.data.en
if(countB<countA){//正常3科之和大,平均分就高,所以对比总和就够了,这里哥就不考虑相等的情况了,大家自己扩展
maxData=nowData
}
if(countC>countA){
minData=nowData
}
nowData=nowData.next
}
callback(maxData.data.name,minData.data.name)
}
}
//数据
var ranking=new list();
var rankRes=[
{id:1,name:"小明",shuxue:90,zn:60,en:70}, //220
{id:2,name:"小红",shuxue:70,zn:80,en:85}, //235
{id:3,name:"小黄",shuxue:70,zn:70,en:99}, //239
{id:4,name:"小刚",shuxue:100,zn:85,en:60}, //245
{id:5,name:"小王",shuxue:88,zn:77,en:50}, //215
{id:6,name:"小李",shuxue:60,zn:75,en:100} //235
]
rankRes.forEach(item=>{//懒
ranking.append(item)
})
ranking.maxminFun((max,min)=>{
console.log(`平均成绩最高:`+max,`,最低:`+min)
})
//冒泡法
6.星系炸弹
高斯日记:
大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210
后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,
它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?
高斯出生于:1777年4月30日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。高斯获得博士学位的那天日记上标着:8113
请你算出高斯获得博士学位的年月日
//这个感觉没必要计算闰年啥的,直接时间戳加减感觉就可以了啊,博主直接上直接的笔记
//获取日期
function getPreDate(pre,date,type) {//pre 向前推几天 type,date有传日期就从data日期开始推, 如果是true 就赛选返回那天的前一天 59分59秒
var c = new Date();
if(date){
c=new Date(date)
}
c.setDate(c.getDate() - pre);
if(type){
return formatDate(c)+" 23:59:59"
}else{
return formatDate(c);
}
}
function formatDate(d) {
return d.getFullYear() + "-" + getMonth(d.getMonth()) + "-" + getMonth(d.getDate(), "getDate")
}
function getMonth(m,type) {
if (type != "getDate") {
m++;
}
if (m < 10)
return "0" + m.toString();
return m.toString();
}
var today= getPreDate(0)//今天日期 "2022-04-27"
var tomorrow= getPreDate(-1)//明天日期 "2022-04-28"
var yesterday= getPreDate(1)//昨天日期 "2022-04-28"
var day5343=getPreDate(-(5343-1),"1777-04-30")//"1791-12-15"
var day8113=getPreDate(-(8113-1),"1777-04-30")//"1799-07-16"
7.特别数的和
小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),
在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。
请问,在 1 到 n 中,所有这样的数的和是多少?
//博主ps,这题要注意看,像13 14,这里面十位数是1,也就是 13和14也是要算进去的,23 24.十位数是2也要算进去。
var x=40;
var count=0
for(var i=1;i<=x;i++){
if(whileFun(i)){
count+=i
}
}
function whileFun(val){
while(val>0){
var theVal=val%10;
if(theVal==0||theVal==1||theVal==2||theVal==9){
return true;
}
val=parseInt(val/10)
}
return false;
}
8.蛇形填数
如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
1 2 6 7 15 …
3 5 8 14 …
4 9 13 …
10 12 …
11 …
…
容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列的数是多少?
//算法一
如果光算 {20,20}的值很简单
//{0,0}{1,1}{2,2}{3,3}{4,4}{5,5}分别对应 1 5 13 25 41 61
//两两差值为 4 8 12 16 20为4的倍数
//差值为4*1 4*2 4*3
var n=20-1;//20-1
var val=1;//{0,0}开始 加 {20,20} 是加了19次
for(var i=1;i<=n;i++){
val+=4*i;
}
console.log(val)//20行20列为 761
//算法二,博主自己想的逻辑。 主要是解决 {10,15}这种不等的坐标值
//{x,y}
// {0,0} {1,0} {2,0} {3,0} 1 2 6 7
// {0,1} {1,1} {2,1} 3 5 8
// {0,2} {1,2} 4 9
// {0,3} 10
var numX=20; //(这是X轴,记得减1才是坐标)20排20列坐标是 {19,19}数组{0,0}开始算的
var numY=20; //(这是Y轴)记得减1才是坐标)20排20列坐标是 {19,19}数组{0,0}开始算的
var val=1;
var arr=[]
var x=0;y=0;
var gosize=0;
var isPlay=true
while(isPlay){
if(!arr[y]){
arr[y]=[]
}
arr[y][x]=val;
if(x==(numX-1) &&y==(numY-1)){
isPlay=false;
break;
}
if(y==0){//
if(gosize==0){
x++
gosize++
}else if(gosize==1){
y++;
x--
}else if(gosize==-1){
x++
gosize=1
}
}else if(x==0){
if(gosize==1){
y++
gosize--
}else if(gosize==0){
x++
y--
gosize--
}
}else if(gosize==-1){
x++
y--
}else if(gosize==1){
x--
y++
}
val++;
}
console.log(arr[y][x])//761