[路飞]_力扣算法题练习一:有效括号、回文数、合并排序链表、二叉树前序遍历

282 阅读2分钟

有效括号

力扣链接

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。

  const left = ['(', '{', '[']
  const map = {
    ')': '(',
    '}': '{',
    ']': '['
  }

  function isValid(str) {
    var arr = str.split('')
    var stack = []
    for (var i = 0; i < arr.length; i++) {
      var item = arr[i]
      if (stack.length === 0 && left.includes(item) === -1) {
        return false
      }
      if (left.includes(item)) {
        stack.push(item)
      } else {
        if (map[item] !== stack.pop()) {
          return false
        }
      }
    }
    if (stack.length) {
      return false
    }
    return true
  }

  console.log(isValid("()"))//true
  console.log(isValid("()[]{}"))//true
  console.log(isValid("(]"))//false
  console.log(isValid("([)]"))//false
  console.log(isValid("{[]}"))//true

回文数

力扣链接

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。

回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。

160_statement.png

  var isPalindrome = function() {
    // 特殊情况:
    // 如上所述,当 x < 0 时,x 不是回文数。
    // 同样地,如果数字的最后一位是 0,为了使该数字为回文,
    // 则其第一位数字也应该是 0
    // 只有 0 满足这一属性
    if (x < 0 || (x % 10 === 0 && x !== 0)) {
        return false;
    }

    let revertedNumber = 0;
    while (x > revertedNumber) {
        revertedNumber = revertedNumber * 10 + x % 10;
        x = Math.floor(x / 10);
    }

    // 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
    // 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,
    // 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
    return x === revertedNumber || x === Math.floor(revertedNumber / 10);
};

利用高阶函数

var isPalindrome = function(x) { 
    if (x < 0 || (x % 10 === 0 && x !== 0)) {
        return false;
    }
    return Array.from(String(x)).reverse().join('') === String(x) 
};

合并排序链表

力扣链接

给定一个链表数组,每个链表都已经按升序排列。

请将所有链表合并到一个升序链表中,返回合并后的链表。

//js并没有链表结构,所以我们需要自己构建链表结构,步骤如下
//数组转链表
//链表合并排序
//链表结果转数组   以数组方式展示
function ListNode(val) {
    this.val = val;
    this.next = null;
}
//数组转链表函数
function ListNode(val) {
  this.val = val;
  this.next = null;
}
//数组转链表函数
function generateList(arr) {
  let fakeHead = new ListNode(0);
  let current = fakeHead;
  for (let index = 0; index < arr.length; index++) {
    current.next = { val: arr[index], next: null }
    current = current.next
  }
  return fakeHead.next
}
//链表转数组
function generateArray(list) {
  let res = [];
  while (list) {
    res.push(list.val);
    list = list.next
  }
  return res;
}
var mergeKLists = function (lists) {
  lists = lists.map(item => generateList(item))
  var newList = new ListNode('head')
  var lastList = newList
  while (lists.length > 0) {
    var nullIndex = 0;
    let min = null
    for (let i = 0; i < lists.length; i++) {
      var item = lists[i]
      if (min === null) {
        min = item.val;
        nullIndex = i
        continue;
      }
      if (min > item.val) {
        min = item.val
        nullIndex = i

        continue;
      }
    }
    lastList.next = new ListNode(min)
    lastList = lastList.next
    lists[nullIndex] = lists[nullIndex].next
    if (lists[nullIndex] === null) {
      lists.splice(nullIndex, 1)
    }
  }
  return generateArray(newList.next)
}

var lists = [
  [1, 3, 5],
  [3, 5, 7],
  [1, 2, 3],
]
console.log(mergeKLists(lists))
//输入[[1,3,5],[3,5,7],[1,2,3]]
//输出[1, 1, 2, 3, 3, 3, 5, 5, 7]

解法二

/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function (lists) {
  // 当是空数组的情况下
  if (!lists.length) {
    return null;
  }
  // 合并两个排序链表
  const merge = (head1, head2) => {
    let dummy = new ListNode(0);
    let cur = dummy;
    // 新链表,新的值小就先接谁
    while (head1 && head2) {
      if (head1.val < head2.val) {
        cur.next = head1;
        head1 = head1.next;
      } else {
        cur.next = head2;
        head2 = head2.next;
      }
      cur = cur.next;
    }
    // 如果后面还有剩余的就把剩余的接上
    cur.next = head1 == null ? head2 : head1;
    return dummy.next;
  };
  const mergeLists = (lists, start, end) => {
    if (start + 1 == end) {
      return lists[start];
    }
    // 输入的k个排序链表,可以分成两部分,前k/2个链表和后k/2个链表
    // 如果将这前k/2个链表和后k/2个链表分别合并成两个排序的链表,再将两个排序的链表合并,那么所有链表都合并了
    let mid = (start + end) >> 1;
    let head1 = mergeLists(lists, start, mid);
    let head2 = mergeLists(lists, mid, end);
    return merge(head1, head2);
  };
  return mergeLists(lists, 0, lists.length);
};

二叉树前序遍历

力扣链接

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

inorder_1.jpg

输入: root = [1,null,2,3]
输出: [1,2,3]
  • 递归法
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    let arr = []
    function qianxu(root){
        if(!root||!root.val) return
        arr.push(root.val)
        qianxu(root.left)
        qianxu(root.right)
    }
    qianxu(root)
    return arr
};
  • 迭代法
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNoderoot
 * @return {number[]}
 */
var preorderTraversal = function(root) {
    const stack = [];
    const res = [];
    if (root) stack.push(root);
    while (stack.length) {
        const node = stack.pop();
        const left = node.left
        const right = node.right
        if (!node.left && !node.right) {
            res.push(node.val);
            continue;
        }
        if (right) stack.push(node.right); // 右
        if (left) stack.push(node.left); // 左
        node.left = null
        node.right = null
        stack.push(node); // 中
    };
    return res;
};