常见的几道算法题

  最近在笔试和看面经的时候经常会碰到几道算法题目,决定记录下来和大家分享以下。

求数组的最大字段和

  比如:arr=[1,-2,3,10,-4,7,2,-5],求它的最大的和是多少,答案是18 。问题来了:那为什么最后结果是18呢?思考… …?

  一波分析:首先,sum = 1+(-2)< 0,这种情况下sum = 0 ,并且从3开始加。

  总结:遇到正数直接加上,遇到负数先判断加上当前的元素后和是不是小于0,是的话就重新计算,否则直接加上。

// 最大字段和
    function maxNumber(arr) {
        var max=0;   //保存最大值
        var sum=0;  //保存当前值
        for(let i=0;i<arr.length;i++){
            if(arr[i]>=0){   //正数的情况
                sum+=arr[i];
                max=sum>max?sum:max;   //判断,改变max值
            }else{                  //负数情况
                if(sum+arr[i]>0){
                    sum+=arr[i];
                }else{
                    sum=0;
                }
            }
        }
        return max;
    }
两个字符串的最长公共子串

  最长公共子串是指两个字符串中相同的字符串,同时还是最长的。比如:“abcdef” 和 “defg” 公共且最长是 “def”。

  过程:先找到长度最短的字符串,把短字符串的子序列枚举出来,依次到长字符串中进行判断是否存在,每次从最长的开始判断,存在就直接返回。

function MaxCommon(str1,str2) {
	if(str1.length > str2.length){
		var temp = str1;
		str1 = str2;
		str2 = temp;
	}
	let len1 = str1.length;
	let len2 = str2.length;
	for(let i=len1; i>0; i--){
		for(let j=0; j<=len1-i; j++){
			let str = str1.substr(j,i);
			if(str2.indexOf(str)>=0){
				return str;
			}
		}
	}
	return "";
}
最长递增子序列

  最长递增子序列意思是在一组数字中,找出最长一串递增的数字,比如:0, 3, 4, 17, 2, 8, 6, 10 对于以上这串数字来说,最长递增子序列就是 0, 3, 4, 8, 10

function Lengthest(nums){
	let array = Array(nums.length).fill(1);  //以1填充数组
	for(let i = 1;i<array.length;i++){
		for(let j = 0;j<i;j++){  //和之前的所有元素进行比较
			if(nums[i]>nums[j]){
				array[i] = Math.max(array[i],1+array[j]);   //取最大值
			}
		}
	}
	return Math.max(...array);  //返回长度
}
var arr = [0, 3, 4, 17, 2, 8, 6, 10];
console.log(Lengthest(arr));   //5
柯里化

  经典考题:add(1)(2)(3)(),add(1,2,3)都返回6。

  柯里化是将一个n元函数转为n个一元函数

  函数柯里化好处:1、提高参数复用性 2、延迟执行(累计传入参数,最后执行)

//先来个 add(1,2)和add(1)(2)
function add(){
	var sum=0;
	if(arguments.length ===1){
		sum = arguments[0];
		return function(y){
			return sum+=y;
		}
	}else{
		return sum=arguments[0]+arguments[1];
	}
}

  上面的只能实现两个参数的情况,当参数再增加的情况就不适用了。add(1)(2)(3)会报错 Uncaught TypeError: add(…)(…) is not a function 。所以应该封装一个都通用的函数。

