javascript剑指offer编程练习#6

第四十五题

题目描述
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

function IsContinuous(numbers)
{
    // write code here
    let times=[]
    for(let i=0;i<13;i++){
         times[i]=0
    }
    if(numbers.length!=5){
        return false
    }
    let max=-1
    let min=14
    for(let i=0;i<numbers.length;i++){
        times[numbers[i]]++
        if(numbers[i]==0){
            continue
        }
        if(times[numbers[i]]>1){
            return false
        }
        if(numbers[i]>max){
            max=numbers[i]
        }
        if(numbers[i]<min){
            min=numbers[i]
        }
    }
    return max-min<5  
}

该问题的思路是先定义一个数组times,里面储存牌面数字出现的次数,当有重复数字出现时,return false,大小王可以看成任何数字,且在数组里显示为0,则判断拿到的牌组最大差值是否小于5即可

第四十六题

题目描述
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)

function LastRemaining_Solution(n, m)
{
    // write code here
    if(n===0){
        return -1
    }
    if(n===1){
        return 0
    }else{
        return (LastRemaining_Solution(n-1,m)+m )%n
    }
    
}

第四十七题

题目描述
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

function Sum_Solution(n)
{
    // write code here
     let sum=0
     plus(n)
     return sum
     function plus(num){
         sum+=num
         num>0&&plus(--num)
     }
}

第四十八题

题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

function Add(num1, num2)
{
    // write code here
    let sum,carry
    do{
        sum=num1^num2
        carry=(num1&num2)<<1
        num1=sum
        num2=carry
    }while(num2!=0){
        return num1
    }
}

需要利用按位操作符来解决该问题
比如我们计算5+17=22这个结果,世界上,我们可以分为3个步骤计算,第一步各位数相加不进位,此时的结果是12(个位相加不进位是2,十位相加是1),所以结果是12; 第二步做进位,5+7有进位,进位值是10;第三步是把前两步计算结果加起来。12 + 10 = 22.

那么运用位运算二进制的数字也可以这么考虑,5是二进制的101,17是二进制的10001。试着把计算分为3步走,第一步各位相加不进位,得到的结果是10100;第二步是记下进位,根据这个例子进位计算结果是10;第三步是把前两步计算结果相加得到结果10110.转化为10进制刚好是22。 用二进制计算,第一步不考虑进位,即每一位相加 0+0=0,1+1=0,0+1=1,1+0=1。结果符合二进制数据的异或运算。第二步只考虑进位运算,0+0,0+1,1+0都不会进位,只有1+1才会进位,结果符合两个数的与运算结果然后向左移动一位。第三步,把前两步骤的结果相加,相加步骤仍然是重复前两步骤。直到不产生进位值。

第四十九题

题目描述
将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0
示例1
输入
+2147483647
1a33
输出
2147483647
0

function StrToInt(str)
{
    // write code here
    if(!str||str.length===0){
        return 0
    }
    let reg=/^(\+?\-?)(\d+)$/
    if(!str.match(reg)){
        return 0
    }
    return parseInt(str)
}

第五十题

题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

function duplicate(numbers, duplication)
{
    // write code here
    //这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    //函数返回True/False
    if(!numbers||numbers.length===0){
        return false
    }
    let len=numbers.length
    for(let i=0;i<len;i++){
        let curr=numbers[i]
        if(numbers.indexOf(curr)!==i){
            duplication[0]=curr
            return true
        }
    }
    return false
}

第五十一题

题目描述
给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。

function multiply(array)
{
    // write code here
    if(!array||array.length===0){
        return []
    }
    let result=[]
    for(let i=0;i<array.length;i++){
        let tempArr=array.filter((item,index)=>{
            return index!==i    
         })
        let temp=1
        tempArr.map(item=>temp*=item)
        result[i]=temp
    }
    
    return result
}

数组过滤

第五十二题

题目描述
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配

//s, pattern都是字符串
function match(s, pattern)
{
    // write code here
    if(s===""&&pattern===""){
        return true
    }
    if(!pattern||pattern.length===0){
        return false
    }
    let reg=new RegExp('^'+pattern+'$')
    return reg.test(s)
}

第五十三题

题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

//s字符串
function isNumeric(s)
{
    // write code here
    let reg=/^[+-]?(?:(\d+)(\.\d+)?|(\.\d+))([eE][+-]?\d+)?$/
    return reg.test(s)
}

正则表达式

第五十四题

题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。

//Init module if you need
let map
function Init()
{
    // write code here
    map={}
}
//Insert one char from stringstream
function Insert(ch)
{
    // write code here
    if(!map[ch]){
        map[ch]=1
    }else{
        map[ch]++
    }
}
//return the first appearence once char in current stringstream
function FirstAppearingOnce()
{
    // write code here
    for(let ch in map){
        if(map.hasOwnProperty(ch)&&map[ch]===1){
            return ch
        }
        
    }
    return '#'
}

利用map计数的思路

第五十五题

题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

/*function ListNode(x){
    this.val = x;
    this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
    // write code here
    if(pHead==null||pHead.next==null){
        return null
    }
    let fast=pHead
    let slow=pHead
    while(slow!==null&&fast.next!==null){
             slow=slow.next
             fast=fast.next.next 
            if(slow===fast) break
    }
    let p1=slow
    let p2=pHead
    while(p1!=p2){
        p1=p1.next
        p2=p2.next
    }
    return p1
}

这道题的思路大概如下:
在这里插入图片描述
我们设:
a=入口到相遇点的距离
x=起点到入口点的距离
c=环长
此时设置两个指针,fast,slow
每次前进一个节点的路径长度Sslow=x+a+mc
每次前进两个节点的路径长度Sfast=x+a+n
c
2 Sslow = Sfast
2 * ( x + m*c + a ) = (x + n *c + a)
从而可以推导出:
x = (n - 2 * m )*c - a
= (n - 2 *m -1 )*c + c - a
起点到入口的距离等于相遇点开始,若干环长+环-入口到相遇点
此时再设置两个指针p1,p2
p1起点为pHead,p2起点为相遇点
这个两个指针相遇点为入口点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值