leetcode算法

leetcode算法

每天3道算法题,具体更新在我的博客中https://dfairy.github.io/dfairyblog/

俩数之和

题目

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。

示例 :

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

题目链接:https://leetcode-cn.com/problems/two-sum/

解法一(js)

var twoSum = function(nums, target) {
     
    if(nums.length<2) return false;
    var arr=[]
    for(var i=0;i<nums.length;i++){
     
        for(var j=i+1;j<nums.length;j++){
     
            console.log('i:'+i+',j:'+j);
            if(nums[i]+nums[j]==target){
     
                arr.push(i,j)
            }
        }
    }
    return arr;
};

解法二(js)

var twoSum = function(nums, target){
     
    const map = new Map();
    for(let i=0; i<nums.length; i++){
     
        if (map.has(nums[i])){
     
            return [map.get(nums[i]),i];
        }else{
     
            map.set(target-nums[i],i);
        }
    }
}

整数反转

题目

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

注意:

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2**31, 2 **31 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

示例 :

输入: -123
输出: -321

题目链接:https://leetcode-cn.com/problems/reverse-integer/

解答

var reverse = function(x) {
     
    var arr=Math.abs(x).toString().split('');
    var num=arr.reverse().join('');
    if(x<0){
     
        return num > 2**31 || -num > 2**31-1 ? 0 : -num
    }else{
     
        return num > 2**31-1 || -num > 2**31 ? 0 : num
    }
};

回文数

题目

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例 :

输入: 121
输出: true
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

题目链接:https://leetcode-cn.com/problems/palindrome-number/

解法一

var isPalindrome = function(x) {
     
    if(x<0) return false;
    var arr=x.toString().split('');
    return arr.reverse().join('')==x?true:false;
           
};

解法二

var isPalindrome = function(x) {
     
    if(x<0) return false;
    x=x.toString();
    for(var i=0,len=x.length;i<len/2;i++){
     
        if(x[i]!=x[len-i-1]){
     
            return false
        }
    }
    return true;
};

最长公共前缀

题目

编写一个函数来查找字符串数组中的最长公共前缀,如果不存在公共前缀,返回空字符串 “”。

示例 :

输入: ["flower","flow","flight"]
输出: "fl"
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。

题目链接:https://leetcode-cn.com/problems/longest-common-prefix/

解法一

var longestCommonPrefix = function(strs) {
     
    if (strs === null || strs.length < 1) return "";
    if(strs.length<2) return strs[0];
    let prevs=strs[0];
    for(let i=1;i<strs.length;i++){
     
        let j=0;
        for(;j<prevs.length && j< strs[i].length;j++){
     
            if(prevs[j] != strs[i][j])
            break;
        }
        prevs=prevs.substring(0,j);
        if(prevs === "") return ""
    }
    return prevs;
};

解法二

var longestCommonPrefix = function(strs) {
     
    var result
    if(strs === null || strs.length < 1) return ""
    if(strs.length<2) return strs[0]
    var reg = /^(\w+)([^,]*),(\1[^,]*,)*\1([^,]*)$/
    var m=strs.join(',').match(reg)
    result=m?m[1]:''
    return result
};

有效的括号

题目

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

示例 :

输入: "()[]{}"
输出: true
输入: "([)]"
输出: false

题目链接:https://leetcode-cn.com/problems/valid-parentheses/

解法一

const isValid = function(s){
     
    const stack=[];
    for(let i=0;i<s.length;i++){
     
        if(s[i]=='(' || s[i]=='[' || s[i]=='{'){
     
            stack.push(s[i])
        }else{
     
            if (stack.length == 0) {
                   // 此时栈空,无法匹配
                return false;
            }
            const top=stack[stack.length-1];
            if((top=='(' && s[i]==')')|| (top=='[' && s[i]==']') ||(top=='{' && s[i]=='}')){
     
                stack.pop()
            }else{
     
                return false;
            }
        } 
    }
    console.log(stack);
    return stack.length==0;
};

解法二

const isValid = function(s){
     
    while(s.length){
     
        var temp=s;
            s=s.replace('()','');
            s=s.replace('[]','');
            s=s.replace('{}','');
        if(temp==s) return false;
    }
    return true;
};

删除排序数组中的重复项

题目

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

示例 :

给定数组 nums = [1,1,2], 

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 

你不需要考虑数组中超出新长度后面的元素。

题目链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

