java 一组数列找出单个数_前端面试中常遇到的算法题及考察点

【灵活应对前端面试中的JS算法题】

实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制

function clone(obj){

var result;

switch(typeof obj){

case 'undefined':

break;

case 'string':

result = obj+'';

break;

case 'number':

result = obj-0;

break;

case 'boolean':

result =obj;

break;

case 'object':

if(obj ===null){

result = null;

} else {

if(Object.prototype.toString.call(obj).slice(8,-1)==='Array'){

result=[];

for(var i=0;i

result.push(clone(obj[i]));

}

}else{

result=[];

for(var k in obj){

result[k]=clone(obj[k]);

}

}

};

break;

default:

result = obj;

break;

}

return result

}

判断一个单词是否是回文

回文是指把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。

很多人拿到这样的题目非常容易想到用for将字符串颠倒字母顺序然后匹配就行了。其实重要的考察的是对于reverse的实现。其实我们可以利用现成的函数,将字符串转换成数组,这个思路很重要,我们可以拥有更多的自由度去进行字符串的一些操作。

let reverseStr = function(str) {

return str = str.split('').reverse().join('');

}

reverseStr('abcdefg');

//gfedcba

在句子中反转词

如fix this one 变为 one this fix。重点是检测到空格时进行处理。

function reverseWord(str){

return str.split(' ').reverse().join(' ')

}

反转每个单词中字符的顺序

“I am the good boy” 反转成这样 “I ma eht doog yob”

function reverse(str){

return str.split(' ').reverse().join(' ').split('').reverse().join('');

}

去掉一组整型数组重复的值

题目如下输入: [3,13,24,11,11,14,1,2]

输出: [3,13,24,11,14,2]

需要去掉重复的11 和 1 这两个元素。

这道题有多重方法,我理解的主要是考察个人对Object的使用,利用key来进行筛选。

function unique(arr) {

let hashTable = {};

let data = [];

for(let i=0,l=arr.length;i

if(!hashTable[arr[i]]) {

hashTable[arr[i]] = true;

data.push(arr[i]);

}

}

return data

}

unique([3,13,24,11,11,14,1,2])

//[3,13,24,11,14,2]

再来一个其他实现方式,这个方法常在我的项目中出现,用的时候确实觉得代码少了那么几行

function unique(arr) {

let data = [];

for(let i=0,l=arr.length;i

if(data.indexOf(arr[i])==-1) {

data.push(arr[i]);

}

}

return data

}

unique([3,13,24,11,11,14,1,2])

//[3,13,24,11,14,2]

统计一个字符串出现最多的字母

输入一段英文连续的英文字符串 afjghdfraaaasdenas,找出重复出现次数最多的字母

function findMaxChar(str) {

if(str.length == 1) {

return str;

}

let charObj = {};

for(let i=0;i

if(!charObj[str.charAt(i)]) {

charObj[str.charAt(i)] = 1;

}else{

charObj[str.charAt(i)] += 1;

}

}

return compare(charObj);

};

function compare(charObj){

let maxChar = '',

maxValue = 1;

for(var k in charObj) {

if(charObj[k] >= maxValue) {

maxChar = k;

maxValue = charObj[k];

}

}

return maxChar;

}

findMaxChar('afjghdfraaaasdenas')

//a

找到字符串中的第一个非重复的字符

遍历字符串,用一个对象当做hash表来存储重复字符。

function firstNonRepeatChar(str){

var count = {};

for(var i=0;i

if(count[str[i]]){

count[str[i]]++;

}else{

count[str[i]] = 1;

}

}

for(var prop in count){

if(count[prop] === 1){

return prop;

}

}

}

删除字符串中重复的字符

其实是在上一个问题的基础上再进行操作:

function firstNonRepeatChar(str){

var count = {};

var result = [];

for(var i=0;i

if(count[str[i]]){

count[str[i]]++;

}else{

count[str[i]] = 1;

}

}

for(var prop in count){

if(count[prop] === 1){

result.push(prop);

}

}

return result.join('');

}

