Skip to content

数学算法

数学算法

统计信息:字数 7821 阅读16分钟

不借助变量交换两个数字

function swap(a , b) {
  b = b - a;
  a = a + b;
  b = a - b;
  return [a,b];
}

罗马数字转换成整数

// https://leetcode.com/problems/roman-to-integer/description/
// https://en.wikipedia.org/wiki/Roman_numerals
// example "DCXXI" => 621
module.exports = function (s) {
  const romanLetters = {
    'M': 1000,
    'CM': 900,
    'D': 500,
    'CD': 400,
    'C': 100,
    'XC': 90,
    'L': 50,
    'XL': 40,
    'X': 10,
    'IX': 9,
    'V': 5,
    'IV': 4,
    'I': 1,
  };
  const arr = s.split('');
  let index = 0;
  let num = 0
  let key = ''
  for (let i = 0; i<arr.length; i++) {
    const key = arr[i]
    if(key !== 'V' || key !== 'M') {
      if(romanLetters[key + arr[i+1]]) {
        num += romanLetters[key + arr[i+1]]
        i += 1
        continue
      }
    }
    num += romanLetters[key]
  }
  return num
}

反转整数

// https://leetcode.com/problems/reverse-integer/description/
/**
Given a 32-bit signed integer, reverse digits of an integer.
Example 1:Input: 123 Output:  321
Example 2:Input: -123 Output: -321
 */
const reverseInteger = function (num) {
  let isNegative = false;
  if (Math.abs(num) !== num) {
    isNegative = true;
  }
  // 可以先取绝对值,然后转换成字符串,就不需要replace了
  let numstr = num + '';
  numstr = numstr.replace('-', '');
  const arr = numstr.split('');
  arr.reverse();
  const result = 0 + arr.join('') * (isNegative ? -1 : 1)
  if (result >= (Math.pow(2, 31) - 1) || result <= -Math.pow(2, 31)) {
    return 0;
  }
  return result;
};

判断回文数字

// https://leetcode.com/problems/palindrome-number/description/
// examples:123 false 121 true
module.exports = function (x) {
  if (x < 0) {
    return false;
  }
  var m = x;
  var n = 0;
  while(m > 0) {
    n = (m % 10 + n * 10)
    m = Math.floor(m / 10)
  }
  return n === x
}

背包问题

/**
 * knapsack https://zh.wikipedia.org/wiki/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98
 * 背包问题
 **/
function knapsack(capacity, size, value, n) {
  var K = [];
  for (let i = 0; i <= n; i++) {
    K[i] = [];
  }
  for (let j = 0; j <=  n; j++) {
    for(let w=0;w<=capacity;w++) {
      if(j==0 || w==0) {
        K[j][w] = 0;
      }else if(size[j-1] <= w) {
        K[j][w] = Math.max(value[j-1] + K[j-1][w-size[j-1]],K[j-1][w]);
      }else {
        K[j][w] = K[j-1][w];
      }
    }  
  }
  return K[n][capacity];
}

最长连续元素

/** find the max value in an consistant element in an array
* input: [1,1,2,4,-5,12,-3,1]
* output: 15
**/

function findMaxConsitantElement(a) {
  let max = 0;
  let t = [];
  for(var i = 0;i<a.length;i++) {
    t[i] = [];
    t[i][0] = a[i];
    if(t[i][0]>max) {
      max = t[i][0];
    }
    for(var j = i+1;j<a.length;j++) {
      t[i][j] = t[i][j-1] + a[j];
      if(t[i][j]>max) {
        max = t[i][j];
      }
    }
  }
  return max; 
}

棋盘算法

/**
假设我们现在有一个 3 x 3 的井字棋游戏,我们用一个二维数组代表棋盘,’x’ 代表玩家 X 下的棋子,’o’ 代表玩家 O 下的棋子,’e’ 代表该格没有棋子。例如:

一个空白的棋盘以下面的二维数组表示
[ [‘e’, ‘e’, ‘e’],
  [‘e’, ‘e’, ‘e’],
  [‘e’, ‘e’, ‘e’] ]

如果玩家 X 在第一行第一列下了一步棋,玩家 O 在第二行第二列下了一步棋,则表示如下:
[ [‘x’, ‘e’, ‘e’],
  [‘e’, ‘o’, ‘e’],
  [‘e’, ‘e’, ‘e’] ]

现在需要一个 function,接受一个已有任意棋子的棋盘(和上面二维数组一样的格式),和玩家的标志(’x’ 或 ‘o'),返回该玩家下一步有几种可能的获胜方式(获胜方式以数组表示,[0, 0] 代表在第一行第一列下一步棋即可获胜,[2, 2] 代表在第三行第三列下一步棋即可获胜)。例如:

someFunction(
‘x’,
[ [‘o’, ‘e’, ‘e’],
  [‘o’, ‘x’, ‘o’],
  [‘x’, ‘x’, ‘e’] ]
)
// return [ [2, 2], [0, 1], [0, 2] ]

someFunction(
‘x’,
[ [‘x’, ‘o’, ‘o’],
  [‘x’, ‘x’, ‘e’],
  [‘e’, ‘o’, ‘e’] ]
)
// return [ [2, 2], [1, 2], [2, 0] ]

someFunction(
‘x’,
[ [‘x’, ‘x’, ‘o’],
  [‘e’, ‘e’, ‘e’],
  [‘e’, ‘e’, ‘e’] ]
)
// return [ ]

someFunction(
‘o’,
[ [‘o’, ‘o’, ‘o’],
  [‘e’, ‘e’, ‘e’],
  [‘e’, ‘e’, ‘e’] ]
)
 return [ ]
*/
// find 'e' to check the empty coordinates
const findE = function (arr) {
  const eCoor = [];
  arr.forEach((row, i) => {
    row.forEach((val, j) => {
      if (val === 'e') {
        eCoor.push([i, j])
      }
    });
  })
  return eCoor;
}

