最近在筆試和看面經的時候經常會碰到幾道算法題目,決定記錄下來和大家分享以下。
求數組的最大字段和
比如: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是我自己實現的,程序可能存在不完美的之處,歡迎指出。
期待大家共同進步?