在n和m之间生成随机整数

Math.floor(Math.random()*(m-n))+n

排序算法(冒泡排序)

冒泡排序JavaScript代码实现:

function bubbleSort(arr) {

var len = arr.length;

for (var i = 0; i < len; i++) {

for (var j = 0; j < len - 1 - i; j++) {

if (arr[j] > arr[j+1]) { //相邻元素两两对比

var temp = arr[j+1]; //元素交换

arr[j+1] = arr[j];

arr[j] = temp;

}

}

}

return arr;

}

bubbleSort([3,5,2,8,9,7,6])

//[2, 3, 5, 6, 7, 8, 9]

排序算法(选择排序)

在时间复杂度上表现最稳定的排序算法之一,因为无论什么数据进去都是O(n²)的时间复杂度。。。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。

function selectionSort(arr) {

var len = arr.length;

var minIndex, temp;

for (var i = 0; i < len - 1; i++) {

minIndex = i;

for (var j = i + 1; j < len; j++) {

if (arr[j] < arr[minIndex]) { //寻找最小的数

minIndex = j; //将最小数的索引保存

}

}

temp = arr[i];

arr[i] = arr[minIndex];

arr[minIndex] = temp;

}

return arr;

}

selectionSort([3,5,2,8,9,7,6])

//[2, 3, 5, 6, 7, 8, 9]

从未排序的整数数组中找出缺失的数字

比如你有1到100的整数,而其中缺了一个,怎么找出这个数字?利用等差数列公式计算这些数应得的和,再计算当前数组所有数字的和,二者的差即为缺少的数。

function missingNumber(arr){

var n = arr.length+1;

var expectedSum = (1+n)*n/2;

var sum = 0;

for(var i=0;i

sum+=arr[i];

}

return expectedSum - sum;

}

检查是否有任何两个数字的和是给定的数字

最暴力的方法就是两层循环,是O(n2).改进方法使用一个对象作为哈希表,用于存储数,这样在每次搜寻是否有另一个数与当前数的和为sum时就可以在O(1)的时间内找到。

function twoSum(arr,sum){

var obj = {};

var num;

for(var i=0;i

num = sum - arr[i];

if(obj[num]){

return true;

}else{

//若没有的话为当前数字建立索引

obj[arr[i]] = true;

}

}

return false;

}

检查是否有任何两个数字的和是给定的数字,有的话将数字和位置以对象的方式返回值,否则返回false

最暴力的方法就是两层循环,是O(n2).改进方法使用一个对象作为哈希表,用于存储数,这样在每次搜寻是否有另一个数与当前数的和为sum时就可以在O(1)的时间内找到。

function twoSum(arr,sum){

var obj = {};

var num;

for(var i=0;i

num = sum - arr[i];

obj[num]=arr.length+1;

if(obj[num]){

obj[arr[i]]=i;

obj[num]=arr.indexOf(num);

return obj;

}else{

//若没有的话为当前数字建立索引

obj[arr[i]] = i;

}

}

return false;

}

找到任意两个数字的最大和

找到两个最大的数并返回它们的和。

function topSum(arr){

if(arr.length<2) return null;

var first,second;

if(arr[0]>arr[1]){

first = arr[0];

second=arr[1];

}else{

first = arr[1];

second=arr[0];

}

for(var i=2;i

if(arr[i]>first){

second = first;

first = arr[i];

}else if(arr[i]>second){

second = arr[i];

}

}

return first+second;

}

从1到n中0的总个数

n=50的话,有5个0,分别是10,20,30,40,50。

n = 120的话,分别是10到90,共九个,110到120,共2个,以及100的两个,一共13个。

也就是说10的整数次方会有多个零,如100,1000,那么就要利用现有的数计算包含了多少个10的平方数。

如2014,2014/10=201; 201/10 = 20; 20/10 = 2; 最后表明出现了两次10的三次方,即1000和2000。

