剑指offer(持续更新)

数组

1380. 矩阵中的幸运数

给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。

幸运数是指矩阵中满足同时下列两个条件的元素:

在同一行的所有元素中最小
在同一列的所有元素中最大

var luckyNumbers  = function(matrix) {
    var minarr = []
    var maxarr = []
    matrix.map((item,index)=>{
        minarr.push(Math.min(...item))
        if(index === 0){
            maxarr.push(...item);
        }else{
            item.map((i,j) =>{
                if(i>maxarr[j]){
                    maxarr[j] = i
                }
            })
        }
        
    })
    var  res = minarr.filter( function (v){  return  maxarr.indexOf(v) > -1 })
    return res
};

查找

整数中1出现的次数

求出1~ 13的整数中1出现的次数,并算出100~ 1300的整数中1出现的次数?为此他特别数了一下1~ 13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

function NumberOf1Between1AndN_Solution(n){
	let count = 0;
	for (let i = 0; i <= n; i++) {
		i.toString().split('').forEach((item)=>{
            if (item == 1) {
                count++;
            }
		})
	};
	return count;
}

旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

function minNumberInRotateArray(rotateArray)
{let len = rotateArray.length;
 if(len == 0){return 0;}
 else{
     var low = 0;
     for(let i = 1;i < len; i++){
         if(rotateArray[i]<rotateArray[low]){
             low = i
         }
     }
     return rotateArray[low]
 } 
}

Math.min.apply(null,rotateArray);
apply第一个参数给了一个null,是因为没有对象去调用这个方法,只需要用这个方法计算得到结果,所以直接传递了一个null过去
详情参看:https://blog.csdn.net/qq_27954643/article/details/88861827

二维数组中查找

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

function Find(target, array){
    var len  = array.length;
    for(var i = 0;i< len; i++){
        for(var j = 0;j<len; j++){
            if(array[i][j] == target){
                return true;
            }
        }
    }
}

数组有序,从左下角开始,
上面的比他小,右侧的比它大;或者从右上角开始

    let row = 0,
        col = array[0].length -1;
    while(row < array.length && col >= 0){
        if(target > array[row][col]){
            row += 1;
        }else if(target < array[row][col]){
            col -= 1;
        }else{
            return true;
        }
    }
    return false;

排序

数据流中位数

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

var arr = [];
function Insert(num)
{
    arr.push(num);
    arr.sort();
    return arr;
}
function GetMedian(){
    var len = arr.length;
    let mid = Math.floor(len/2);
    if(len%2 == 0){ 
        return (arr[mid]+arr[mid-1])/2;
    }
    else{
        return arr[mid];
    }
}

递归

字符串全排

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
思路:

  1. str.length == 1;输出 [ str ]
  2. 循环str,取出目标字符串放首字符firstNumber,以及剩余字符remainNumber。
    ①. 对剩余字符递归循环得到remainSort
    ② 拼接:首字符+剩余字符的可能排序结果
    3.数组去重
function Permutation(str){
    var res = [];
    if(str.length == 1){
        return [str];
    }
    else{
        for(let i =0; i < str.length; i++){
            var firstNumber = str[i];
            var remainNumber = str.slice(0,i)+str.slice(i+1,str.length);
            var remainSort = Permutation(remainNumber);
            for(let j = 0; j<remainSort.length; j++){
                var tmp = firstNumber + remainSort[j];
                res.push(tmp);
            }   
        }
    }
    return Array.from(new Set(res));
}

矩形覆盖、跳台阶

请问用n个21的小矩形无重叠地覆盖一个2n的大矩形,总共有多少种方法?
在这里插入图片描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

思路:实际上是属于斐波那契数列:后一位等于前两位之和。

function rectCover(number){
    if (number<0){
        return -1;
    }else if(number <=2){
        return number
    }
    var arr = [];
    arr[0] = 1;
    arr[1] = 2;
    for(var i = 2; i < number; i++) {
        arr[i] = arr[i - 1] + arr[i - 2];
    }
    return arr[number-1];
}

