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;
}