function sum(...args){//这里的三个点...是扩展运算符,该运算符将一个数组,变为参数序列。
	if([...args].length==1){//判断参数个数的形式是否为1个,即第二种形式
		var cache = [...args][0];//将第一个参数的值暂存在cache中
		var add = function (y){//创建一个方法用于实现第二个条件,最后并返回这个方法
            cache += y;
			return add; 
        }
        add.toString = function () { return cache }
	    return add; 
	}else{
		var res = 0;//这里最好先声明要输出的变量,并给其赋值,不然值定义而不赋值会输出NaN,因为js将undefined+number两个数据类型相加结果为NaN
		for(var i = 0;i<[...args].length;i++){
			res += [...args][i]; //参数累加
        }
        return res;
	} 
} 
console.log(sum(2,3,4));
console.log(sum(2)(3)(4)(5));
原生js实现splice()函数

  这一题是我今天看牛客面经的时候看到的一道题,挺不错的,实习的话就需要对splice函数中的每一项参数都特别理解,之前可能对每一项参数都特别模糊,趁着现在好好复习一下。

  splice(参数一,参数二,参数三),要了解的是该函数会改变原数组。。。

  参数一:如果只有该参数,则删除从该值后的所有元素,splice返回的是被删除的元素

  参数二:如果为0,不操作数组,返回空数组,否则表示删除数组的长度

  参数三:表示要插入的值。

  // 实现splice()
    Array.prototype.mySplice = function () {
        var arr = this;
        var res = [], temp = [];
        if (arguments.length == 1) {   //存在第一个参数情况
            for (let i = arguments[0]; i < arr.length; i++) {
                res.push(arr[i]);
            }
            for (let i = 0; i < arguments[0]; i++) {
                temp.push(arr[i]);
            }
            arr = temp;  //改变原数组
            return res;   
        } else { 
            if (arguments[1] == 0 || arguments[1] > arr.length) {  
                return [];   //第二个参数为0,或者超过原数组的情况
            } else {
                let k = arguments[1];  //保存下来,后面取值会用到
                let n = arguments[0]
                for (let i = n; i < arr.length; i++) {
                    res.push(arr[i]);
                    arguments[1]--;  //第二个参数减减
                    if (arguments[1] <= 0) {
                        var array = Object.assign([], arr);  //浅拷贝
        //会有删除中间元素的情况,这样的话就要取到第一个被删除元素前的,和最后被删除后的元素
        //比如[1, 2, 4, 5, 8, 7] 删除[2,4,5] ,那么原数组为[1,8,7]
                        for (let i = 0; i < n; i++) {  //取到[1]
                            temp.push(array[i])
                        }
                        for (let i = k; i < array.length; i++) {  //取到[8,7]
                            temp.push(array[i])
                        }
                        arr = temp;  //赋值给原数组
                        break;
                    }
                }
                if (arguments[2]) {  //存在第三个函数的情况,做插入
                    arr[n] = arguments[2];
                }
            }
            return res;
        }
    }
    var arr = [1, 2, 4, 5, 8, 7];
    console.log(arr.mySplice(1,3,44));

  实现splice是我自己实现的,程序可能存在不完美的之处,欢迎指出。

  期待大家共同进步?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java常见算法有很多,以下是一些常见算法目及其解决方法。 1. 求两个整数的最大公约数和最小公倍数。可以使用辗转相除法来求最大公约数,即不断用较大数除以较小数,直到余数为0,则较小数就是最大公约数。最小公倍数等于两数的乘积除以最大公约数。 2. 数组中找出第K大(小)的数。可以使用快速排序的思想,选取一个基准元素,将数组分为大于基准元素和小于基准元素的两部分,递归地在其中一部分中查找第K大(小)的数。 3. 判断一个字符串是否为回文串。可以使用双指针法,分别从字符串的开头和结尾开始遍历,判断对应字符是否相等,直到两指针相遇或交叉。 4. 实现链表的反转。可以使用迭代或递归的方式,将当前节点的下一个节点指向上一个节点,然后继续遍历链表。 5. 实现二分查找算法。对于有序数组,可以使用二分查找法,在数组的中间位置判断目标值与中间值的大小关系,然后缩小查找范围,直到找到目标值或查找范围为空。 6. 实现图的深度优先搜索(DFS)和广度优先搜索(BFS)。DFS使用递归的方式进行搜索,遍历当前节点的邻接节点,直到遍历完所有节点或找到目标节点。BFS使用队列进行搜索,将当前节点的邻接节点加入队列,并依次出队访问,直到找到目标节点或队列为空。 以上只是一些常见算法目,掌握这些算法可以帮助我们更好地理解和解决实际问。当然,还有许多其他的算法目,不断学习和练习才能更好地掌握。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值