解法

var removeDuplicates = function(nums) {
     
    for(let i=0;i<nums.length;i++){
     
        console.log(nums.indexOf(nums[i]));
        if(nums.indexOf(nums[i])!=i){
     
            nums.splice(i,1)
            i=i-1;
        }   
    }
   return nums.length;
};

移除元素

题目

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

示例 :

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

题目链接:https://leetcode-cn.com/problems/remove-element/

解法

  var removeElement = function(nums, val) {
     
      for(let i=0;i<nums.length;i++){
     
          if(nums[i]==val){
     
              nums.splice(i,1);
              i--;
          }
      }
     return nums.length;
};

实现strStr()

题目

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

示例 :

输入: haystack = "hello", needle = "ll"
输出: 2

题目链接:https://leetcode-cn.com/problems/implement-strstr/

解法

var strStr = function(haystack, needle) {
     
    return haystack.indexOf(needle); 
};

搜索插入位置

题目

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

示例 :

输入: [1,3,5,6], 5
输出: 2
输入: [1,3,5,6], 2
输出: 1

题目链接:https://leetcode-cn.com/problems/search-insert-position/

解法

  var searchInsert = function(nums, target) {
     
    for (let j = 0; j < nums.length; j++) {
     
        if (nums[j] >= target) {
     
            return j
        }
    }
    return nums.length
};

最后一个单词的长度

题目

给定一个仅包含大小写字母和空格 ’ ’ 的字符串 s,返回其最后一个单词的长度。如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词。如果不存在最后一个单词,请返回 0 。

示例 :

输入: "Hello World"
输出: 5

题目链接:https://leetcode-cn.com/problems/length-of-last-word/

解法一

var lengthOfLastWord = function(s) {
     
    var str = s.trim().split(" ");//trim()用于删除字符串的头尾空白符。
    return str[str.length - 1].length;
};

解法二

var lengthOfLastWord = function(s) {
     
    let arr=s.split(" ");
    for(let i=0;i<arr.length;i++){
     
        if(arr[i]==""){
     
            arr.splice(i,1)
            i--;
        }
    }
    return arr.length<=0 ? 0:arr[arr.length-1].length;   
};

外观数列

题目

给定一个正整数 n ,输出外观数列的第 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"

示例 :

输入:n = 4
输出:"1211"
解释:
countAndSay(1) = "1"
countAndSay(2) = 读 "1" = 一 个 1 = "11"
countAndSay(3) = 读 "11" = 二 个 1 = "21"
countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"

题目链接:https://leetcode-cn.com/problems/count-and-say/

解法一

 var countAndSay = function(n) {
     
    if(n == 1){
     
        return "1";   
    }
    let newStr="",preStr,index=1,
        str=countAndSay(n-1);//21
        preStr=str[0];
    for(let i=1;i<str.length;i++){
     
        if(preStr == str[i]){
     
            index++;
        }else{
     
            newStr+=index+preStr;
            preStr=str[i];
            index=1;
        }
    }
    return newStr+=index+preStr;
};

解法二

var countAndSay = function(n) {
     
    let reg=/(\d)\1*/g;
    if(n==1) return '1';
    return countAndSay(n-1).match(reg).map(item=>item.length+item[0]).join('');
};

解法三

var countAndSay = function(n) {
     
    let prev = '1'
    for(let i = 1; i < n; i++){
     
        prev = prev.replace(/(\d)\1*/g, item =>`${
       item.length}${
       item[0]}`)
    }
    return prev
};

最大子序和

题目

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和

示例 :

输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

题目链接:https://leetcode-cn.com/problems/maximum-subarray/

解法一

 var maxSubArray = function(nums) {
     
     let sum=0,maxAns=nums[0];
     for(let item of nums){
     
         if(sum>0){
     
             sum+=item
         }else{
     
             sum=item
         }
     }
     return Math.max(sum,maxAns)
};

解法二

var maxSubArray = function(nums) {
     
    let pre=0,maxAns=nums[0]
    nums.forEach(item => {
     
        pre=Math.max(pre+item,item)
        maxAns=Math.max(maxAns,pre)
    });
    return maxAns;
};

加一

题目

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 :

输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。

题目链接:https://leetcode-cn.com/problems/plus-one/

解法

