这是一份不定期更新的笔记。封面 pid:77734148

1.两数之和

原题
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

输入: nums = [2, 7, 11, 15], target = 9
输出: [0,1]

var twoSum = function(nums, target) {
    let map ={};
    // nums某个数=>该数的下标
    for(let i in nums){
        //for num in nums,在map中检查是有 num 的差值,有就返回
        if(!isNaN(map[target-nums[i]]))return [i,map[target-nums[i]]];
        //录入num
        map[nums[i]] = i;
    }
};

2.两数相加

原题
给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。可以假设除了数字 0 之外,这两个数都不会以 0 开头。

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

/**
 * 节点定义
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
var addTwoNumbers = function(l1, l2) {
    let x,y,tmp,c=0,ret = new ListNode(0);
    let cur = ret;
    while(l1||l2){
        //如果到尽头了,当做0
        x = l1?l1.val:0;
        y = l2?l2.val:0;
        tmp = x + y + c;
        c = tmp>=10?1:0;
        cur.next = new ListNode(tmp%10);
        cur = cur.next;
        //先到尾的就维持为 null
        l1 && (l1 = l1.next);
        l2 && (l2 = l2.next);
    }
    //最后还有进位就再加一位
    c && (cur.next = new ListNode(c))
    return ret.next;
};

3.无重复字符的最长子串

原题
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

var lengthOfLongestSubstring = function(s) {
    let p1,p2,max=0,i1,i2,map={};//使用hashmap查重
    i1 = i2 = p1 = p2 = 0;
    while(p2<s.length){
        //p1,p2组成移动窗口,维护一个无重复字符的窗口
        //后指针p2尽量往后移
        if(!map[s[p2]]){
            map[s[p2]] = 1;
            p2++;
        }
        //p2后移出现重复,前指针p1后移直到重复消除
        else{
            delete map[s[p1]];
            p1++;
        }
        if(p2-p1>max){
            //i1,i2记录最长子串的起始点,max记录其长度
            i1 = p1;
            i2 = p2;
            max = p2 - p1
        }
    }
    //因为p2++的存在,max是默认加一的
    return max
};

5.最长回文子串

原题
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

输入: "babad"
输出: "bab"/"aba"

var longestPalindrome = function(s) {
    //中心扩展算法
    if(!s)return '';
    let [left,right,len,maxStart,maxLen] = [0,0,1,0,0];
    for(let i=0;i<s.length;i++){
        left = i - 1;
        right = i + 1;
        //i指向中心,首先从中心向两边扩展,寻找最长重复串
        while(left>=0&&s[i]==s[left]){
            len++;
            left--;
        }
        while(right<s.length&&s[i]==s[right]){
            len++;
            right++;
        }
        //最长重复串的基础再向两边(等长)扩展,要求两边相等
        while(left>=0 && right<s.length && s[left]==s[right]){
            len += 2;
            left--;right++;
        }
        //有更长的回文,记录其开始点和长度
        if(len>maxLen){
            maxLen = len;
            maxStart = left+1;
        }
        //中心下移,len重置
        len = 1;
    }
    return s.substr(maxStart,maxLen);
};

6.Z 字形变换

原题
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:

L   C   I   R
E T O E S I I G
E   D   H   N

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。请实现这个将字符串进行指定行数变换的函数

输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"

var convert = function(s, numRows) {
    //从上往下扫描算法
    //排除空串、长度不大于行数的串、行数为1的情况
    if(!s)return '';
    if(numRows==1||s.length<=numRows)return s;
    //分别是取值下标、s长度、返回结果
    let [ind,len,res] = [0,s.length,''];
    //最长间隔
    let maxInterval = 2*(numRows-1);
    //最长间隔分成前后两个小间隔
    let front,back;
    //从上到下逐行填充
    for(let i=0;i<numRows;i++){
        ind = i;
        front = maxInterval - i*2;
        back = i*2;
        res += s[ind];
        while(ind<len){
            //前后间隔中不为0的那个,作为步幅加到当前下标并取值(如果没超出索引范围)
            if(front){
                ind+=front;
                ind<len && (res+=s[ind]);
            }
            if(back){
                ind+=back;
                ind<len && (res+=s[ind]);
            }
        }
    }
    return res;
};

7.整数反转

原题
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。假设数值范围为 [−231, 231 − 1],如果反转后整数溢出那么就返回 0。

输入: 123/-123/120
输出: 321/-321/21

var reverse = function(x) {
    let ret = 0;
    while(x!=0){
        if(ret > 214748364 || ret < -214748364)
            return 0;
        ret = ret*10 + x%10;
        x = x>0?Math.floor(x/10):Math.ceil(x/10);
    }
    return ret;
};

8.字符串转换整数

原题
根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来的转化规则如下:

  • 如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。
  • 假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。
  • 该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换,即无法进行有效转换,返回 0

输入: "42"/"- 42"/"www114"/"114www"
输出: 42/-42/0/114

//最简正则
var myAtoi = function(str) {
    let ret = /^[+-]?\d+/.exec(str.trim());
    if(ret===null)return 0;
    return Math.min(Math.max(parseInt(ret[0]),-2147483648),2147483647);
};

11.盛最多水的容器

原题
给定若干个非负整数列 an,对应坐标(n,an),对n个坐标作垂线,相邻两条垂线间隔为1,任两条垂线和横坐标能能组成一个u型容器,先求该容器的最大容量(满足木桶原理)

输入:[1,8,6,2,5,4,8,3,7]
输出:49

var maxArea = function(height) {
    //前后双指针解法
    let [p1,p2,ret,tmp] = [0,height.length-1,0,0];
    while(p1!=p2){
        //计算面积并保留大值
        tmp = Math.min(height[p1],height[p2]) * (p2-p1);
        if(tmp>ret)
            ret = tmp;
        //值小的指针往另外的方向移动
        height[p1]>height[p2]?p2--:p1++;
    }
    return ret;
};

    添加新评论 | #

    Markdown Supported
    简单数学题:NaN + NaN =
    表情

    Comments | ?? 条评论

    • 单身为狗 21 年

    • 朝循以始 夜继以终

    • Blog: Von by Bersder

    • Alive: 0 天 0 小时 0 分

    Support:

    frame ssr server DNS music player

    © 2019-2020 ᛟᛊᚺᛁᚾᛟ

    back2top