剑指offer前端基础刷题
1、题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是第一个重复的数字2。没有重复的数字返回-1。
示例1
输入:[2,3,1,0,2,5,3],输出:2
class Solution:
def duplicate(self , numbers ):
temp = {}
for item in numbers:
if item not in temp.keys():
temp[item]=1
else:
return item
if len(temp.keys()) == len(numbers):
return -1
2、大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
n\leq 39n≤39
示例1
输入:4,输出:3
function
Fibonacci(n)
{
// write code here
if (n <= 1){return n}
var n1 = 0;
var n2 = 1;
var res = 0;
for (var i=2; i <= n; i++){
res = n1 + n2;
n1 = n2;
n2 = res;
}
return res;
}
module.exports = {
Fibonacci: Fibonacci
};
3、数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
示例1
输入:[1,2,3,2,2,2,5,4,2] ,返回值:2
import math
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
temp = {}
for item in numbers:
if item not in temp.keys():
temp[item] = 1
else:
tep = temp[item]
temp[item] = tep + 1
for key, value in temp.items():
if value > math.ceil(len(numbers) / 2):
return key
return 0
4、统计一个数字在升序数组中出现的次数。
示例1
输入:[1,2,3,3,3,3,4,5],3 输出:4
class Solution:
def GetNumberOfK(self, data, k):
temp = {}
for item in data:
if item not in temp.keys():
temp[item] = 1
else:
tep = temp[item]
temp[item] = tep + 1
if k not in temp.keys():
return 0
return temp[k]
5、写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
示例1
输入:1,2 ,输出:3
function Add(num1, num2)
{
// write code here
var temp;
while(num2 !=0){
temp = (num1&num2)<<1;
num1 = num1^num2;
num2 = temp;
}
return num1;
}
module.exports = {
Add : Add
};
6、用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
import Java.util.Stack;
pubilc class Solution{
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(node){
stack1.push(node);
}
public void pop(){
if(stack1.empty()&&stack2.empty()){
throw new RuntimeException();
}
while(!stack1.empty()){
stack2.push(stack1.pop());
}
return stack2.pop();
}
7、题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
示例1
输入[3,4,5,1,2] 返回值 1
function minNumberInRotateArray(rotateArray)
{
// write code here
if(rotateArray.length == 0){
return 0;
}
for (var i = 0;i<rotateArray.length;i++){
if(rotateArray[i]>rotateArray[i+1]){
return rotateArray[i+1];
}
}
return 0;
}
module.exports = {
minNumberInRotateArray : minNumberInRotateArray
};
二分查找:链接:https://www.nowcoder.com/questionTerminal/9f3231a991af4f55b95579b44b7a01ba
来源:牛客网
public static int minNumberInRotateArray(int[] array) {
if (array.length == 0)
return 0;
int left = 0;
int right = array.length - 1;
int middle = -1;
while (array[left]>=array[right]) {
if(right-left==1){
middle = right;
break;
}
middle = left + (right - left) / 2;
if (array[middle] >= array[left]) {
left = middle;
}
if (array[middle] <= array[right]) {
right = middle;
}
}
return array[middle];
}
8、题目描述
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
示例1
输入:“google”, 输出:4
class Solution:
def FirstNotRepeatingChar(self, s):
temp = {}
for item in s:
if item not in temp.keys():
temp[item] = 1
else:
count = temp[item]
temp[item] = count + 1
for index, value in enumerate(s):
if temp[value] == 1:
return index
return -1
9、题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
示例1
输入:3,返回值:4
function jumpFloorII(number){
if (number <= 0{
return -1;
} else if (number == 1){
return 1;
} else {
return 2 * jumpFloorII(number - 1);
}
}
module.exports = {
jumpFloorII: jumpFloorII
};
10、输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
示例1
输入:{1,3,5},{2,4,6},返回值:{1,2,3,4,5,6}
function ListNode(x){
this.val = x;
this.next = null;}
function Merge(pHead1, pHead2)
{
// write code here
if (pHead1 == null){ return pHead2;}
if (pHead2 == null){ return pHead1;}
var pHead = new ListNode(-1);
if(pHead1.val <= pHead2.val){
pHead = pHead1;
pHead.next = Merge(pHead1.next,pHead2);
}else{
pHead = pHead2;
pHead.next = Merge(pHead1,pHead2.next);
}
return pHead;
}
module.exports = {
Merge : Merge
};
11、操作给定的二叉树,将其变换为源二叉树的镜像。
比如: 源二叉树
8
/
6 10
/ \ /
5 7 9 11
镜像二叉树
8
/
10 6
/ \ /
11 9 7 5
示例1
输入 {8,6,10,5,7,9,11}
返回值 {8,10,6,11,9,7,5}
function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
}
function Mirror( pRoot ) {
// write code here
if (pRoot == null){
return;
}
var tempRoot = pRoot.right;
pRoot.right = pRoot.left;
pRoot.left = tempRoot;
Mirror(pRoot.left);
Mirror(pRoot.right);
return pRoot;
}
module.exports = {
Mirror : Mirror
};
12、题目描述
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n).
示例1
输入:[1,-2,3,10,-4,7,2,-5],返回值:18
function FindGreatestSumOfSubArray(array){
// write code here
var max = array[0];
var len = array.length;
var dp = new Array(len);
dp[0] = array[0];
for (var i = 1;i < array.length; i++){
var newMax = dp[i-1]+array[i];
if (newMax > array[i]){
dp[i] = newMax;
}else{
dp[i] = array[i];
}
if (dp[i] > max){max = dp[i];}
}
return max;
}
module.exports = {
FindGreatestSumOfSubArray : FindGreatestSumOfSubArray
};
13、题目描述
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
示例1
输入:{1,2,3,4,5,#,6,#,#,7},返回值:4
function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
}
function TreeDepth(pRoot)
{
// write code here
if (pRoot == null){return null;}
var leftHight = TreeDepth(pRoot.left);
var rightHight = TreeDepth(pRoot.right);
var hight = 1 + (leftHight>rightHight ? leftHight :rightHight);
return hight;
}
module.exports = {
TreeDepth : TreeDepth
};
14、输入一棵二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
示例1
输入:{1,2,3,4,5,6,7},返回值:true
function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
}
function high(pRoot){
if(pRoot==null){return 0;}
return Math.max(high(pRoot.left),high(pRoot.right)) + 1;
}
function IsBalanced_Solution(pRoot)
{
// write code here
return !pRoot ? true : Math.abs(high(pRoot.right) - high(pRoot.left)) <= 1 && IsBalanced_Solution(pRoot.right) && IsBalanced_Solution(pRoot.left);
}
module.exports = {
IsBalanced_Solution : IsBalanced_Solution
};
查找两个节点的最近的一个共同父节点,可以包括节点自身
输入描述:
oNode1 和 oNode2 在同一文档中,且不会为相同的节点
function commonParentNode(oNode1, oNode2) {
for(;oNode1;oNode1=oNode1.parentNode){
if(oNode1.contains(oNode2)){
return oNode1;
}
}
}
根据包名,在指定空间中创建对象
function namespace(oNamespace, sPackage) {
var res = oNamespace;
var obj = sPackage.split('.');
for (let i = 0;i<obj.length;i++){
if (obj[i] in oNamespace){
if (typeof oNamespace [obj[i]] !== 'object'){
oNamespace[obj[i]] = {}
}else{
oNamespace = oNamespace[obj[i]];
}
}else{
oNamespace[obj[i]] = {}
oNamespace = oNamespace[obj[i]];
}
}
return res;
}
为 Array 对象添加一个去除重复项的方法
Array.prototype.uniq = function () {
return Array.from(new Set(this));
}
用 JavaScript 实现斐波那契数列函数,返回第n个斐波那契数。 f(1) = 1, f(2) = 1 等
fu
nction fibonacci(n) {
var fn1 = 1;
var fn2 = 1;
var fn = 0;
for (let i = 2;i<n;i++){
fn = fn1 + fn2;
fn1 = fn2;
fn2 = fn;
}
return fn;}
找出数组 arr 中重复出现过的元素
示例1 输入 [1, 2, 4, 4, 3, 3, 1, 5, 3] 输出 [1, 3, 4]
function duplicates(arr) {
var arr1 = arr.filter(function(value,index){
return arr.indexOf(value) !== index;
})
return Array.from(new Set(arr1));}
统计数组 arr 中值等于 item 的元素出现的次数
输入 [1, 2, 4, 4, 3, 4, 3], 4
输出 3
function count(arr, item) {
var count = 0;
var index = arr.indexOf(item);
while(index != -1){
count++;
index = arr.indexOf(item,index+1);
}
return count;}
按所给的时间格式输出指定的时间
格式说明
对于 2014.09.05 13:14:20
yyyy: 年份,2014
yy: 年份,14
MM: 月份,补满两位,09
M: 月份, 9
dd: 日期,补满两位,05
d: 日期, 5
HH: 24制小时,补满两位,13
H: 24制小时,13
hh: 12制小时,补满两位,01
h: 12制小时,1
mm: 分钟,补满两位,14
m: 分钟,14
ss: 秒,补满两位,20
s: 秒,20
w: 星期,为 [‘日’, ‘一’, ‘二’, ‘三’, ‘四’, ‘五’, ‘六’] 中的某一个,本 demo 结果为 五
示例1
输入 formatDate(new Date(1409894060000), ‘yyyy-MM-dd HH:mm:ss 星期w’)
输出 2014-09-05 13:14:20 星期五
function formatDate(dt,rule){
var obj = {
yyyy:dt.getFullYear(),
yy:('' + dt.getFullYear()).slice(-2),
MM:('0' + (dt.getMonth() + 1)).slice(-2),
M:dt.getMonth() + 1,
dd:('0' + dt.getDate()).slice(-2),
d:dt.getDate(),
HH:('0' + dt.getHours()).slice(-2),
H:dt.getHours(),
hh:('0' + dt.getHours()%12).slice(-2),
h:dt.getHours()%12,
mm:('0' + dt.getMinutes()).slice(-2),
m:dt.getMinutes(),
ss:('0' + dt.getSeconds()).slice(-2),
s:dt.getSeconds(),
w:['日', '一', '二', '三', '四', '五', '六'][dt.getDay()]
}
return rule.replace(/([a-z]+)/ig,function(key){
return obj[key];
})
}
// return rule.replace(/([a-z]+)/ig,function($1){return obj[$1]});
console.log(formatDate(new Date(1409894060000), 'yyyy-MM-dd HH:mm:ss 星期w'))
实现一个打点计时器,要求
1、从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
2、返回的对象中需要包含一个 cancel 方法,用于停止定时操作
3、第一个数需要立即输出
function count(start, end) {
console.log(start)
var timer = setInterval(function(){
if(start<end){
console.log(start+=1);
}
},100)
return {cancel:function(){clearInterval(timer)}};
}
题目描述
将数组 arr 中的元素作为调用函数 fn 的参数
示例1
输入 function (greeting, name, punctuation) {return greeting + ', ’ + name + (punctuation || ‘!’);}, [‘Hello’, ‘Ellie’, ‘!’]
输出 Hello, Ellie!
function argsAsArray(fn, arr) {
return fn.apply(this,arr);}
实现函数 function,调用之后满足如下条件:
1、返回值为一个函数 f
2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ', ’
3、所有函数的参数数量为 1,且均为 String 类型
示例1
输入functionFunction(‘Hello’)(‘world’)
输出 Hello, world
// 用闭包解决
function functionFunction(str){
var f = function(str1){
return str + ', ' + str1;
}
return f;}
如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1
否则如果字符 Unicode 编码 > 255 则长度为 2
示例1 输入’hello world, 牛客’, false 输出17
function strLength(s, bUnicode255For1) {
if(s.length === 0){return 0;}
if (bUnicode255For1 === true){
return s.length;
}else{
// var len = 0;
var arr = s.split('').map(function(value,index){
return s.charCodeAt(index)>255 ? 2:1;
})
return arr.reduce(function(pre,cur){
console.log(pre);
return pre+cur;
})
}
}
实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 resulti,结果与 fn(arr[i]) 相同
示例1
输入[1, 2, 3], function (x) {
return x * x;
}
输出 4
function makeClosures(arr, fn) {
return arr.map(value =>{
return function(){
return fn(value);
}
})
}
已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件:
1、返回一个函数 result,该函数接受一个参数
2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致
function partial(fn, str1, str2) {
return function(str3){
return fn(str1,str2,str3);
}
}
实现函数 callIt,调用之后满足如下条件
1、返回的结果为调用 fn 之后的结果
2、fn 的调用参数为 callIt 的第一个参数之后的全部参数
function callIt(fn) {
var arr = [].slice.call(arguments, 1)
return fn.apply(this,arr)
}
实现函数 partialUsingArguments,调用之后满足如下条件:
1、返回一个函数 result
2、调用 result 之后,返回的结果与调用函数 fn 的结果一致
3、fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数
function partialUsingArguments(fn) {
var arr = [].slice.call(arguments,1);
function result(){
var arrFromResult = [].slice.call(arguments)
return fn.apply(null,arr.concat(arrFromResult));
}
return result;
}
计算给定数组 arr 中所有元素的总和
输入描述:数组中的元素均为 Number 类型
示例1 输入 [ 1, 2, 3, 4 ] 输出 10
function sum(arr) {
return arr.reduce(function(pre,cur){
return pre + cur;
})}
判断输入是否是正确的邮箱格式
输入描述:邮箱字符串输出描述:true表示格式正确
function isAvailableEmail(sEmail) {
if(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(sEmail)){
return true;
}else return false;}
移除数组 arr 中的所有值与 item 相等的元素。不要直接修改数组 arr,结果返回新的数组
示例1 输入[1, 2, 3, 4, 2], 2 输出[1, 3, 4]
function remove(arr, item) {
return arr.filter(function(value,index){
return value !== item;
})}
题目描述
将 rgb 颜色字符串转换为十六进制的形式,如 rgb(255, 255, 255) 转为 #ffffff
- rgb 中每个 , 后面的空格数量不固定
- 十六进制表达式使用六位小写字母
- 如果输入不符合 rgb 格式,返回原始输入
示例1 输入 ‘rgb(255, 255, 255)’ 输出 #ffffff
function rgb2hex(sRGB) {
var reg = new RegExp(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
if (reg.test(sRGB)){
var num = sRGB.slice(4,-1).split(',');
var res = '#';
for (let i =0;i<num.length;i++){
if(num[i]>=0&&num[i]<=255){
res += ('0'+parseInt(num[i]).toString(16)).slice(-2);
}else return sRGB;
}
return res;
}else{
return sRGB;
}}
统计字符串中每个字符的出现频率,返回一个 Object,key 为统计字符,value 为出现频率
- 不限制 key 的顺序
- 输入的字符串参数不会为空
- 忽略空白字符
输入’hello world’ 输出{h: 1, e: 1, l: 3, o: 2, w: 1, r: 1, d: 1}
function count(str) {
var obj = {};
for (let i = 0;i<str.length;i++){
if (str.charAt(i)!= ''){
if(obj[str.charAt(i)]){obj[str.charAt(i)] += 1}
else{obj[str.charAt(i)] = 1}
}
}
return obj;}
使用一个标签将“牛客网”三个字加粗显示
var p = document.querySelector('p')
var t = p.innerHTML;
var str = t.replace('牛客网','<strong>牛客网</strong>');
p.innerHTML = str;
移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回
示例1 输入 [1, 2, 2, 3, 4, 2, 2], 2 输出[1, 3, 4]
function removeWithoutCopy(arr, item) {
for (let i = 0;i<arr.length;i++){
if(arr[i]===item){
arr.splice(i,1)
i--;
}
}
return arr;}
css 中经常有类似 background-image 这种通过 - 连接的字符,通过 javascript 设置样式的时候需要将这种样式转换成 backgroundImage 驼峰格式,请完成此转换功能
- 以 - 为分隔符,将第二个起的非空单词首字母转为大写
- -webkit-border-image 转换后的结果为 webkitBorderImage
function cssStyle2DomStyle(sName) {
var arr = sName.split('-');
if (arr[0]===''){arr.splice(0,1);}
return arr.map(function(value,index){
if (index == 0){
return value;
}else{
return value.replace(value.charAt(0),value.charAt(0).toUpperCase());
}
}).join('') }
给定字符串 str,检查其是否符合美元书写格式
1、以 $ 开始
2、整数部分,从个位起,满 3 个数字用 , 分隔
3、如果为小数,则小数部分长度为 2
4、正确的格式如:$1,023,032.03 或者 $2.03,错误的格式如:$3,432,12.12 或者 $34,344.3
示例1 输入 ‘$20,933,209.93’ 输出 true
function isUSD(str) {
return /^\$\d{1,3}(,\d{3})*(\.\d{2})?$/.test(str);
}
function trans(str){
var obj = {
'亿':100000000,
'千万':10000000,
'百万':1000000,
'十万':100000,
'万':10000,
'千':1000,
'百':100,
'十':10,
'九':9,
'八':8,
'七':7,
'六':6,
'五':5,
'四':4,
'三':3,
'二':2,
'一':1,
}
var arr = str.split('');
console.log(arr)
res = 0;
for (let i = 0;i<arr.length;i=i+2){
console.log(obj[arr[i]],obj[arr[i+1]])
if(arr[i+1]){
res += obj[arr[i]]*obj[arr[i+1]];
}else{
res += obj[arr[i]];
}
}
console.log(res)
return (res)
}
console.log(trans('一千三'))
var s = '1+3+5+8444*9-7'
小Q定义了一种数列称为翻转数列:
给定整数n和m, 满足n能被2m整除。对于一串连续递增整数数列1, 2, 3, 4…, 每隔m个符号翻转一次, 最初符号为’-’;。
例如n = 8, m = 2, 数列就是: -1, -2, +3, +4, -5, -6, +7, +8.而n = 4, m = 1, 数列就是: -1, +2, -3, + 4.
小Q现在希望你能帮他算算前n项和为多少。
输入描述:
输入包括两个整数n和m(2 <= n <= 109, 1 <= m), 并且满足n能被2m整除。
输出描述:输出一个整数, 表示前n项和。
示例1:输入:8 2,输出:8
var n = 4;
var m = 1;
var arr = [-1,-2,3,4];
console.log(m*n/2);
牛牛和羊羊正在玩一个纸牌游戏。这个游戏一共有n张纸牌, 第i张纸牌上写着数字ai。
牛牛和羊羊轮流抽牌, 牛牛先抽, 每次抽牌他们可以从纸牌堆中任意选择一张抽出, 直到纸牌被抽完。
他们的得分等于他们抽到的纸牌数字总和。
现在假设牛牛和羊羊都采用最优策略, 请你计算出游戏结束后牛牛得分减去羊羊得分等于多少。
输入描述:
输入包括两行。
第一行包括一个正整数n(1 <= n <= 105),表示纸牌的数量。
第二行包括n个正整数ai(1 <= ai <= 109),表示每张纸牌上的数字。
输出描述:
输出一个整数, 表示游戏结束后牛牛得分减去羊羊得分等于多少。
输入例子1:
3
2 7 4
输出例子1:
5
var arr = [1,2,3,4,8,6,0]
var newArr = arr.sort();
var eve = 0;
var odd = 0;
console.log(newArr);
for(let i = 0;i<newArr.length;i++){
if (i%2 == 0){
eve += newArr[i];
}
else{
odd += newArr[i];
}
}
console.log(eve-odd);
封装函数 f,使 f 的 this 指向指定的对象
function bindThis(f, oTarget) {
return function(...arguments){
return f.apply(oTarget,arguments);
}
}
function bindThis(f, oTarget) {
return function(x,y){
return f.call(oTarget,x,y);
}
}
获取 url 中的参数
- 指定参数名称,返回该参数的值 或者 空字符串
- 不指定参数名称,返回全部的参数对象 或者 {}
- 如果存在多个同名参数,则返回数组
示例1 输入 http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe key; 输出 [1, 2, 3]
function getUrlParam(sUrl, sKey) {
var index = sUrl.indexOf('?');
if (index === -1){
if (sKey == ''){
return {};
}else{
return "";
}
}
var res = {};
var queryString = sUrl.split('?')[1].split('#')[0];
var queryArr = queryString.split('&');
for (var i = 0;i< queryArr.length;i++ ){
var key = queryArr[i].split('=')[0];
var value = queryArr[i].split('=')[1];
if (res[key]){
temp = []
temp.push(...res[key],value)
res[key] = temp
}else{
res[key] = value;
}
}
if (sKey){
return res[sKey]?res[sKey]:'';
}else{
return res;
}
}