var plusOne = function(digits) {
     
    let len=digits.length;
    for(let i=len-1;i>=0;i--){
     
        digits[i]++;
        digits[i]%=10;
        if(digits[i]!=0){
     
            return digits;
        }
    }
    digits=[...Array(len+1)].map(_=>0);
    digits[0]=1;
    return digits;
};

二进制求和

题目

给你两个二进制字符串,返回它们的和(用二进制表示)。输入为 非空 字符串且只包含数字 1 和 0。

示例 :

输入: a = "1010", b = "1011"
输出: "10101"

题目链接:https://leetcode-cn.com/problems/add-binary/

解法

var addBinary = function(a, b) {
     
    let ca=0,ans='';
    for(let i=a.length-1,j=b.length-1;i>=0 || j>=0;i--,j--){
     
        let sum=ca;
        sum+= i>=0?parseInt(a[i]):0;
        sum+=j>=0?parseInt(b[j]):0;
        ans+=sum%2;
        ca=Math.floor(sum/2)
    }
    ans+=ca=='1'?ca:''
    return ans.split('').reverse().join('')
};

x的平方根

题目

计算并返回 x 的平方根,其中 x 是非负整数。由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 :

输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 
     由于返回类型是整数,小数部分将被舍去。

题目链接:https://leetcode-cn.com/problems/sqrtx/

解法

var mySqrt = function(x) {
     
    if (x<1) {
     
        return 0;
    }
    var find = function ( left, right, x) {
     
        if (right - left <= 1) {
     
            return left;
        }
        mid = Math.floor((left + right) / 2);
        if (mid * mid > x) {
     
            right = mid;
        } else {
     
            left = mid;
        }
        return find( left, right, x);
    }
    return find(1, x, x);
};

合并俩个有序数组

题目

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

示例 :

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3

输出:[1,2,2,3,5,6]

题目链接:https://leetcode-cn.com/problems/merge-sorted-array/

解法

var merge = function(nums1, m, nums2, n) {
     
   let count=m+n;
   while(m>0 && n>0){
     
       nums1[--count]=nums1[m-1]<nums2[n-1]?nums2[--n]:nums1[--m];
   }
   if(n>0){
     
       nums1.splice(0,n,...nums2.slice(0,n))
   }
   return nums1
};

杨辉三角

题目

给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。

示例 :

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

题目链接:https://leetcode-cn.com/problems/pascals-triangle/

解法

var generate = function(numRows) {
     
    if(numRows==0) return [];
    let j=0,res=[];
    while(j<numRows){
     
        let temp=[1];
        for(let i=1;i<j;i++){
     
            let row=res[j-1];
            temp.push(row[i-1]+row[i])
        }
        if(j>0) temp.push(1);
        res.push(temp);
        j++;

    }
    return res;
};

杨辉三角 II

题目

给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。

示例 :

输入: 3
输出: [1,3,3,1]

题目链接:https://leetcode-cn.com/problems/pascals-triangle-ii/

解法

var getRow = function(rowIndex) {
     
    if(rowIndex<0 && k>33) return [];
    let number=rowIndex+1;
    let j=0;res=[];
    while(j<number){
     
        let temp=[1]
        for(let i=1;i<j;i++){
     
            let row=res[j-1];
            temp.push(row[i-1]+row[i])
        }
        if(j>0) temp.push(1)
        res.push(temp);
        j++;
    }
    return res[rowIndex];
};

买卖股票的最佳时期

题目

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。注意:你不能在买入股票前卖出股票。

示例 :

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

题目链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/

解法

var maxProfit = function(prices) {
     
    if (!prices || !prices.length) return 0
    let max=0;
    for(let i=0;i<prices.length;i++){
     
        for(let j=i+1;j<prices.length;j++){
     
            if(prices[j]>prices[i]){
     
                max=Math.max(max,prices[j]-prices[i])
            }
        }
    }
    return max;
};

买卖股票的最佳时期 II

题目

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 :

输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
     因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

题目链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/

解法

var maxProfit = function(prices) {
     
    if (!prices || !prices.length) return 0
    let profit=0;
    for(let i=1;i<prices.length;i++){
     
        const diff=prices[i]-prices[i-1]  // 今天和昨天的差价
        if(diff>0){
       / 差价大于0
            profit+=diff  // 今天卖掉,赚了今天和昨天的差价
        }
       
    }
    return profit;
};

验证回文串

题目

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

示例 :

输入: "A man, a plan, a canal: Panama"
输出: true
输入: "race a car"
输出: false