function countZero(n){

var count = 0;

while(n>0){

count+=Math.floor(n/10);

n/=10;

}

return count;

}

匹配字符串的子字符串

function substr(str,subStr){

for(var i=0;i

for(var j=0;j

if(str[i+j] != subStr[j]){

break;

}

}

if(j == subStr.length){

return i;

}

}

return -1;

}

字符串的全排列

var result = [];

function permutations(str){

var arr= str.split('');

helper(arr,0,[]);

return result;

}

function helper(arr,index,list){

if(index === arr.length){

result.push(list.join(''));

return;

}

for(var i = 0;i

if(list.indexOf(arr[i]) != -1){

continue;

}

list.push(arr[i]);

helper(arr,index+1,list)

list.pop();

}

}

不借助临时变量,进行两个整数的交换

把 a = 2, b = 4 变成 a = 4, b =2

这种问题非常巧妙,需要大家跳出惯有的思维,利用 a , b进行置换

主要是利用 + – 去进行运算,类似 a = a + ( b – a) 实际上等同于最后 的 a = b;

function swap(a , b) {

b = b - a;

a = a + b;

b = a - b;

console.log('a='+a);

console.log('b='+b)

}

var a=2,b=4;

swap(a,b)

//a=4;b=2

斐波那契数列(黄金分割数列)不说换金分割我也不知道是啥玩意儿啦

斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列主要考察递归的调用。

function getFibonacci(n) {

var fibarr = [];

var i = 0;

while(i

if(i<=1) {

fibarr.push(i);

}else{

fibarr.push(fibarr[i-1] + fibarr[i-2])

}

i++;

}

return fibarr;

}

getFibonacci(9); //拿到9个

//[0、1、1、2、3、5、8、13、21]

获得第n个斐波那契数字

解法一:迭代

var fibonacci = function(n){

var fibo = [0,1];

for(var i=2;i<=n;i++){

fibo[i] = fibo[i-1]+fibo[i-2];

}

return fibo[n];

}

解法二:递归

var fibonacci = function(n){

if(n>=2){

return fibonacci(n-1)+fibonacci(n-2);

}else{

return n;

}

}

找到两个数的最大公约数

解法一:遍历

var greatestCommonDivisor= function(a,b){

if(a<2 || b<2) return 1;

var divider = 2;

var greatestDivisor = 1;

while(divider<=a && divider<=b){

if(a%divider == 0 && b%divider == 0){

greatestDivisor = divider;

}

divider++;

}

return greatestDivisor;

}

解法二:辗转相除法

又名欧几里德算法(Euclidean algorithm)乃求两个正整数之最大公因子的算法。它是已知最古老的算法……

有解释的,但我选择不去理解……

function greatestCommonDivisor(a, b){

if(b == 0)

return a;

else

return greatestCommonDivisor(b, a%b);

}

合并两个排序数组

var mergeSortedArray = function(a,b){

var merge = [];

var i = 0,j = 0;

var k = 0;

while(i

if(i == a.length || (j!=b.length && a[i]>b[j])){

merge[k++] = b[j++];

}else{

merge[k++] = a[i++];

}

}

return merge;

}

验证一个数是否是质数

质数只能被1和它自己整除,因此令被除数从2开始,若能整除则不是质数,若不能整除则加一,直到被除数到达根号n,此时n则是质数。

function isPrime(n){

var divider = 2;

var limit = Math.sqrt(n);

while(divider<=limit){

if(n%divider == 0){

return false;

}

divider++;

}

return true;

}

isPrime(3);

//true

查找数字的所有质数因子

divider从2开始,如果n能整除divider,则将divider加入到结果中,n为此次计算后的商,如果n不能整除divider,则divider++

var primeFactors = function(n){

var factors = [];

var divider = 2;

while(n>2){

if(n%divider == 0){

factors.push(divider);

n /= divider;

}else{

divider++;

}

}

return factors;

}

找出正数组的最大差值比

