西瓜仔刷题集4--剑指offer(41-50题)

41.和为S的连续正数序列
【22.5.14 中等】

解题思路:类似于TCP协议的滑动窗口协议

使用left和right两个变量来代替滑动窗口的左边界和右边界。
核心while循环的条件是:只要左边界 小于 目标值的一半就要进入循环,只要不小于循环结束,说明此时已经找到完了。
定义temp变量,用来存放滑动窗口中的所有元素的和。
当temp小于target的值的时候,右边界向右扩一个。
当temp大于target的时候,左边向右一个

function FindContinuousSequence(sum)
{
let left=1;
let right=1;
let temp=0;
let res=[];
let result=[];
   
while(left<(sum/2)){
    
    //则应该增加一个值,即增大high(相当于窗口扩张,让这个窗口包含更多的值)
      while(temp<sum){
         temp=temp+right;
          res.push(right);
          right+=1;
      }
    //可以去掉一个比较小的值,即增大low的值(相当于去掉了一个最小值,窗口收缩)
      while(temp>sum){
         temp=temp-left;
          //注意这里要用shift函数,删除数组的第一个
          res.shift();
          left+=1;          
      }
    
      if(temp==sum){
          //等于了以后保留临时结果,
          result.push([...res]);
          temp=temp-left;
          res.shift();
          left+=1;             
      }
    
    
}
    return result;
}

;
42.和为s的字符串:输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S
【22.5.24 简单】

注意一下break在哪个分支

function FindNumbersWithSum(array, sum)
{
    // write code here
    if(array.length<2) return [];
    const res=[];
    let left=0;let right=array.length-1;
    while(left<right){
        if(array[left] + array[right]< sum)
            left++;
        else if(array[left] + array[right] >sum)
            right--;
        else 
        {res.push(array[left],array[right]);
                    break;
        }
    }
        return res;

}

43.左旋转字符串
【22.5.24 简单】

以循环方式来移位即为位元循环(Bitwise Rotation)。
tips: 当循环移动次数超过数组长度时,从数的一端移出的位立即复制到该数的另一端。
在这里插入图片描述
这里:aab每次左边移出去后,都会从右边再补回来

function LeftRotateString(str, n) {
  if (str === null || str.length === 0) return '';
  n = n % str.length;
  //这里return 返回的第一部分是:str.slice(n)表示从n开始后的字符串,
  //表示字符串没有被移出去的位置
  //这里return 返回的第二部分是:str.slice(0, n)表示从n开始后的字符串,
  //表示字符串没有被移出去的位置
  return str.slice(n) + str.slice(0, n);
}

44.单词翻转序列
【22.5.24 简单】

例如,“nowcoder. a am I”。将正确的句子应该是“I am a nowcoder.”。

function ReverseSentence(str) {
  return str
    .split(' ')//将句子拆分成数组
    .reverse()//数组翻转
    .join(' ');//把数组拼接成英文句子
}

45.单词翻转序列
【22.5.25 中等】

“红心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的运气如何。为了方便起见,你可以认为大小王是0。
解题思路:
1.最大和最小之差不超过5。
2.这5个数当中不能有重复的数字。
3.遇到0跳过判断
4. 利用了位运算的技巧来判断是否有数字重复,值得记下来