题目链接:https://leetcode-cn.com/problems/valid-palindrome/

解法

var isPalindrome = function(s) {
     
    let str=s.toLocaleLowerCase().match(/[A-Za-z0-9]+/g); //s = s.replace(/[^a-z0-9]/g,'');
    if(!str) return true;
    let arr=str.join('').split('');
     for(let i=0;i<arr.length;i++){
     
         
         if(arr[i]!=arr[arr.length-i-1]){
     
             return false
         }
         
     }
     return true;
};

快乐数

题目

编写一个算法来判断一个数 n 是不是快乐数。「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。如果 n 是快乐数就返回 True ;不是,则返回 False 。

示例 :

输入:19
输出:true
解释:
1**2 + 9**2 = 82
8**2 + 2**2 = 68
6**2 + 8**2 = 100
1**2 + 0**2 + 0**2 = 1

题目链接:https://leetcode-cn.com/problems/happy-number/

解法

var isHappy = function(n) {
     
    while(n=n.toString().split('').reduce((p,v)=>p+v*v,0)){
     
        if(n==1){
     
            return true
        }else if(n==4){
     
            return false
        }
    }
};

Excel表列名称

题目

给定一个正整数,返回它在 Excel 表中相对应的列名称。

例如:

    1 -> A
    2 -> B
    3 -> C
    ...
    26 -> Z
    27 -> AA
    28 -> AB 
    ...

示例:

输入: 28
输出: "AB"

题目链接:https://leetcode-cn.com/problems/excel-sheet-column-title/

解法

var convertToTitle = function(n) {
     
    const str="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    let result=''
    while(n>0){
     
        n--;
        result=str[n%26]+result;
        n=Math.floor(n/26);
    }
    return result;
   
};

Excel表序列号

题目

给定一个Excel表格中的列名称,返回其相应的列序号。

例如:

    A -> 1
    B -> 2
    C -> 3
    ...
    Z -> 26
    AA -> 27
    AB -> 28 
    ...

示例:

输入: "AB"
输出: 28

示例:

输入: "ZY"
输出: 701

题目链接:https://leetcode-cn.com/problems/meeting-rooms/

解法

var canAttendMeetings = function(intervals) {
     
    intervals=intervals.sort((a,b)=>a[0]-b[0]);
    console.log(intervals);
    for(let i=0;i<intervals.length-1;i++){
     
       if(intervals[i][1]>intervals[i+1][0]){
     
           return false;
       }
    }
    return true;
};

存在重复元素

题目

给定一个整数数组,判断是否存在重复元素。如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。

示例:

输入: [1,2,3,1]
输出: true

示例:

输入: [1,2,3,4]
输出: false

题目链接:https://leetcode-cn.com/problems/contains-duplicate/

解法一(new Set)

var containsDuplicate = function(nums) {
     
    const arr=[...new Set(nums)]
    if(arr.length!=nums.length) return true;
    return false;
};

解法二(indexOf)

var containsDuplicate = function(nums) {
     
    for(let i=0;i<nums.length;i++){
     
        if(nums.indexOf(nums[i])!=i){
     
            return true;
        }
    }
    return false;
};

解法三(sort)

var containsDuplicate = function(nums) {
     
    nums.sort((a,b)=>a-b);
   for(let i=1;i<nums.length;i++){
     
       if(nums[i]==nums[i-1]) return true;
   } 
   return false;    
};

解法四(includes)

var containsDuplicate = function(nums) {
     
    let arr=[];
    for(let i=0;i<nums.length;i++){
     
        if(arr.includes(nums[i])){
     
            return true;
        }else{
     
            arr.push(nums[i])
        }
    }
    return false;
};

解法五(new Map)

var containsDuplicate = function(nums) {
     
  let map=new Map;
  for(let i=0;i<nums.length;i++){
     
      if(map.has(nums[i])){
     
          return true;
      }else{
     
          map.set(nums[i],1)
      }
  }
  return false;
};

解法六(枚举法)

var containsDuplicate = function(nums) {
     
  for(let i=0;i<nums.length-1;i++){
     
     for(let j=i+1;j<nums.length;j++){
     
         if(nums[i]==nums[j])return true;
     }
  }
  return false;
};

存在重复元素 II

题目

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

示例:

输入: nums = [1,2,3,1], k = 3
输出: true

示例:

输入: nums = [1,2,3,1,2,3], k = 2
输出: false

