常見的幾道算法題

  最近在筆試和看面經的時候經常會碰到幾道算法題目,決定記錄下來和大家分享以下。

求數組的最大字段和

  比如: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是我自己實現的,程序可能存在不完美的之處,歡迎指出。

  期待大家共同進步?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章