const checkVictory = function(x, y, role, arr, degree) {
  arr[x][y] = role;
  let result = false;
  if (degree === 0) {
    result = arr[x][0] === role && arr[x][1] === role && arr[x][2] === role;
  } else if (degree === 90) {
    result = arr[0][y] === role && arr[1][y] === role && arr[2][y] === role;
  } else if (degree === 45) {
    result = arr[0][0] === role && arr[1][1] === role && arr[2][2] === role;
  } else if (degree === -45) {
    result = arr[0][2] === role && arr[1][1] === role && arr[2][0] === role;
  }
  arr[x][y] = 'e';
  return result;
}

// check if win to select the coordinate
const queryVictory = function (role, coors, arr) {
  const victoryResults = [];
  coors.forEach((item) => {
    var x = item[0];
    var y = item[1];
    [-45, 0, 45, 90].forEach((degree) => {
      if (checkVictory(x, y, role, arr, degree)) {
        return victoryResults.push([x, y]);
      }
    })
  });
  return victoryResults;
}

module.exports = function getResult(role, arr) {
  const result = [];
  const eCoor = findE(arr);
  if (eCoor.length === 0) {
    return [];
  }
  return queryVictory(role, eCoor, arr);

}

斐波那契算法

canvas 画布

var canvas = document.querySelector('canvas');

canvas.width = 600;
canvas.height = 480;

var coor = {
  x: 300,
  y: 240,
};

var ctx = canvas.getContext('2d');

function draw(r, n ,prevR) {
   if(n>2) {
     switch(n%4) {
      case 0 :
        coor.y = coor.y - 5 * prevR;
        coor.y = coor.y + 5 * r;

        break;
      case 1 :
        coor.x = coor.x + 5 * prevR;
        coor.x = coor.x - 5 * r;
        break;
      case 2 :
        coor.y = coor.y + 5 * prevR;
        coor.y = coor.y - 5 * r;
        break;
      case 3 :
        coor.x = coor.x - 5 * prevR;
        coor.x = coor.x + 5 * r;
        break;
    }
  }
  ctx.beginPath();
  ctx.arc(coor.x,coor.y,5*r,Math.PI*0.5*(n),Math.PI*0.5*(n-1),true);
  if(n>1) {
     switch(n%4) {
      case 0 :
        ctx.moveTo(coor.x - 5*r,coor.y);

        break;
      case 1 :
        ctx.moveTo(coor.x,coor.y + 5*r);
        break;
      case 2 :
       ctx.moveTo(coor.x + 5*r,coor.y);
        break;
      case 3 :
        ctx.moveTo(coor.x,coor.y-5*r);
        break;
    }
  }

  ctx.lineWidth = 1;
  ctx.strokeStyle = '#fff';
  ctx.stroke();
}


function getFibonacci(n) {
  var fibarr = [];
  var i = 0;
  while(i<n) {
    if(i<=1) {
      fibarr.push(i);
    }else{
      fibarr.push(fibarr[i-1] + fibarr[i-2])
    }
    i++;
  }

  return fibarr;
}
var data = getFibonacci(10);

for(var i = 0,l=data.length;i<l;i++) {
  if(data[i]!=0) {
    draw(data[i],i,data[i-1]);

  }
}

哈希表算法

两数之和

https://leetcode.com/problems/two-sum/description/

function twoSum(nums, target) {
  const arr = nums;
  const keyMap = {};
  for (let i = 0, len = arr.length; i < len; i++) {
    if (typeof keyMap[target - arr[i]] !== 'undefined') {
      return [keyMap[target - arr[i]], i]
    }
    keyMap[arr[i]] = i;
  }
  return [i, j];
};

Last update: November 9, 2024