题目链接:https://leetcode-cn.com/problems/contains-duplicate-ii/

解法一(枚举法)

var containsNearbyDuplicate = function(nums,k) {
     
    for(var i = 0; i < nums.length - 1; i++){
     
        for(var j = i + 1; j < nums.length; j++){
     
            if (nums[i] === nums[j]){
     
               if(j-i<=k){
     
                   return true;
               }
            }
        }      
    }
    return false;   
};

解法二(includes)

var containsNearbyDuplicate = function(nums,k) {
     
    let arr=[]
    for(let i=0;i<nums.length;i++){
     
        if(arr.includes(nums[i])){
     
            return true;
        }else{
     
            arr.push(nums[i]);
            if(arr.length>k){
     
                arr.splice(0,1)
            }
        }
    }
    return false;  
};

解法三(set)

var containsNearbyDuplicate = function(nums,k) {
     
    let set=new Set();
    for(let i=0;i<nums.length;i++){
     
        if(set.has(nums[i])){
     
            return true;
        }else{
     
            set.add(nums[i])
            if(set.size>k){
     
                set.delete(nums[i-k])
            }
        }
    }
    return false;
};

解法三(some)

var containsNearbyDuplicate = function(nums,k) {
     
    return nums.some((item,index)=>{
     
       var tempArr=nums.slice(index+1,index+k+1);
        return tempArr.indexOf(item)!=-1?true:false;
    });
};

反转字符串中的单词

题目

给定一个字符串,逐个翻转字符串中的每个单词。

示例:

输入:"the sky is blue"
输出:"blue is sky the"

示例:

输入:"a good   example"
输出:"example good a"
解释:如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

题目链接:https://leetcode-cn.com/problems/reverse-words-in-a-string/

解法

var reverseWords = function(s) {
     
    let arr=s.split(" ");
    for(let i=0;i<arr.length;i++){
     
        if(arr[i]==""){
     
            arr.splice(i,1)
            i--;
        }
    }
    return arr.reverse().join(' ');
};

反转字符串中的单词 II

题目

给定一个字符串,逐个翻转字符串中的每个单词。

示例:

输入: ["t","h","e"," ","s","k","y"," ","i","s"," ","b","l","u","e"]
输出: ["b","l","u","e"," ","i","s"," ","s","k","y"," ","t","h","e"]

题目链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-ii/

解法

var reverseWords = function(s) {
     
    const length=s.length;
    let temp=' ',i=0;
    while(i<length){
     
        if(s[i]!=" "){
      
           temp+=s[i];   
        }else{
     
            s.splice(length,0,...temp)
            temp=" ";
        }
        i++;
    }
    if(temp.length>1){
     
        s.splice(length,0,...temp)
    }
    s.splice(0,length+1);//删除原先的数组
    return s;
};

解法二(先整体反转再挨个反转)

var reverseWords = function(s) {
     
    const length=s.length;
    const reverse=function(s,start,end){
     
        while(start<end){
     
            let temp=s[end];
            s[end]=s[start];
            s[start]=temp;
            start++;
            end--;
        }
    }
    reverse(s,0,length-1);//整体反转
    let start=0,end=0;
    while(end<length){
     
        if(s[end]==" "){
     
            reverse(s,start,end-1)//挨个反转
            start=end+1;
        }
        end++;
    }
    reverse(s,start,end-1)//最后一个单词反转
    return s;
};

反转字符串中的单词 III

题目

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例:

输入:"Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"

题目链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/

解法

var reverseWords = function(s) {
     
    return s.split(' ').map(x=>x.split('').reverse().join('')).join(' ')
};

最短单词距离

题目

给定一个单词列表和两个单词 word1 和 word2,返回列表中这两个单词之间的最短距离。

示例:

输入:words = ["practice", "makes", "perfect", "coding", "makes"], word1 = “coding”, word2 = “practice”
输出: 3

示例:

输入:words = ["practice", "makes", "perfect", "coding", "makes"], word1 = "makes", word2 = "coding"
输出: 1

题目链接:https://leetcode-cn.com/problems/shortest-word-distance/

解法

var shortestDistance = function(words, word1, word2) {
     
    let result=Infinity;
    let word1_index=-1,word2_index=-1;
    for(let i=0;i<words.length;i++){
     
        if(words[i]==word1){
     
            word1_index=i;
        } 
        if(words[i]==word2){
     
            word2_index=i
        }
        if(word1_index!=-1 && word2_index!=-1){
     
            result=Math.min(result,Math.abs(word2_index-word1_index))
        }
    }
    return result;
};

