leetcode - 103道入门基础题

一、leetcode - 字符串
二、leetcode - 二进制、数学类
三、leetcode - 数组
四、leetcode - 二分查找
五、leetcode - 快慢指针
六、leetcode - 滑动窗口
七、leetcode - 矩阵
八、leetcode - 栈和队列
九、leetcode - 链表
十、leetcode - 二叉树
十一、leetcode - 并查集
十二、leetcode - 回溯
十三、leetcode - 动态规划
十四、leetcode - 贪心

一、leetcode - 字符串

344. 反转字符串
输入: s = [ "h", "e", "l", "l", "o" ]
输出:     [ "o", "l", "l", "e", "h" ]
/**
 * @param {character[]} s
 * @return {void} Do not return anything, modify s in-place instead.
 */
var reverseString = function(s) {
   
    return s.reverse();
};
[ 'o', 'e', 'l', 'l', 'h' ] 
[ 'o', 'l', 'l', 'e', 'h' ] 
[ 'o', 'l', 'l', 'e', 'h' ]
/**
/**
 * @param {character[]} s
 * @return {void} Do not return anything, modify s in-place instead.
 */
var reverseString = function(s) {
   
    let l = 0;
    let r = s.length - 1;
    while(l <= r) {
   
        // let temp = s[l];
        // s[l] = s[r];
        // s[r] = temp;
        [s[l], s[r]] = [s[r], s[l]];
        l++;
        r--;
        console.info(s);
    }
    return s;
};
9. 回文数
输入: x = 121
输出: true
1 1 
2 2
输入: x = -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
- 1
/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
   
    let arr = x.toString();
    let len = arr.length;
    for(let i = 0; i < len/2; i++) {
   
        console.info(arr[i] + '  ' + arr[len - 1 - i]);
        if(arr[i] !== arr[len - 1 - i]) {
   
            return false;
        }
    }
    return true;
};
/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
   
    return x.toString() === x.toString().split('').reverse().join('');
};
125. 验证回文串
输入: "A man, a plan, a canal: Panama"
输出: true
解释: "amanaplanacanalpanama" 是回文串
amanaplanacanalpanama // 只保留字母和数字
a a 
m m 
a a 
n n 
a a 
p p 
l l 
a a 
n n 
a a 
c c  // 最后下标重合 c自己和自己比较
/**
 * @param {string} s
 * @return {boolean}
 */
var isPalindrome = function(s) {
   
    s = s.toLowerCase().replace(/[^a-z0-9]/g, '');
    console.info(s);
    let l = 0;
    let r = s.length - 1;
    while(l <= r) {
   
        console.info(s[l] + ' ' + s[r]);
        if(s[l] !== s[r]) return false;
        l++;
        r--;
    }
    return true;
};
28. 实现 strStr()

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。

输入: haystack = "hello", needle = "ll"
输出: 2
h l 
e l 
l l 
ll ll
/**
 * @param {string} haystack
 * @param {string} needle
 * @return {number}
 */
var strStr = function(haystack, needle) {
   
    if(needle.length === 0) return 0;
    let res = -1;
    for(let i = 0; i < haystack.length; i++) {
   
        console.info(haystack[i] + ' ' + needle[0]);
        if(haystack[i] === needle[0]) {
   
            console.info(haystack.substring(i, needle.length + i) + ' ' + needle);
            if(haystack.substring(i, needle.length + i) === needle) {
   
                res = i;
                break;
            }
        }
    }
    return res;
};
387. 字符串中的第一个唯一字符

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

s = "leetcode"
返回 0
{ l: 1, e: 3, t: 1, c: 1, o: 1, d: 1 }
/**
 * @param {string} s
 * @return {number}
 */
var firstUniqChar = function(s) {
   
    let map = {
   };
    for(let item of s){
   
        map[item] = (map[item] || 0) + 1;
    }
    console.info(map);
    for(let i = 0; i < s.length; i++){
   
        if(map[s[i]] === 1) return i;
    }
    return -1;
};
242. 有效的字母异位词

st 中每个字符出现的次数都相同,则称 st 互为字母异位词。

