剑指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。
思路:
- str.length == 1;输出 [ str ]
- 循环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
}