算法连载(第二期)

146 阅读4分钟

hello 大家好,我是django。 今天跟大家分享几道算法题分别是《搜索插入位置》、《二叉树的深度》、《罗马数字转整数》、《反转字符串》

一、搜索插入位置

要求

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 为无重复元素的升序排列数组
  • -104 <= target <= 104

思路

由于要插入的数组是已经排好序的数组,我们可以利用插入排序的思想将要插入式的数与之前的数进行对比,如果arr[i - 1] === target既返回i-1,如果arr[i - 1] < target既返回i,否则i-1i互换位置。

实现

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
function searchInsert (nums, target) {
  nums.push(target);

  for (let i = nums.length - 1; i > 0; i--) {
    if (nums[i - 1] === target) {
      return i - 1;
    }
    if (nums[i - 1] > target) {
      const temp = nums[i - 1];
      nums[i - 1] = nums[i];
      nums[i] = temp;
    } else {
      return i;
    }
  }
  return 0;
};

二、二叉树的深度

要求

输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。

例如:

给定二叉树 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

思路

二叉树的最大高度计算公式为 maxHeight = Math.max(leftHeight, rightHeight) + 1

实现

利用递归遍历得到左右两边的节点高度

  function getHeight(node) {
      // k0 为真
      if(!node) return 0;
      return Math.max(getHeight(node.left), getHeight(node.right)) + 1;
  }

三、罗马数字转整数

要求

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 49

X可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 

C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 给定一个罗马数字,将其转换成整数。

示例 1:

输入: s = "III"
输出: 3

示例 2:

输入: s = "IV"
输出: 4

示例 3:

输入: s = "IX"
输出: 9

思路

  • 当左边的值小于右边的时候我们需要右边减去该值
  • 将字符串转为数组进行累加 或者我们也可以对每个如I这些特殊的字符进行判断

实现

function romanToInt(s) {
  // 定一个map映射罗马数字
  const romaMap = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
  const arr = s.split("");
  let sum = 0;
  for (let i = 0; i < arr.length; i++) {
    const iVal = arr[i];
    const jVal = arr[i + 1];
    if (jVal) {
      if (romaMap[iVal] < romaMap[jVal]) {
        sum += romaMap[jVal] - romaMap[iVal];
        i++;
        continue;
      }
    }
    sum += romaMap[iVal];
  }
  return sum;
}

四、反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1:

输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]

示例 2:

输入:s = ["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]

提示:

1 <= s.length <= 105
s[i] 都是 ASCII 码表中的可打印字符

思路

数组反转可以采用获取中心点后公式arr[i]arr[arr.length - 1 - i]进行位置互换

实现

/**
 * @param {character[]} s
 * @return {void} Do not return anything, modify s in-place instead.
 */
 var reverseString = function(s) {
     // 向下取整
    for(let i = 0; i < Math.floor(s.length / 2); i++) {
        const temp = s[i];
        s[i] = s[s.length - 1 -i];
        s[s.length - 1 -i] = temp;
    }
};

写在最后

在学习算法过程中,往往第一想到的可能不是最优的解法。但是思考并实践是我们想要做的事,本次分享不代表算法是最优写法只是记录个人在算法学习过程中的思路。谢谢大家,我是django下期见