会议室

题目

给定一个会议时间安排的数组 intervals ,每个会议时间都会包括开始和结束的时间 intervals[i] = [starti, endi] ,请你判断一个人是否能够参加这里面的全部会议。

示例:

输入:intervals = [[0,30],[5,10],[15,20]]
输出:false

示例:

输入:intervals = [[7,10],[2,4]]
输出:true

题目链接:https://leetcode-cn.com/problems/meeting-rooms/

解法

var canAttendMeetings = function(intervals) {
     
    intervals=intervals.sort((a,b)=>a[0]-b[0]);
    for(let i=0;i<intervals.length-1;i++){
     
       if(intervals[i][1]>intervals[i+1][0]){
     
           return false;
       }
    }
    return true;
};

各位相加

题目

给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。

示例:

输入: 38
输出: 2 
解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2 是一位数,所以返回 2。

题目链接:https://leetcode-cn.com/problems/add-digits/

解法一

var addDigits = function(num) {
     
    if(num<10){
     
        return num;
    }
    while(num=num.toString().split('').reduce((p,v)=>Number(p)+Number(v),0)){
     
        if(num.toString().length==1){
     
            return num;
        }
    }  
};

解法二

var addDigits = function(num) {
     
    if(num<10){
     
        return num;
    }
    return num%9 ||9;
};

同构字符串

题目

给定两个字符串 s 和 t,判断它们是否是同构的。

如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。

每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。

示例:

输入:s = "egg", t = "add"
输出:true

示例:

输入:s = "foo", t = "bar"
输出:false

题目链接:https://leetcode-cn.com/problems/isomorphic-strings/

解法

var isIsomorphic = function(s, t) {
     
   if(s.length!=t.length) return false;
   for(let i=0;i<s.length;i++){
     
       if(s.indexOf(s[i])!=t.indexOf(t[i])){
     
           return false;
       }
   }
   return true;
};

丑数

题目

编写一个程序判断给定的数是否为丑数。丑数就是只包含质因数 2, 3, 5 的正整数。

示例:

输入: 6
输出: true
解释: 6 = 2 × 3

示例:

输入: 8
输出: true
解释: 8 = 2 × 2 × 2

题目链接:https://leetcode-cn.com/problems/ugly-number/

解法

var isUgly = function(num) {
     
    if(num<1) return false;
    [2,3,5].map(item=>{
     
        while(num%item==0) num=num/item
    })
    return num==1;
};

丢失的数字

题目

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

示例:

输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例:

输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。

题目链接:https://leetcode-cn.com/problems/missing-number/

解法

var missingNumber = function(nums) {
     
    let length=nums.length;
    let arr=[];
    for(let i=0;i<=length;i++){
     
        if(!nums.includes(i)){
     
            arr.push(i)
        }
    }
    return arr;
};

重新排列数组

题目

给你一个数组 nums ,数组中有 2n 个元素,按 [x1,x2,…,xn,y1,y2,…,yn] 的格式排列。请你将数组按 [x1,y1,x2,y2,…,xn,yn] 格式重新排列,返回重排后的数组。

示例:

输入:nums = [2,5,1,3,4,7], n = 3
输出:[2,3,5,4,1,7] 
解释:由于 x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 ,所以答案为 [2,3,5,4,1,7]

题目链接:https://leetcode-cn.com/problems/shuffle-the-array/

解法

var shuffle = function(nums, n) {
     
    let arr=[];
    let num1=nums.splice(0,n)
    for(let i=0;i<n;i++){
     
        arr.push(num1[i],nums[i])
    }
    return arr;
};

宝石与石头

题目

给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。

示例:

输入: J = "aA", S = "aAAbbbb"
输出: 3

题目链接:https://leetcode-cn.com/problems/jewels-and-stones/

解法

var numJewelsInStones = function(jewels, stones) {
     
    let index=0
    for(let i=0;i<stones.length;i++){
     
        if(jewels.indexOf(stones[i])!=-1){
     
            index++
        }
    }
    return index;
};

统计一致字符串的数目

题目

给你一个由不同字符组成的字符串 allowed 和一个字符串数组words。如果一个字符串的每一个字符都在 allowed 中,就称这个字符串是 一致字符串。

