1.找一个数列中的最长”上升下降“序列的数组下标
比如
8 //数列长度
1 3 1 2 5 4 3 9 //数列
0 1 2 3 4 5 6 7 //数列下标
那么下标就是
2 6
这个需要设参数来确保是上升还是下降序列,看代码吧。
var incredecre=function(array){
var incre;
var finalstart=-1,finalend=-1,maxlen=0;
var len=0,start=-1,end=-1;
if (array.length<3) {return false;}
else{
for (var i = 0; i < array.length-1; i++) {
if(array[i]<array[i+1]) {
if (incre!=true) {start=i;len=1;}
else{len++;}
incre=true;
}
else {
if(incre===true){
len++;
if(!array[i+2]||array[i+1]<=array[i+2]){
len++;end=i+1;
if(maxlen<len){maxlen=len;finalstart=start;finalend=end;}
}
}
else if(incre===false){
if(!array[i+2]||array[i+1]<=array[i+2]){
len+=2;end=i+1;
if(maxlen<len){maxlen=len;finalstart=start;finalend=end;}
}
else {len++;}
}
incre=false;}
console.log("start "+start+" end "+end+" len "+len+"incre "+incre);
}
console.log("finalstart "+finalstart+"finalend "+finalend+"maxlen "+maxlen);
return true;
} //end of else
}; //end of function incredecre
只扫一遍。
为了表示效果,console台输出了整个过程,比如:
测试代码如下,本来还想小数点保留1位的,但发现1位小数点我就开始晕了(啊,为我的脑容量默哀。。。。)所以都搞成了整数。
var createRandomList=function(){
var list=[];
for (var i = 0; i < 10; i++) {
var item=10*Math.random();
list.push(+item.toFixed(0));}
return list;
};
如果上面那种不是非常好理解的话,还可以用找极大点的方法,先扫到某个数arrary[i]>array[i+1]&&array[i]>array[i-1],然后对这个极大点向左向右扫,找到start和end。但在坏的情况下,要扫2*array.length次。效率不高。
2.给出包括m个句子的查询组(B),和n个句子的被查询组(A)。对查询组中的每个句子,找出被查询组中相同单词数最多的句子。
更新:还是用hash做预处理。
下面是原来的暴力解法
var eqcount_sentence=function(sen1array,sen2array){
var eqnum=0;
for(var i=0;i<sen1array.length;i++){
for(var j=0;j<sen2array.length;j++){
if(sen1array[i]===sen2array[j])
{eqnum++;}
}
}
return eqnum;
};
var nm="3 2";
var n,m;
n=nm.split(" ")[0];
m=nm.split(" ")[1];
var l=[],w=[],senl=[],sen=[];
var eqnum=[];maxeq=[];
sen[0]="i love you";
sen[1]="i love i love";
sen[2]="you hate you";
for(var i=0;i<n;i++){
// sen[i]=read_line();
senl[i]=sen[i].split(" ");
}
var query=[],qul=[],qlen=[],x=[];
query[0]="love i";
query[1]="you hate love";
for(i=0;i<m;i++){
//query[i]=read_line();
qul[i]=query[i].split(" ");
eqnum[i]=[];maxeq[i]=-1;x[i]=-1;
for(var k=0;k<n;k++){
eqnum[i][k]=eqcount_sentence(qul[i],senl[k]); //eqnum[i]是第i行查询行对第k行被查询行的相同单词数
if(maxeq[i]<eqnum[i][k]){
maxeq[i]=eqnum[i][k];
x[i]=k;
}
}
console.log(sen[x[i]]);
}
关于怎么算两个句子中的相同单词数,我是这么理解的:
这是最笨的暴力求解法,有人说用hash,我想到了kmp,但都觉得不是很实用。而且kmp想来想去无从下手。毕竟是真实的单词和句子。扫n, 扫m感觉都是必须的。能优化的应该是那个两个句子统计相同单词数的地方吧。
一个是两个单词比较的部分,代码里直接是===,但如果将单词看作字符串的话,可以先比个长度再依次比,或者跳跃比(类似希尔排序),因为单词的前后缀可能相同,这样打乱顺序比较概率上说如果有不同可以尽快发现。
一个是用自带的indexOf来做,相信js 自带的功能跑的要快。。。
var eqcount_sentence=function(sen1array,sen2array){
var eqnum=0;
for(var i=0;i<sen1array.length;i++){ //sen1array当做查询组
var item=sen1array[i];
var y=sen2array.indexOf(item);
if(y!=-1){
y=sen2array.indexOf(item,y+1);
eqnum++;
}
}
return eqnum;
};
还有个好处就是不用把被查询组的句子转成单词数组了,可以少扫一遍段落。这个还是挺好的。
这样做的注意事项是,两个参数的位置不能颠倒,不然结果减半。
senl是啥见上面的代码,自定义的。没了编译器,js读入数据要自己搞,这个真愁人。赶紧学nodejs!
再有就是先学习查询句的结构了,比如看看有没有相同的单词,可以直接砍掉,然后对那个单词eq*2。这个如果查询句长的话也许有点用,但现实生活的话,一个句子中某个单词多次出现,应该是歌词吧。。。
3.给出A,B两个数组和条件组,每个条件组x,y两个数,找出满足Ai>=x&&Bi>=y的i的个数。隐含条件是A,B两个数组等长??
var counti=function(arr,brr,condition){
var num=0;
for(var i=0;i<arr.length;i++){
if(arr[i]>=condition[0]&&brr[i]>=condition[1]){
num++;
}
}
return num;
};
var A="3 2 4";
var B="6 5 8";
var a=A.split(" ");
var b=B.split(" ");
condition1=[1,1];
condition2=[4,8];
counti(a,b,condition1);
counti(a,b,condition2);
结果是
3
1
不是很理解,感觉这也太简单了吧?不知道是不是理解错了题意,明天应该就有官方答案出来了。到时看看。
更新,啊啊,就知道没那么简单,肯定是要靠通过率卡优化的。回去整树状数组。
考试的时候出了点问题,一个都没通过。啊。等于编程空白了。
上午写了一道,把电脑锁在柜子里,晚上准备继续,发现柜子打不开了。。。守到8点多终于来了人把电脑解救出来。差一点电脑就要在柜子里过清明了。。。
登录网易官网想查询一下信息,说没有投递记录,换了另一个邮箱登录,说没有这个用户。可是笔试通知还是发到这个邮箱的。。。真是醉了。我可能投了个假简历。不过反正笔试的也不好,就随意吧。
去登录爱奇艺的招聘,发现居然注册过手机号,还是个男性头像,还是个非主流名字,完全没有印象。啊,我究竟有没有脑子?这是个老问题了。
最后是javascript的在线编程tips:
- for循环不要用let 不要用es6
- 如果让外部调试,一上来先写封装好的函数和console.log输出,不要直接print||read_line() 除非有把握一次成功。
- 如果不让调试,唉,那就听天由命吧。
- 赶紧瞅吧瞅吧node!