var isStraight = function(nums) {
    /* 
       分治思想 五张牌构成顺子的充分条件需要满足
       1. 不重复 使用Set去重
       2. max - min < 5 最大牌值 减去 最小牌值 小于5 且跳过大小王
    */
function IsContinuous(numbers)
{
    // write code here
    const set=new Set();
    let min=14,max=0;
    
    for (const num of numbers){
    //去重
    if(set.has(num)) return false;
    //遇到0,跳过
    if(!num) continue;
    //更新set
     set.add(num);

    min=Math.min(num,min);
    max=Math.max(num,max);

    }
        //最大最小值只差小于5
    if(max-min>=5) return false;
    return true;
}

46. 孩子们的游戏:年六一儿童节,牛客都会准备一些小礼物和小游戏去看望孤儿院的孩子们。其中,有个游戏是这样的:首先,让 n 个小朋友们围成一个大圈,小朋友们的编号是0~n-1。然后,随机指定一个数 m ,让编号为0的小朋友开始报数。每次喊到 m-1 的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0… m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客礼品,请你试着想下,哪个小朋友会得到这份礼品呢?
【 22.5.30 中等】

解题思路一:按照题意来写
1:原本每个人的状态都是1 哪个人出局 就把那一个人的状态置0 然后计算的时候首先进行判断 是1的人才能进入循环
2:循环的结束条件是,当出局的人数等于n-1的时候
3:最后一个人怎么找出 循环结束之后找出flag为1的那个人的标号即可
算法流程:
判断flag为1的人进入下一次循环;
当count达到m时,出圈人数加1;并把下一位置0让他出圈;
计数器清零,进入下一波循环;

function LastRemaining_Solution(n, m)
{
   if(n < 1 || m < 1){
        return -1;
    }
    //计数器
    // write code here
    var flag=[];
    var Count=0;//Count计数出局人数
    var count=0;//一个循环中报数了几个人
    for(var i=0;i<n;i++){
        flag[i] = 1
    }
  
    //人数是否为n-1,判断只剩最后一个小孩
    while(Count<n-1){
  
    for(let i=0;i<n;i++){  
     //判断flag不为0的进入循环
        if(flag[i]){        
             count++; 
    //count等于m表示一次循环完成,有一人出局,下一次循环开始
            if(count==m){
                Count++;
                flag[i]=0;
                count=0; } 
          }      
        }
        
    }
    
      for(var i=0;i<n;i++){
        if(flag[i]==1) return i;
    }
}

解题思路二:约瑟夫环问题,利用公式推导

47. 孩子们的游戏
【22.5.26 中等】

解题思路:
一,利用短路 && 来实现 if的功能;
当n–等于0的时候
二,利用递归来实现循环while的功能;

function SumSolution(n) {
  return n && Sum_Solution(n - 1) + n;
}

48. 不用加减乘除做加法
【 5.26 中等】

解题思路:考虑用位运算符去实现三个步骤

1.怎么用位运算符实现各个位分别相加,而不用加法呢?17(10001)、5(00101),我们可以发现要对各个位进行相加,其实就是175=(10100)(10=1,11=0,00=0,正好不算进位)
2.找出进位的数字。17(10001)、5(00101),我们要找到进位的数字,可以发现只有1+1的时候才会产生进位,我们可以模拟成是两个数先安位与,在向左移动1位
3.第三步,将前两步相加。相加依旧是重复前两步,直到其中的一个数为0,也就是不在产生进位了,那么他们两个的和值就等于另外一个数字`

function Add(num1, num2) {
  while (num2 !== 0) {
    const tmp1 = num1 ^ num2;//或:各位相加
    num2 = (num1 & num2) << 1;//与:找出需要进位的地方
    num1 = tmp1;//不断迭代
  }
  return num1;
}

49把字符串转化为整数
【22.5.27 中等 掌握正则表达式】

function StrToInt (str) {
    // 首先去除字符串两侧空格
    str = str.trim();
    // 使用正则表达式匹配出数字部分
    let num = str.match(/^[+-]?\d+/);
    if (!num) {
        return 0;
    } else {
    //js中:num数组的第一个数值就是结果
        num = num[0];
    }
    // 确定数值范围的最大值和最小值
    const min = - (2 ** 31);
    const max = (2 ** 31) - 1;
    // 判断num是否超出数值范围
    return num < min ? min : num > max ? max : num;
};

50. 数据中的重复数字
【22.5.30 】 简单

解题思路:新建一个map,用map存储numbers对应数据的次数,为空就存为1,若不为空说明已经出现过一次,返回即可

function duplicate(numbers) {
    // 注意:新建一个map用{}
    const map={};
    for(let i=0;i<numbers.length;i++){
    //为空的话置为1
        if(!map[numbers[i]])
        {map[numbers[i]]=1;}
        else
        {return numbers[i];}
    }
    return -1;
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值