输入: s = "anagram", t = "nagaram"
输出: true 
{ a: 1, n: -1 } 
{ a: 0, n: 0 } 
{ a: 1, n: 0, g: -1 } 
{ a: 0, n: 0, g: 0 } 
{ a: 0, n: 0, g: 0, r: 0 } 
{ a: 0, n: 0, g: 0, r: 0 } 
{ a: 0, n: 0, g: 0, r: 0, m: 0 }
/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
   
    let sLen = s.length;
    let tLen = t.length;
    if(sLen !== tLen) return false;
    let count = {
   };
    for(let i = 0; i < sLen; i++) {
   
        count[s[i]] ? count[s[i]]++ : count[s[i]] = 1;
        count[t[i]] ? count[t[i]]-- : count[t[i]] = -1;
        console.info(count);
    }
    return Object.values(count).every(item => item === 0);
};
383. 赎金信

给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。

(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)

输入: ransomNote = "aa", magazine = "aab"
输出: true
{ a: 2, b: 1 }  // 杂志中包含的字符
{ a: 1, b: 1 }  // 赎金信中用掉一个a
{ a: 0, b: 1 }  // 赎金信中又用掉一个a
/**
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function(ransomNote, magazine) {
   
    let map = {
   }; 
    // 统计杂志中字母个数
    for(const s of magazine) {
   
        map[s] = (map[s] || 0) + 1;
    }
    console.info(map);
    // 从杂志中逐个删除赎金信中用到的字符,如果杂志中缺少要用到的字符则直接返回false
    for(const s of ransomNote) {
    
        if(!map[s]) return false;
        map[s]--;
        console.info(map);
    }
    return true;
};
ab // 赎金信中用掉一个a
b  // 赎金信中又用掉一个a
/**
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function(ransomNote, magazine) {
   
    // 直接遍历赎金信,其中的字符如果在杂志中没有则直接返回false
    // 如果在杂志中有则从杂志中删除该字符,因为已经使用
    for (let i = 0; i < ransomNote.length; i++) {
   
        let s = ransomNote[i];
        if(magazine.indexOf(s) === -1) return false;
        magazine = magazine.replace(s, '');
        console.info(magazine);
    }
    return true;
};

二、leetcode - 二进制、数学类

191. 位1的个数
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
每次去掉二进制中的最后一个1
1010 
1000 
0
/**
 * @param {number} n - a positive integer
 * @return {number}
 */
var hammingWeight = function(n) {
   
    let res = 0;
    while(n) {
   
        n = (n - 1) & n;
        res++;
        console.info(parseInt(n).toString(2));
    }
    return res;
};
326. 3的幂
输入: n = 27
输出: true
9 
3 
1
输入: n = 45
输出: false
15 
5 
1.6666666666666667
/**
 * @param {number} n
 * @return {boolean}
 */
var isPowerOfThree = function(n) {
   
    while(n >= 3) {
   
        n = n / 3;
        console.info(n);
    }
    return n === 1;
};
136. 只出现一次的数字
输入: [2,2,1]
输出: 1
相同值异或运算为0,与0进行异或运算为原值
res  运算过程
0    2^2=0
1    0^1=1
/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
   
    let res = nums[0];
    for(let i = 1; i < nums.length; i++) {
   
        res ^= nums[i];
        console.info(res);
    }
    return res;
};
172. 阶乘后的零
输入: n = 5
输出: 1
解释: 5! = 120 ,有一个尾随 0
1
/**
 * @param {number} n
 * @return {number}
 */
var trailingZeroes = function(n) {
   
    let res = 0;
    while(n > 1) {
   
        n = (n / 5 | 0);
        res += n;
        console.info(n);
    }
    return res;
};
7. 整数反转
输入: x = -123   输出: -321
输入: x = 120    输出: 21
res=-3   x=-12 
res=-32  x=-1 
res=-321 x=0

res=0  x=12 
res=2  x=1 
res=21 x=0
/**
 * @param {number} x
 * @return {number}
 */
var reverse = function(x) {
   
    let res = 0;
    let min = Math.pow(-2, 31);
    let max = Math.pow(2, 31) - 1;
    while(x) {
   
        res = res * 10 + x % 10; // x % 10: 取10进制的个位数字
        if(res > max || res < min) return 0;
        x = x / 10 | 0; // 取10进制个位以上的数字
        console.info('res='+res+' x='+x);
    }
    return res;
};
171. Excel 表列序号
输入: columnTitle = "AB"
输出: 28
1 
28
/**
 * @param {string} columnTitle
 * @return {number}
 */