这是通过一道题目去测试对于基本的数组的最大值和最小值的查找

function getMaxProfit(arr) {

var minPrice = arr[0];

var maxProfit = 0;

for (var i = 0; i < arr.length; i++) {

var currentPrice = arr[i];

minPrice = Math.min(minPrice, currentPrice);

var potentialProfit = currentPrice - minPrice;

maxProfit = Math.max(maxProfit, potentialProfit);

}

return maxProfit;

}

getMaxProfit([10,5,11,7,8,9])

//6

随机生成指定长度的字符串

function randomString(n) {

let str = 'abcdefghijklmnopqrstuvwxyz9876543210';

let tmp = '',

i = 0,

l = str.length;

for (i = 0; i < n; i++) {

tmp += str.charAt(Math.floor(Math.random() * l));

}

return tmp;

}

randomString(9); //指定长度为9

//4ldkfg9j7

实现类似getElementsByClassName 的功能

自己实现一个函数,查找某个DOM节点下面的包含某个class的所有DOM节点?不允许使用原生提供的 getElementsByClassName querySelectorAll 等原生提供DOM查找函数。

function queryClassName(node, name) {

var starts = '(^|[ \n\r\t\f])',

ends = '([ \n\r\t\f]|$)';

var array = [],

regex = new RegExp(starts + name + ends),

elements = node.getElementsByTagName("*"),

length = elements.length,

i = 0,

element;

while (i < length) {

element = elements[i];

if (regex.test(element.className)) {

array.push(element);

}

i += 1;

}

return array;

}

queryClassName()

使用JS 实现二叉查找树

一般叫全部写完的概率比较少,但是重点考察你对它的理解和一些基本特点的实现。 二叉查找树,也称二叉搜索树、有序二叉树(英语:ordered binary tree)是指一棵空树或者具有下列性质的二叉树:

任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 任意节点的左、右子树也分别为二叉查找树;

没有键值相等的节点。二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低。为O(log

n)。二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。

class Node {

constructor(data, left, right) {

this.data = data;

this.left = left;

this.right = right;

}

}

class BinarySearchTree {

constructor() {

this.root = null;

}

insert(data) {

let n = new Node(data, null, null);

if (!this.root) {

return this.root = n;

}

let currentNode = this.root;

let parent = null;

while (1) {

parent = currentNode;

if (data < currentNode.data) {

currentNode = currentNode.left;

if (currentNode === null) {

parent.left = n;

break;

}

} else {

currentNode = currentNode.right;

if (currentNode === null) {

parent.right = n;

break;

}

}

}

}

remove(data) {

this.root = this.removeNode(this.root, data)

}

removeNode(node, data) {

if (node == null) {

return null;

}

if (data == node.data) {

// no children node

if (node.left == null && node.right == null) {

return null;

}

if (node.left == null) {

return node.right;

}

if (node.right == null) {

return node.left;

}

let getSmallest = function(node) {

if(node.left === null && node.right == null) {

return node;

}

if(node.left != null) {

return node.left;

}

if(node.right !== null) {

return getSmallest(node.right);

}

}

let temNode = getSmallest(node.right);

node.data = temNode.data;

node.right = this.removeNode(temNode.right,temNode.data);

return node;

} else if (data < node.data) {

node.left = this.removeNode(node.left,data);

return node;

} else {

node.right = this.removeNode(node.right,data);

return node;

}

}

find(data) {

var current = this.root;

while (current != null) {

if (data == current.data) {

break;

}

if (data < current.data) {

current = current.left;

} else {

current = current.right

}

}

return current.data;

}

}

module.exports = BinarySearchTree;

统计数组中每个元素及出现的次数,并输出到页面

function getArrayMess(arr) {

if(arr.length == 1) {

console.log("{"+arr[0]+":1")

}

let charObj = {};

for(let i=0;i

if(!charObj[arr[i]]) {

charObj[arr[i]] = 1;

}else{

charObj[arr[i]] += 1;

}

}

console.log(charObj)

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值