【LeetCode】算法题基础篇

  1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
例子:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

解题思路:
(1)暴力枚举:枚举数组中的每一个数 x,寻找数组中是否存在 target - x
(2)哈希表:我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。

var twoSum = function(nums, target) {
	//暴力枚举方法1
    /*for(let i=0;i
    //暴力枚举方法2
    for(let i=0;i<nums.length;i++){
        let temp = target - nums[i]
        let j = nums.indexOf(temp)
        if(j != -1 && j != i) return [i,j]    
    }
    return [-1, -1]
};
var twoSum = function(nums, target) {
    let hashTable = {}
    for(let i=0; i<nums.length; i++){
        let temp = target-nums[i]
        // if(hashTable.hasOwnProperty(temp)) {
        if(temp in hashTable) {
            return [hashTable[temp], i]
        }     
        hashTable[nums[i]] = i
    }
    return []
};
  1. 回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。

解题思路:
(1)转成字符串,逐步判断前后数字是否相等
(2)将数字本身反转,然后将反转后的数字与原始数字进行比较,如果它们是相同的,那么这个数字就是回文。

var isPalindrome = function(x) {
    //1.基础方法  转成字符串,遍历进行判断
    let s = x.toString().split('')
    for(let i=0; i<s.length/2;i++){
        if(s[i] != s[s.length-1-i]) return false
    }
    return true 

var isPalindrome = function(x) {
    //2.官方算法思路  反转数字进行判断
    // (1)负数和最后一位数字为0(0除外)的肯定不是回文数
    if(x === 0) return true
    if(x < 0 || x % 10 === 0) return false

    //(2)从后往前取除以10的商和余数,计算反转后的数,当反转后的数大于等于商时,就取完了一半的数,可以停止了
    let quotient = x
    let remainder = 0
    let revert = 0
    while(revert < quotient){
        remainder = quotient % 10
        quotient = Math.floor(quotient / 10)
        revert = revert * 10 + remainder
        // console.log(remainder, quotient, revert)
    }
    //这一步之前没想到
    if(revert === quotient || quotient === Math.floor(revert / 10)) return true
    return false
};

官方题解

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

    let revertedNumber: number = 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);
};
  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) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。
示例 1:
输入: s = “III”
输出: 3
示例 2:
输入: s = “IV”
输出: 4

解题思路:
(1)遍历字符串,先把六种特殊情况给计算并替换为空,再计算普通情况
(2) 遍历的时候进行上一位的加减,上一位小于本位则在总和上减,否则则加

// @lc code=start
/**
 * @param {string} s
 * @return {number}
 */
var romanToInt = function(s) {
    let objSpecial = {
        'IV': 4,
        'IX': 9,
        'XL': 40,
        'XC': 90,
        'CD': 400,
        'CM': 900,
    }
    let objNormal = {
        'I': 1,
        'V': 5,
        'X': 10,
        'L': 50,
        'C': 100,
        'D': 500,
        'M': 1000
    }

    // 方法一
     let str = s
     //获取字符串中特殊的字符
     let sum = 0
     Object.entries(objSpecial).forEach(([key, value]) => {
         let num = 0
         let index = str.indexOf(key)
         while(index != -1) {
             num += 1
             str = str.replace(key,'')
             index = str.indexOf(key)
         }
         sum += num*value
     });
     Object.entries(objNormal).forEach(([key, value]) => {
         let num = 0
         let index = str.indexOf(key)
         while(index != -1) {
             num += 1
             str = str.replace(key,'')
             index = str.indexOf(key)
         }
         sum += num*value
    });
    // // console.log(sum);
    return sum

};
// @lc code=start
/**
 * @param {string} s
 * @return {number}
 */
var romanToInt = function(s) {
    let objSpecial = {
        'IV': 4,
        'IX': 9,
        'XL': 40,
        'XC': 90,
        'CD': 400,
        'CM': 900,
    }
    let objNormal = {
        'I': 1,
        'V': 5,
        'X': 10,
        'L': 50,
        'C': 100,
        'D': 500,
        'M': 1000
    }

    //方法二-多判断一位,右边大于左边就减,否则就加
    let sum = 0
    let pre = ''
    for (let i=0; i< s.length; i++){
        if(pre == '') {
            pre = s[i]
            continue
        }
        if(objNormal[s[i]] > objNormal[pre]){
            sum -= objNormal[pre]
        }
        else{
            sum += objNormal[pre]
        }
        pre = s[i]
    }
    sum += objNormal[s[s.length-1]]
    return sum

};
  1. 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”
示例 2:
输入:strs = [“dog”,“racecar”,“car”]
输出:“”
解释:输入不存在公共前缀。

解题思路:
先获取所有字符串的最小长度,分别对字符串进行遍历,并将对应index的字符保存在一个数组中,如果数组所有元素都相同,则进行公共前缀的拼接,执行下一次循环,否则则退出循环,返回结果

// @lc code=start
/**
 * @param {string[]} strs
 * @return {string}
 */
var longestCommonPrefix = function(strs) {
    let commonStr = ''
    let minLen = Math.min(...strs.map(function(eleStr){ 
        return eleStr.length
    }))
    for(let i=0; i< minLen; i++){
        let s = []
        strs.forEach(ele=>{
            s.push(ele[i])
        })   
        if(s.every(item=>item==s[0])){
            commonStr += s[0]
        }else{
            break
        }
    }
    return commonStr
};
  1. 有效的括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false

解题思路:
遍历字符串,遇到左括号则压入保存进数组,遇到右括号,则进行判断:
(1)判断是否在right中,获取右括号在right数组中的index
(2)判断数组中的最后一位,与left[index]是否相等,相等则进行pop,否则则不匹配,跳出循环
最后根据flag和数组长度是否等于0来进行结果判断

// @lc code=start
/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    let left = ['(', '[', '{']
    let right = [')', ']', '}']
    let arr = []
    let flag = true
    for(let i=0; i<s.length; i++){
        //ES6新增的数组方法,用于检测数组是否包含某个元素,如果包含返回true,否则返回false,比较厉害的是,能直接检测NaN
        if(left.includes(s[i])) {
            arr.push(s[i])
            continue
        }
        let index = right.indexOf(s[i])
        if(index != -1) {
            if(arr[arr.length-1] == left[index]){
                arr.pop()
                continue
            }
            else{
                flag = false
                break
            }
        }
    }
    
    return flag && arr.length == 0

};

你可能感兴趣的:(LeetCode刷题,算法,leetcode,职场和发展)