var titleToNumber = function(columnTitle) {
   
    let ans = 0;
    for(let item of columnTitle){
   
        ans = ans * 26 + (item.charCodeAt() - 'A'.charCodeAt() + 1);
        console.info(ans);
    }
    return ans;
};
190. 颠倒二进制位
输入:n = 00000010100101000001111010011100
输出:964176192 (00111001011110000010100101000000)
解释:输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596,
     因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。
32次循环,一次挪动一位
0 - 1010010100000111101001110 
0 - 101001010000011110100111 
1 - 10100101000001111010011 
11 - 1010010100000111101001 
111 - 101001010000011110100 
1110 - 10100101000001111010 
11100 - 1010010100000111101 
111001 - 101001010000011110 
1110010 - 10100101000001111 
11100101 - 1010010100000111 
111001011 - 101001010000011 
1110010111 - 10100101000001 
11100101111 - 1010010100000 
111001011110 - 101001010000 
1110010111100 - 10100101000 
11100101111000 - 1010010100 
111001011110000 - 101001010 
1110010111100000 - 10100101 
11100101111000001 - 1010010 
111001011110000010 - 101001 
1110010111100000101 - 10100 
11100101111000001010 - 1010 
111001011110000010100 - 101 
1110010111100000101001 - 10 
11100101111000001010010 - 1 
111001011110000010100101 - 0 
1110010111100000101001010 - 0 
11100101111000001010010100 - 0 
111001011110000010100101000 - 0 
1110010111100000101001010000 - 0 
11100101111000001010010100000 - 0 
111001011110000010100101000000 - 0 
964176192
/**
 * @param {number} n - a positive integer
 * @return {number} - a positive integer
 */
var reverseBits = function(n) {
   
    let result = 0
    for (let i = 0; i < 32; i++) {
   
        result = (result << 1) + (n & 1); // 获取二进制最后一位,并不断左移
        n = n >> 1; // 原二进制数不断右移
        console.info(parseInt(result).toString(2)+' - '+parseInt(n).toString(2));
    }
    // 为什么要 >>> 0 呢,一位javascript没有无符号整数,全是有符号的
    // 不>>>0的话,得出来的值是负数,但是无符号整数是没有符号的
    // javascript 有符号转化为无符号的方法就是>>>0
    console.info(result >>> 0);
    return result >>> 0;
};

三、leetcode - 数组

217. 存在重复元素
输入: [1,2,3,1]
输出: true
/**
 * @param {number[]} nums
 * @return {boolean}
 */
var containsDuplicate = function(nums) {
   
    let map = {
   };
    for(let item of nums) {
   
        if(map[item]) {
   
            return true;
        }
        map[item] = true;
    }
    return false;
};
349. 两个数组的交集

输出结果中的每个元素一定是唯一的

map 双循环

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersection = function(nums1, nums2) {
   
    let map = {
   };
    let res = [];
    for(let item of nums1) {
   
        map[item] = true;
    }
    for(let item of nums2) {
   
        if(map[item]) {
   
            res.push(item);
            map[item] = false;
        }
    }
    return res;
};
350. 两个数组的交集 II

输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致

双数组双指针

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
   
    let map = {
   };
    let res = [];
    for(let item of nums1) {
   
        map[item] = (map[item] || 0) + 1;
    }
    for(let item of nums2) {
   
        if(map[item]) {
   
            res.push(item);
            map[item]--;
        }
    }
    return res;
};
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
   
    nums1.sort((a, b) => a - b);
    nums2.sort((a, b) => a - b);
    let res = [];
    let l1 = nums1.length - 1;
    let l2 = nums2.length - 1;
    while(l1 >= 0 && l2 >= 0) {
   
        if(nums1[l1] === nums2[l2]) {
   
            res.push(nums1[l1]);
            l1--;
            l2--;
        }
        if(nums1[l1] > nums2[l2]) l1--;
        if(nums1[l1] < nums2[l2]) l2--;
    }
    return res;
};
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
   
    let res = [];
    let l1 = 0;
    let l2 = 0;
    nums1.sort((a, b) => a - b);
    nums2.sort((a, b) => a - b);
    while(l1 < nums1.length && l2 < nums2.length) {
   
        if(nums1[l1] === nums2[l2]) {
   
            res.push(nums1[l1]);
            l1++;
            l2++;
        }
        if(nums1[l1] > nums2[l2]) {
   
            l2++;
        }
        if(nums1[l1] < nums2[l2]) {
   
            l1++;
        }
    }
    return res;
};
1. 两数之和 输入无序数组