示例:

输入:allowed = "ab", words = ["ad","bd","aaab","baa","badab"]
输出:2
解释:字符串 "aaab" 和 "baa" 都是一致字符串,因为它们只包含字符 'a' 和 'b' 。

题目链接:https://leetcode-cn.com/problems/count-the-number-of-consistent-strings/

解法

var countConsistentStrings = function(allowed, words) {
     
    let count=0
   for(let i=0;i<words.length;i++){
     
      words[i].split('').every(item=>allowed.includes(item))==true?count++:count;
   }
   return count;
};

最长连续递增序列

题目

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], …, nums[r - 1], nums[r]] 就是连续递增子序列。

示例:

输入:nums = [1,3,5,4,7]
输出:3
解释:最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。 

题目链接:https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence

解法

var findLengthOfLCIS = function(nums) {
     
    let max=0,start=0;
    for(let i=0;i<nums.length;i++){
     
        if(i>0 && nums[i]<=nums[i-1]){
     
            start=i;
        }
        max=Math.max(max,i-start+1)
    }
    return max;
};

将数字变成0的操作次数

题目

给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。

示例:

输入:num = 14
输出:6
解释:
步骤 1) 14 是偶数,除以 2 得到 7 。
步骤 2) 7 是奇数,减 1 得到 6 。
步骤 3) 6 是偶数,除以 2 得到 3 。
步骤 4) 3 是奇数,减 1 得到 2 。
步骤 5) 2 是偶数,除以 2 得到 1 。
步骤 6) 1 是奇数,减 1 得到 0 。 

题目链接:https://leetcode-cn.com/problems/number-of-steps-to-reduce-a-number-to-zero/

解法

var numberOfSteps  = function(num) {
     
    let index=0;
   while(num!=0){
     
       if(num%2==0){
     
           num=num/2;
           index++;
       }else{
     
           num=num-1;
           index++;
       }
   }
   return index;

};

所有奇数长度子数组的和

题目

给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。子数组 定义为原数组中的一个连续子序列。请你返回 arr 中 所有奇数长度子数组的和 。

示例:

输入:arr = [1,4,2,5,3]
输出:58
解释:所有奇数长度子数组和它们的和为:
[1] = 1
[4] = 4
[2] = 2
[5] = 5
[3] = 3
[1,4,2] = 7
[4,2,5] = 11
[2,5,3] = 10
[1,4,2,5,3] = 15
我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58

题目链接:https://leetcode-cn.com/problems/sum-of-all-odd-length-subarrays/

解法

var sumOddLengthSubarrays = function(arr) {
     
    let sum=0;
    for(let i=0;i<arr.length;i++){
     
        for(let j=i;j<arr.length;j++){
     
            if((j-i+1)%2!=0){
     
                for(let k=i;k<=j;k++){
     
                    sum+=arr[k]
                }
            }
        }
    }
    return sum;
};

转换成小写字母

题目

实现函数 ToLowerCase(),该函数接收一个字符串参数 str,并将该字符串中的大写字母转换成小写字母,之后返回新的字符串。

示例:

输入: "Hello"
输出: "hello"

题目链接:https://leetcode-cn.com/problems/to-lower-case/

解法

var toLowerCase = function(str) {
     
    let s=''
    str.split('').forEach(element => {
     
       if(element.charCodeAt()<=90 && element.charCodeAt()>=65){
     
            s+=String.fromCharCode(element.charCodeAt()+32)
       }else{
     
           s+=element;
       } 
    });
    return s;


      // return str.replace(/[A-Z]/g,c=>String.fromCharCode(c.charCodeAt()+32)) 解法二
};

解码字母到整数映射

题目

给你一个字符串 s,它由数字(‘0’ - ‘9’)和 ‘#’ 组成。我们希望按下述规则将 s 映射为一些小写英文字符:

字符('a' - 'i')分别用('1' - '9')表示。
字符('j' - 'z')分别用('10#' - '26#')表示。
返回映射之后形成的新字符串。

题目数据保证映射始终唯一。

示例:

输入:s = "10#11#12"
输出:"jkab"
解释:"j" -> "10#" , "k" -> "11#" , "a" -> "1" , "b" -> "2".

题目链接:https://leetcode-cn.com/problems/decrypt-string-from-alphabet-to-integer-mapping/

解法