贪心

剪绳子

给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

思路:
4 : 2*2

5 : 2*3

6 : 3*3

7 : 2* 2* 3 或者 4*3

8 : 2* 3* 3

9 : 3* 3* 3

10:2* 2* 3* 3 或者 4* 3* 3

11:2* 3* 3* 3

12:3* 3* 3* 3

13:2* 2* 3* 3* 3 或者4* 3* 3* 3
只有2和3,2的个数只有1或2,根据余数判断2的个数
时间复杂度:O(log n)

function cutRope(number){
    if(number===2) return 1;
    if(number===3) return 2;
    let a=Math.floor(number/3),b=number%3;
    switch(b){
        case 0:return Math.pow(3,a);
        case 1:return Math.pow(3,a-1)*4;
        case 2:return Math.pow(3,a)*2;   
    }
}

变态跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法?

function jumpFloorII(number){
    return Math.pow(2, number-1);
}

穷举

丑数

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

function GetUglyNumber_Solution(index)
{
    if(index == 0){
        return 0;
    }
    let index2 = 0,index3 = 0,index5 = 0;
    let res  = []
    res[0] = 1;
    for(let i=1;i<index;i++){
        res[i] = Math.min(res[index2]*2,res[index3]*3,res[index5]*5);
        if(res[i] === res[index2]*2)index2++;
        if(res[i] === res[index3]*3)index3++;
        if(res[i] === res[index5]*5)index5++;  
    }
    return res[index-1];        
}

和为s的连续正序列

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!

输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

function FindContinuousSequence(sum)
{
    if(sum === 1) return [];
    var k = Math.ceil(sum/2);
    var temp = [];
    var res = [];
    var sumNumber = 0;
    var count = 0;
    for (let i = 1; i <= k;i++){
        while (sumNumber<=sum) {
            sumNumber += (i+count);
            temp.push(i+count);
            count++;
            if (sumNumber === sum){
                res.push([...temp]);
            }
        }
        temp = [];
        sumNumber = 0;
        count=0;
        continue
    }
    return res;
}
function FindContinuousSequence(sum)
{
    if(sum === 1) return [];
    var k = Math.ceil(sum/2);
    var temp = [];
    var res = [];
    var sumNumber = 0;
    for (let i = 1; i <= k;i++){
        for (let j = i; j <= k;j++){
            sumNumber += j;
            temp.push(j);
            if (sumNumber === sum){
                res.push([...temp]);
                temp = [];
                sumNumber = 0;
                break
            } else if (sumNumber >sum){
                temp = [];
                sumNumber = 0;
                break
            }
        }
    }
    return res;
}

高级算法

最小k个数

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。

function GetLeastNumbers_Solution(input, k)
{    
    if (k>input.length)return [];
    var sortInput = input.sort();
    var out = []
    for (var i = 0;i < k;i++){
        out.push(input[i]);
    }
    return out;
}

数学

二进制中1的个数

输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。

function NumberOf1(n)
{
    if (n===0) return 0;
    var count = 0;
    for (let i=0;i<32;i++){
        if ((n>>i & 1) ===1){  //右移并与1进行&运算
            count++;
        }
    }
    return count;
}

数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

保证base和exponent不同时为0

function Power(base, exponent)
{
    if(base ===0 && exponent === 0){
        return false;
    }
        return Math.pow(base, exponent); 
}

1+2+3+…+n

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

function Sum_Solution(n)
{
    var sum = n;
    n && (sum += Sum_Solution(n-1))
    return sum;
}

不用加钱乘除的加法

function Add(num1, num2)
{
    var res,front;
    while(num2){        // 进位不为0则继续执行加法处理进位
        res = num1 ^ num2;        //不进位加法
        num2 = (num1 & num2) << 1;    //进位
        num1 = res;
    }
    return num1;
}

字符串转整数

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

function StrToInt(str)
{
    return Number(str) ? parseInt(str) : 0
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值