map

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
输入: nums = [3,2,4], target = 6
输出: [1,2]
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
   
    let map = {
   };
    for(let i = 0; i < nums.length; i++) {
   
        if(map[nums[i]] !== undefined) {
   
            return [map[nums[i]], i];
        }
        map[target - nums[i]] = i;
    }
};
167. 两数之和 II 输入有序数组

单数组左右对撞指针

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(numbers, target) {
   
    let l = 0;
    let r = numbers.length - 1;
    while(l <= r) {
   
        if(numbers[l] + numbers[r] === target) return [l+1, r+1];
        if(numbers[l] + numbers[r] > target) r--;
        if(numbers[l] + numbers[r] < target) l++;
    }
};
977. 有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

单数组左右对撞指针

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
   
    let res = [];
    let l = 0;
    let r = nums.length -1;
    while(l <= r){
   
        let l_val = nums[l] * nums[l];
        let r_val = nums[r] * nums[r];
        if(l_val <= r_val) {
   
            res.unshift(r_val);
            r--;
        }else{
   
            res.unshift(l_val);
            l++;
        }
    }
    return res;
};
11. 盛最多水的容器

单数组左右对撞指针

给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器。

image.png

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
   
    let l = 0;
    let r = height.length - 1;
    let res = 0;
    while(l < r) {
   
        if(height[l] <= height[r]) {
   
            res = Math.max(height[l] * (r - l), res);
            l++
        } else {
   
            res = Math.max(height[r] * (r - l), res);
            r--
        }
    }
    return res;
};

15. 三数之和

单数组左右对撞指针

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
   
    let res = [];
    nums.sort((a, b) => a - b);
    for(let i = 0; i < nums.length - 2; i++) {
   
        let cur = nums[i];
        if(i - 1 >= 0 && cur === nums[i - 1]) continue;
        let left = i + 1;
        let right = nums.length - 1;
        while(left < right) {
   
            let l = nums[left];
            let r = nums[right];
            if(l + r + cur === 0) {
   
                res.push([cur, l, r]);
                // 跳过左右两边相同的值
                while(left < right && nums[left] === l) left++;
                while(left < right && nums[right] === r) right--;

            }
            if(l + r + cur > 0) right--;
            if(l + r + cur < 0) left++;
        }
    }
    return res;
};
88. 合并两个有序数组

双数组双指针

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
   
    let len = m + n - 1;
    let mLen = m - 1;
    let nLen = n - 1;
    while(mLen >= 0 && nLen >= 0) {
   
        if(nums1[mLen] > nums2[nLen]) {
   
            nums1[len] = nums1[mLen];
            mLen--;
        } else {
   
            nums1[len] = nums2[nLen];
            nLen--;
        }
        len--;
    }
    while(nLen >= 0) {
   
        nums1[len] = nums2[nLen];
        nLen--;
        len--
    }
};
14. 最长公共前缀

使用reduce两两比较。

输入: strs = ["flower","flow","flight"]
输出: "fl"
/**
 * @param {string[]} strs
 * @return {string}
 */
var longestCommonPrefix = function(strs) {
   
    let len = strs.length;
    if(len === 0) return '';
    if(len === 1) return strs[0];
    return strs.reduce(function(a, b) {
   
        let res = '';
        for(let i = 0; i < a.length; i++) {
   
            if(a[i] === b[i]) {
   
                res += a[i];
            } else {
   
                break;
            }
        }
        return res;
    });
};
169. 多数元素

map

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

输入: [3,2,3]
输出: 3
/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {
   
    let count = {
   };
    let mid = nums.length >> 1;
    for(let i = 0; i < nums.length; i++) {
   
        const element = nums[i];
        count[element] ? count[element]++ : count[element] = 1;
        if(count[element] > mid) {
   
            return element;
        }
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值