var freqAlphabets = function(s) {
     
    let str=''
    for(let i=0,j;i<s.length;i++){
     
       j=i+2;
       if(s[j]=='#'){
     
           let value=+(s[j-2]+s[j-1])+96
           str+=String.fromCharCode(value)
           i=j;
       }else{
     
           str+=String.fromCharCode(+s[i]+96)
       }
    }
    return str;

    //return s.replace(/(\d{2}(?=#)\#)|(\d{1})/g,item=> String.fromCharCode(parseInt(item)+96)) 第二种解法
};

自除数

题目

自除数 是指可以被它包含的每一位数除尽的数。

例如,128 是一个自除数,因为 128 % 1 == 0,128 % 2 == 0,128 % 8 == 0。

还有,自除数不允许包含 0 。

给定上边界和下边界数字,输出一个列表,列表的元素是边界(含边界)内所有的自除数。

示例:

输入: 
上边界left = 1, 下边界right = 22
输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22]

题目链接:https://leetcode-cn.com/problems/self-dividing-numbers/

解法

var selfDividingNumbers = function(left, right) {
     
    let res=[]
    for(let i=left;i<=right;i++){
     
        if(i.toString().split('').every(item=>i%parseInt(item)==0))res.push(i)
    }
    return res;
};

查找常用字符

题目

给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表。例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 次。

示例:

输入:["bella","label","roller"]
输出:["e","l","l"]

题目链接:https://leetcode-cn.com/problems/find-common-characters/

解法

var commonChars = function(A) {
     
    let arr=[],word=A[0]
    for(let c of word){
     
        if(A.every(item=>item.includes(c))){
     
            A=A.map(m=>m.replace(c,''))
            arr.push(c)
        }
    }
    return arr;
};

无法吃午餐的学生数量

题目

学校的自助午餐提供圆形和方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。
餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮:

如果队列最前面的学生 喜欢 栈顶的三明治,那么会 拿走它 并离开队列。
否则,这名学生会 放弃这个三明治 并回到队列的尾部。
这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。

给你两个整数数组 students 和 sandwiches ,其中 sandwiches[i] 是栈里面第 i​​​​​​ 个三明治的类型(i = 0 是栈的顶部), students[j] 是初始队列里第 j​​​​​​ 名学生对三明治的喜好(j = 0 是队列的最开始位置)。请你返回无法吃午餐的学生数量。

示例:

输入:students = [1,1,0,0], sandwiches = [0,1,0,1]
输出:0 
解释:
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,0,0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,0,1,1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [0,1,1],三明治栈为 sandwiches = [1,0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,1,0]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1,0],三明治栈为 sandwiches = [0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1],三明治栈为 sandwiches = [1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [],三明治栈为 sandwiches = []。
所以所有学生都有三明治吃。


题目链接:https://leetcode-cn.com/problems/number-of-students-unable-to-eat-lunch/

解法

var countStudents = function(students, sandwiches) {
     
    while(students.some(item=>item==sandwiches[0])){
      //关键在于some函数
        if(students[0] === sandwiches[0]){
     
           students.shift()
           sandwiches.shift()
       }else{
     
    // 拿出第一个学生塞到队列最后
          let first = students.shift()
           students.push(first)
       }
    }
    return students.length;
};

独一无二的出现次数

题目

给你一个整数数组 arr,请你帮忙统计数组中每个数的出现次数。如果每个数的出现次数都是独一无二的,就返回 true;否则返回 false。

示例:

输入:arr = [1,2,2,1,1,3]
输出:true
解释:在该数组中,1 出现了 3 次,2 出现了 2 次,3 只出现了 1 次。没有两个数的出现次数相同。

题目链接:https://leetcode-cn.com/problems/unique-number-of-occurrences/

解法一

var uniqueOccurrences = function(arr) {
     
    let obj = {
     };
    for(let item of arr){
     
        obj[item]?obj[item]++:obj[item]=1;
    } 
    let res=Object.keys(obj).map(key=>obj[key]);
    return res.length==[...new Set(res)].length;
};

解法二

var uniqueOccurrences = function(arr) {
     
    let map=new Map();
    for(let item of arr){
     
        if(map.has(item)){
     
            map.set(item,map.get(item)+1)
        }else{
     
            map.set(item,1)
        }
    }
    let set=new Set();
    for(let [key, value] of map){
     
        set.add(value)
    }
    return map.size==set.size;
};

你可能感兴趣的:(leetcode)