Bootstrap

(JavaScript版)LeetCode刷题笔记-1

1、 两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

var twoSum = function(nums, target) {
  let number = [];
  var set = new Set();
  for(let j = 0; j < nums.length-1; j++){
for(let i = 1; i <= nums.length; i++){
      if(nums[i] + nums[j] === target){
          set.add(j);
          set.add(i);
      }
  }
  }

  for(let x of set){
    number.push(x)
  }
  return number
}

2、回文数字
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入: 121
输出: true
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

var isPalindrome = function(x) {
  if(x < 0){
      return false;
  }
      let y = x;
      let n = 0;
      let m = 0;
      while(y != 0){
          n = y % 10;
          m = m*10 + n;
          y = Math.floor( y / 10);
      }
      return m == x;
  
};

3、 柠檬水找零
在柠檬水摊上,每一杯柠檬水的售价为 5 美元。
顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。
每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。
注意,一开始你手头没有任何零钱。
如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
提示:

  • 0 <= bills.length <= 10000
  • bills[i] 不是 5 就是 10 或是 20
/**
 * 已知题意:每杯柠檬水是 5 刀,且每人只能买一杯。
 * @param {number[]} bills
 * @return {boolean}
 */

var lemonadeChange = function (bills) {

  let five = 0, ten = 0;
  for(let i of bills){
    if (i === 5) five++; //如果直接付款5,直接入账
    else if (i === 10) {five--; ten++;}//付款10,入10,出5
    else if (ten > 0 && five > 0) {ten--; five--;} // 如果有10和5,则出账
    else five -= 3;
    if (five < 0) return false;
  }
  return true;
}

4、整数反转
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。
请根据这个假设,如果反转后整数溢出那么就返回 0。

/*
 * @param {number} x
 * @return {number} 
 */
var reverse = function (x) {
  let str = '';
  if (x < 0) {
    str = '-'
    x = -x;
  }
  let n = 0;
  while (x != 0) {
    n = n * 10 + x % 10;
    x = Math.floor(x / 10);
  }
  n = str + n;
  if (n >= (Math.pow(2, 31) - 1) || n <= -Math.pow(2, 31)) return 0;
  return n;
};

5、 罗马数字转整数
罗马数字包含以下七种字符: 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) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

/*
 * @param {string} s
 * @return {number}
 */
var romanToInt = function (s) {
  let romeLable = new Map([["I", 1],
  ["V", 5],
  ["X", 10],
  ["L", 50],
  ["C", 100],
  ["D", 500],
  ["M", 1000]]);
  let number = 0;
  let numbers = [];
  for (let i = 0; i <= s.length-1; i++) {
    if (romeLable.get(s[i]) >= romeLable.get(s[i + 1])) {
      numbers.push(romeLable.get(s[i]))
    }
    if (romeLable.get(s[i]) < romeLable.get(s[i + 1])) {
      numbers.push(-romeLable.get(s[i]))
    }
  }
  numbers.push(romeLable.get(s[s.length-1]))
  numbers.forEach(element => {
    number += element;
  })
  return number;
};

6、最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。

 /* 方法一
 * @param {string[]} strs
 * @return {string}
 */
var longestCommonPrefix = function (strs) {
  let s = "";
  let result = "";
  let flag = false;
  let j = 1;
  for (let i = 0; i < strs[0].length; i++) {
    s = strs[0].slice(0, j);
    for (let n = 1; n < strs.length; n++) {
      if (s === strs[n].slice(0, j)) {
        if (n === strs.length - 1) {
          result = strs[n].slice(0, j);
        }
      } else {
        flag = true;
        break;
      }
    }
    if (flag) {
      break;
    }
    j += 1;
  }
  return result;
};
/**
 * 方法二
 * @param {*} strs 
 */
var longestCommonPrefix = function (strs) {
  let arr = [];
  let result = "";
  for (let i = 0; i < strs.length; i++) {
    arr.push(strs[i].length)
  }
  arr.sort((a, b) => a - b); // 进行排序从小到大-找出最小长度
  for (let j = 0; j < arr[0]; j++) {  //公共前缀小于等于最小长度
    let s = strs[0][j]; // 取出第一个的每个字符
    if (strs.every(val => val[j] === s)) { // 判断数组的每一项中的位置j的字符是否与取出进行比较的字符相等
      result += s; //相等便记录下来
    } else {
      break; // 直到找到出现不同的地方
    }
  }
  return result;

}

7、 有效括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’
的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

/*
 * @param {string} s
 * @return {boolean}
 */
var isValid = function (s) {
  let valid = []
  //前提是s 的长度为偶数 或 0
  if (s.length % 2 === 0 || s.length === 0) {
    let length = s.length;
    for (let i = 0; i < length; i++) {
      if (s[i] === '(') valid.push(')');
      else if (s[i] === '[') valid.push(']');
      else if (s[i] === '{') valid.push('}');
      else {
        if (s[i] === '' || s[i] !== valid.pop()) {
          return false;
        };
      }
    }
    if (valid[0] !== undefined) return false;
    return true;
  } else {
    return false;
  }
};

8、移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function (nums, val) {
  let length = nums.length;
  for (let i = 0; i < length; i++) {

    if (nums.indexOf(val) !== -1) {
      nums.splice(nums.indexOf(val), 1);
    }
  }
  return nums.length;
};

9、外观数列
给定一个正整数 n ,输出外观数列的第 n 项。
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
你可以将其视作是由递归公式定义的数字字符串序列:

countAndSay(1) = “1”
countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。
前五项如下:

  1. 1
    
  2. 11
    
  3. 21
    
  4. 1211
    
  5. 111221
    

第一项是数字 1
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 “11”
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 “21”
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 “1211”
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 “111221”
要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。

/*
 * @param {number} n
 * @return {string}
 */
var countAndSay = function (m) {
  let s = '1';
  for(let i = 0; i < m-1; i++){
   s = say(s)
  }
  return s
};

var say = function(s) {
  let str = s;
  let ss = ''
  let n = -1;

  for (let i = 0; i < str.length; i++) {
    let item = str[i];
    let count = 0;
    for (let j = n + 1; j < str.length; j++) {
      if (str[j] === item) {

        if (j === str.length - 1) {
          n = str.length - 1
        }
        count += 1; // 获得个数
      } else {
        n = j - 1;
        break;
      }
    }
    j = n; // 获得停止处的位置
    i = n;
    ss += (count + item);
  }
  return ss;
}

10、 删除排序数组中的重复项
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

/*
 * @param {number[]} nums
 * @return {number}
 */

var removeDuplicates = function (nums) {
  let length = nums.length;
  let s = new Set(nums) //去重
  for(let j = 0; j<length; j++){ // 清空nums
    nums.pop()
  }
  for (let i of s) { // 重新赋值
    nums.push(i)
  }
  return s.size; //返回长度
};
;