1.两数之和

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

  1. 解法一:
  2. var twoSum = function (numbers, target) {
  3. for (var i = 0; i < numbers.length - 1; i++) {
  4. for (var j = i + 1; j < numbers.length; j++) {
  5. if (numbers[i] + numbers[j] === target) return [i, j];
  6. }
  7. }
  8. };
  9. 解法二:
  10. var twoSum = function (nums, target) {
  11. const map = {};
  12. if (Array.isArray(nums)) {
  13. for (let i = 0; i < nums.length; i++) {
  14. if (map[target - nums[i]] != undefined) {
  15. return [map[target - nums[i]], i];
  16. } else {
  17. map[nums[i]] = i;
  18. }
  19. }
  20. }
  21. return [];
  22. };

15. 三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
// Two Pointer
var threeSum = function(nums) {
    var len = nums.length;
    var res=[];
    if(len<2 ) return res;

    nums = nums.sort((a,b) => a-b);

    for(var i =0;i<len-2;i++){
        //去重
        if(i>0 && nums[i]==nums[i-1]) continue

        var low = i+1;
        var high = len - 1;
        var sum = 0 - nums[i];

        while(low < high ){
            if(nums[low]+nums[high]==sum){
                res.push([nums[i],nums[low],nums[high]])
                //去重
                while(low<high && nums[low]==nums[low+1]) low++
                while(low<high && nums[high] == nums[high-1]) high--
                low++;
                high--
            } else if(nums[low]+nums[high] < sum){
                low++;
            } else{
                high--;
            }

        }
    }
    return res;  
};

18.四数之和

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。

示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]
//思路同三数之和
var fourSum = function(nums, target) {
        var len = nums.length;
        var res=[];
        if(len< 4 ) return res;

        nums = nums.sort((a,b) => a-b);

        for(var i=0;i<len-3;i++){
            if(i>0 && nums[i]== nums[i-1]) continue

            for(var j=i+1;j<len-2;j++){
                if(j>i+1 && nums[j]==nums[j-1]) continue

                var low = j+1;
                var high = len-1;
                var sum = target - nums[i] - nums[j];

                while(low<high){
                    if(nums[low]+nums[high] == sum){
                        res.push([nums[i],nums[j],nums[low],nums[high]])
                        while(low<high && nums[low] == nums[low+1]) low++
                        while(low<high && nums[high] == nums[high-1]) high--
                        low++;
                        high--;
                   } else if(nums[low]+nums[high]<sum){
                       low++
                   } else {
                       high--
                   }
                }
            }
        }

    return res
};

217. 给定一个整数数组,判断是否存在重复元素。

如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
输入: [1,2,3,1] 输出: true

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

}

219. 存在重复元素 II

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

示例 1:
输入: nums = [1,2,3,1], k = 3
输出: true
示例 2:
输入: nums = [1,0,1,1], k = 1
输出: true
解法一:
var containsNearbyDuplicate = function(nums, k) {

    for(var i=0;i<nums.length;i++){
        for(var j=i+1;j-i<=k && j<nums.length;j++){
            if(nums[i]===nums[j]){
                return true
            }
        }
    }
    return false       
};
解法二:hash
// hash存 val和索引
// [1,2,3,1]  k=3
//   index   num        hash
//     0     1         {1:0}
//     1     2         {1:0,2:1}
//     2     3         {1:0,2:1,3:2}
//     3     1        map.has(1) && 3-0 <= k
var containsNearbyDuplicate = function(nums, k) {

    if(nums.length == 0 ) return false

    var hash = {};

    for(var i=0;i<nums.length;i++){

        var j = hash[nums[i]]

        if(j!==undefined && i-j<=k){
            return true;
        }

        hash[nums[i]] = i;
    }
    return false   
 };
};

26.删除有序数组重复元素

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

示例 1:
给定数组 nums = [1,1,2], 
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 
你不需要考虑数组中超出新长度后面的元素.
/**
 * @param {number[]} nums
 * @return {number}
 */
//双指针 c指针是返回数组的 i指针从头到尾遍历
//  case [0,0,1,1,1,2,2,3,3,4]
//          c
//            i
//   res [0,1,2,3,4]
var removeDuplicates = function(nums) {
    //如果相等 i++
    if(nums.length == 0) return 0;
    var c=1;
    for(var i=1;i<nums.length;i++){
        if(nums[i] !=nums[i-1]){
            nums[c++] = nums[i]
        }
    }
    return c;
};

80. 删除排序数组中的重复项 II

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

给定 nums = [1,1,1,2,2,3],
函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。
你不需要考虑数组中超出新长度后面的元素。
//  [1,1,1,2,2,3]
//       c
//       i
//  [1,1,2,2,3] 
var removeDuplicates = function(nums) {
    if(nums.length <= 2) return nums.length;

    var c =2;//可以有两个重复元素

    for(var i =2;i<nums.length;i++){
        if(!(nums[c-1] == nums[c-2] && nums[c-1] == nums[i])){
            nums[c++] = nums[i]
        }
    }
    return c
};

88.合并有序数组

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3
输出: [1,2,2,3,5,6]
//三个指针 右->左  ij k
//k指针从nums1 最右侧开始填充
//将较大的数字填充在k位置
var merge = function(nums1, m, nums2, n) {
    var i=m-1, j=n-1, k=m+n-1;


    while(i>=0 && j>=0){
        nums1[k--] = nums1[i]>=nums2[j]?nums1[i--]:nums2[j--]
    }
    //nums2的长度大于nums1
    while(j>=0){
        nums1[k--] = nums2[j--]
    }

};

4.Pow(x,n)

实现 pow(x, n) ,即计算 x 的 n 次幂函数。

示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:
输入: 2.10000, 3
输出: 9.26100
示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25

分治思想:

var myPow = function(x, n) {
    if(n < 0)   {
        return 1/myPow(x, -n);
    }
    if(n === 0) {
        return 1;
    }
    if(n === 1) {
        return x;
    }

    if(n%2 !== 0){
        return x*myPow(x,n-1)
    }

    return myPow(x*x,n/2);


};

169.求众数

给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1:
输入: [3,2,3]
输出: 3
map{x,count_x}
sort
分治
/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {

    var hash={};                         
    var halfNum=nums.length/2;
    if (nums.length===1) return nums[0];
    for (let i=0;i<nums.length;i++){    
       if(hash[nums[i]]){                
           hash[nums[i]]+=1;             

       }else{
           hash[nums[i]]=1;             
       }
    }

    for(let i in hash){
        if(hash[i]>halfNum){
            return i
        }
    }

};

第二种解法:Moore vote
既然有出现次数超过一半的数字,那么我们把没出现一半的数字的次数进行抵消,出现一半以上的数字仍然不会被完全消除掉。
time:O(n)space:O(1)

/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {
    var count = 0;
    var res=0;
    for(var i=0;i<nums.length;i++){
        if(count == 0){
            res = nums[i];
        }
        if(nums[i] != res){
            count --;
        } else {
            count ++;
        }
    }
    return res;

};

229 求众数

给定一个大小为 n 的数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。
说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1)。

示例 1:
输入: [3,2,3]
输出: [3]
示例 2:
输入: [1,1,1,3,3,2,2,2]
输出: [1,2]
解法:Moore vote

数组中出现次数超过⌊ n/3 ⌋次的最多有两个!因为如果3个的话,这三个数字的总次数 > 3×⌊ n/3 ⌋ = n,不可能的。所以我们对这个题的做法同样使用摩尔投票法,先使用两个变量分别保存次数最多和次多。然后我们还需要再遍历一遍数组,判断次数最多和次多的是不是超过了⌊ n/3 ⌋次,把超过的数字返回就行了。

// 未全部通过
var majorityElement = function(nums) {
    var limit =Math.ceil(nums.length/3);

       if(nums.length <=2){
        return Array.from(new Set(nums));
    }

    var res=[];
    var number1=0,number2=0;
    var count1=0,count2=0;
    for(var i=0;i<nums.length;i++){
        if(nums[i] == number1){
            count1++;
        } else if(nums[i] == number2){
            count2++;
        } else if(count1 == 0){
            number1=nums[i];
            count1=1
        } else if(count2 == 0){
            number2=nums[i];
            count1=2
        } else {
            count1--;
            count2--;
        }
    }
    count1=count2=0;

    for(var i=0;i<nums.length;i++){
        if(nums[i]==number1) {
            count1++;
        }else if(nums[i]==number2) {
            count2++;
        }

    }

    if(count1 > limit) res.push(number1);
    if(count2 > limit) res.push(number2);
    return res;


};

187 重复的DNA序列

所有 DNA 由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。
编写一个函数来查找 DNA 分子中所有出现超过一次的10个字母长的序列(子串)。

示例:
输入: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出: ["AAAAACCCCC", "CCCCCAAAAA"]
//该方法超时
/**
 * @param {string} 
 * @return {string[]}
 */
var findRepeatedDnaSequences = function(s) {
    var word_map = {};
    var res = [];

    for(var i=0;i<s.length;i++){

        let word = s.substr(i,10);
        if(word.length<10) continue;

        if(!word_map[word]){
            word_map[word] = 1;
        } else {
            word_map[word] += 1;
        }     
    }


    for (let k in word_map){
        if(word_map[k] > 1){
            res.push(k)
        }
    }
    return res;
};
//位运算

3.无重复的最长字符串

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

示例 1:
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 示例 2:
输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
   /**
     * @param {string} s
     * @return {number}
     */
    //分析
    // 双指针 begin i维护一个窗口,窗口之间的就是无重复的
    // word为begin和i之间的单词 初始word_map={}
    //  begin
    //    |
    //    a b c a b c b b
    //    |
    //    i=0  word='a' max=1   word_map={a:1}
    //  begin
    //    |
    //    a b c a b c b b
    //      |
    //      i=1  word='ab' max=2 word_map={a:1,b:1}
    //  begin
    //    |
    //    a b c a b c b b
    //        |
    //        i=2  word='abc' max=3 word_map={a:1,b:1,c:1}
    //     begin
    //      |
    //    a b c a b c b b  
    //          |
    //          i=3  word='bca' max=3 word_map={a:2,b:1,c:1}
    //  word_map[s[i]]>1 说明word中出现过a,word_map[s[begin]]--标志word中word_map[s[begin]]没有出现
    //  移动begin到a后 并且更新word
    // 以此类推  最终得到 max 为3
var lengthOfLongestSubstring = function(s) {

    if (s.length <= 1)
    return s.length;
    let max = 0;
    let begin = 0;
    let word = '';
    let word_map = new Map();

    for(var i=0;i<s.length;i++){
        if(!word_map[s[i]]){
           word_map[s[i]]=1; 
        } else {
           word_map[s[i]]++;
        }

       if(word_map[s[i]]==1){
           //word中没有出现该字符
           word += s[i];
           // max = Math.max(word.length,max)
           if(max< word.length){
               max = word.length;
           }
       } else {
           //滑动窗口begin,word_map[s[i]]>1表示begin越过了重复的字符 
           while(begin<i && word_map[s[i]]>1){

               word_map[s[begin]] --;
               begin ++;   
           }
           word = '';
           //更新word
           for(let j=begin;j<=i;j++){
               word += s[j];
           }

       }
    }
   return max;  
};
优化解法
 var lengthOfLongestSubstring = function(s) {

    if (s.length <= 1)
     return s.length;

     let max = 1;
     let begin = 0;

     for (let i = 1; i < s.length; i++) {
         let index = s.indexOf(s.charAt(i), begin);  //begin检索的开始位置  每遍历一个i,检查第i个之前的字符串有没有和s[i]相同的;
         if (index < i) {  说明i之前存在和s[i]相同的字符
             beign = index + 1;  begin是和s[i]相同的那个s[index]的下一个.这时候s[begin]和s[i]之间没有重复的字符串
         }
         max = Math.max(max, i-begin+1);
     } 
     return max;   
 };

49 字母异位词分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
/**
 * @param {string[]} strs
 * @return {string[][]}
 */
//分析:
//构建哈希映射,以每个单词的排序为key,排序前单词为value
//     ['eat','tea','tan','ate','nat','bat']
//  'eat' 排序后   ate  ----  eat
//  'tea' 排序后   ate  ----  eat  tea
//  'tan' 排序后   ant  ----  tan
//  'ate' 排序后   ate  ----  eat tea ate
var groupAnagrams = function(strs) {
    var res = [];
    var word_map = new Map;


    for(var i = 0;i<strs.length;i++){

        var str = strs[i].split('').sort().join('');//'eat'---'aet'

        if(!word_map.has(str)){
            word_map.set(str,[strs[i]])
        } else {
            word_map.get(str).push(strs[i])
        }

    }

    for(let [key,value] of word_map){
        res.push(value)
    }
    return res;
};
// var groupAnagrams = function(strs){ 
//     var griddle = [];
//     var result = [];
//     griddle = new Map();
//     result = [];
//     for(var str in strs)
//     {  
//        var key = Array.from(strs[str]).sort().join(); 
//        if (griddle.has(key)){ 
//            griddle.get(key).push(strs[str])  
//        } else {
//            griddle.set(key, [strs[str]]);
//        }
//     }
//     griddle.forEach((e)=>{ result.push(e) });
//     return result;
// }

290 单词模式

给定一种 pattern(模式) 和一个字符串 str ,判断 str 是否遵循相同的模式。
这里的遵循指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应模式。

示例1:
输入: pattern = "abba", str = "dog cat cat dog"
输出: true
示例 2:
输入:pattern = "abba", str = "dog cat cat fish"
输出: false
示例 3:
输入: pattern = "aaaa", str = "dog cat cat dog"
输出: false
示例 4:
输入: pattern = "abba", str = "dog dog dog dog"
输出: false
说明:
你可以假设 pattern 只包含小写字母, str 包含了由单个空格分隔的小写字母。
/**
 * @param {string} pattern
 * @param {string} str
 * @return {boolean}
 */
//设置单词到模式的哈希映射,used[]记录pattern字符使用情况
//拆分单词,
//若单词从未出现在哈希表中
//               1. 该单词对应的pattern已经在used[]中,返回false
//               2. 否则,将对应的pattern记录到used[]中
//若单词出现在哈希表中:如果该单词在哈希表中对应的pattern与当前pattern不等,返回false
//单词个数与pattern个数不等  返回false
//  str            dog      cat     cat     fish
// pattern          a        b       b       a
// 1.     dog->a    used={a:1}  创建word_map={dog:a};
// 2.     cat->b    used={a:1,b:1}  创建word_map={dog:a,cat:b};
// 3.     cat->b    used={a:1,b:1,b:1} 查询word_map={dog:a,cat:b};
// 4.    fish->a    fish对应的a在used中出现过, false
var wordPattern = function(pattern, str) {
    var word_map = {};
    var used = {};
    var strArr = str.split(' ');

    if(pattern.length != strArr.length){
        return false;
    }

    for(var i=0;i<strArr.length;i++){
        if(!word_map[strArr[i]]){//如果当前单词没有出现在哈希表中
            if(used[pattern[i]]){//如果该单词对应的pattern已经使用过
                return false;
            } 
            word_map[strArr[i]] = pattern[i];
            used[pattern[i]] = 1
        } else {
            if(word_map[strArr[i]] != pattern[i]){
                return false
            }
        }

    }
    return true   
};

47.最长回文串

给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 “Aa” 不能当做一个回文字符串。
注意: 假设字符串的长度不会超过 1010。

示例 1:
输入:
"abccccdd"
输出:
7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
//回文串是否有中心点 flag
//遍历每个字符的数量cnt 如果cnt为 偶数 max_length += cnt
//cnt为奇数 max_length += cnt—1 flag = 1
//最长回文串的长度 flag + max_length
// a 1个  max_length = 0 flag = 1;
// d 1个  max_length = 0 flag = 1;
// c 4个  max_length = 4 flag = 1;
// d 2个  max_length = 6 flag = 1;
// max_length + flag = 7;
var longestPalindrome = function(s) {
    var hash_map = {};
    var max_length = 0; //回文串的偶数部门长度
    var flag = 0 ;//回文串中心点

    for(var i=0;i<s.length;i++){
        if(hash_map[s[i]]){
            hash_map[s[i]]++;
        } else {
            hash_map[s[i]] = 1;
        }
    }

    for(var k in hash_map){
        if(hash_map[k] %2){
            max_length += hash_map[k]-1;
            flag = 1;
        } else {
            max_length += hash_map[k];
        }
    }
    return max_length+flag

};

20.判断有效括号

function Stack() {
this.dataStore = [];
this.top = 0;  //记录栈顶位置
}
//压栈操作
Stack.prototype.push = function(element) {
    this.dataStore[this.top++] = element;//压入元素后将top加1
}
//出栈操作
Stack.prototype.pop = function() {
    return this.dataStore[--this.top];//取出元素后将top减1
}
//返回栈顶元素
Stack.prototype.peek = function() {
    return this.dataStore[this.top-1];
}
//返回栈的长度
Stack.prototype.length = function() {
    return this.top;
}
//清空栈
Stack.prototype.clear = function() {
    this.top = 0;
}
var isValid = function(s) {
    var stack = new Stack();
    for(var i = 0; i<s.length; i++){
        //碰到左括号,push右括号
        if(s[i] === "(") {
            stack.push(")");
        } else if(s[i] === "[") {
            stack.push("]");
        } else if(s[i] === "{") {
            stack.push("}");
        } else{
        //不是左括号,判断栈是否为空或栈顶元素是否等当前元素
            if(!stack.top || stack.peek() != s[i]){
                return false
            }else{
                stack.pop()
            }
        } 
    }
    return !stack.top;
};

22. 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,
给出 n = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

解法1:

var add = function(left, right, stack, s) {
    if (left === 0 && right === 0) {
        stack.push(s);
        return;
    }
    if (left === right) {
        add(left - 1, right, stack, s + "(");
    } else if (left === 0) {
        add(left, right - 1, stack, s + ")");
    } else {
        add(left - 1, right, stack, s + "(");
        add(left, right - 1, stack, s + ")");
    }
};
var generateParenthesis = function(n) {
    var stack = [];
    add(n, n, stack, "");
    return stack;
};

解法2:

var ans;
function dfs(s, left, right, n) {
  if (left === n && right === n) {
    ans.push(s);
    return;
  }
  if (left + 1 <= n)
    dfs(s + '(', left + 1, right, n);
  if (right + 1 <= n && right + 1 <= left)
    dfs(s + ')', left, right + 1, n);
}
var generateParenthesis = function(n) {
  ans = [];
  dfs('', 0, 0, n);
  return ans;
}

解法3:

var generateParenthesis = function(n) {
    let res = [];
    function generate(left, right, result){
        if(left == n && right == n){
            res.push(result);
            return;
        }
        if(left < n){
            generate(left + 1, right, result + "(" );
        }
        if(left > right && right < n) generate(left, right + 1, result + ")");
    }
    generate(0, 0, "");
    return res;
};

17.电话号码的字母组合

解法1:

var letterCombinations = function(digits) {
      digits = digits + '';
    let letterList = {
        2: ['a', 'b', 'c'],
        3: ['d', 'e', 'f'],
        4: ['g', 'h', 'i'],
        5: ['j', 'k', 'l'],
        6: ['m', 'n', 'o'],
        7: ['p', 'q', 'r', 's'],
        8: ['t', 'u', 'v'],
        9: ['w', 'x', 'y', 'z']
    };

    let result = [];

    for (var i = 0; i < digits.length; i++) {
        let num = digits[i];
        let letter = letterList[num];
        if (result == "") {
            result = letterList[num];
        } else {

            let list = [];
            for (var j = 0; j < result.length; j++) {
                for (var k = 0; k < letterList[num].length; k++) {
                    list.push(result[j] + letterList[num][k]);
                }
            }

            result = list;
        }
    }

    return result;
    }

解法2:【回溯+递归】

/**
 * @param {string} digits
 * @return {string[]}
 */
var letterCombinations = function(digits) {

    var list = [];
    if(digits.length == 0){
        return list;
    }
    backtracing('',digits,0,list);
    return list;

};
  /*
     *比如输入2,3。对应的是abc,def。回先从a开始,然后flag+1,依次向下遍历def,
     * 然后依次向上返回返回ad,ae,af,并且添加到结果集中,然后再向上返回到i=0的循环
     * 然后i+1,从b开始,再依次向下遍历def,如同a一样,依次返回所有结果,当所有的遍历完之和,返回到letterCombinations中结束。
     */
function backtracing(s,digit,flag,list){
    var  strings = { 2: "abc",3: "def",4: "ghi", 5:"jkl",6: "mno", 7:"pqrs", 8:"tuv",9: "wxyz" };
    if(flag >=digit.length ){ //如果已经遍历完所有输入的数字,说明已经到达底部,需要向上溯源。
        list.push(s);//到达底部说明已经是完整的一个结果,则将此次结果添加到结果集中
        return   //返回,向上回溯
    }
    var chars = strings[digit.charAt(flag) - '0'];
    for(var i=0; i<chars.length;i++){  //遍历一个数字对应的所有字母
        backtracing(s+chars.charAt(i),digit,flag+1,list);  //将当前字符加到s上并将flag+1循环下一个数字的字母
    }

}

解法3:

var ans, tmp;
function dfs(str, idx, digits) {
  if (idx === digits.length) {
    ans.push(str);
    return;
  }
  var num = Number(digits[idx]);
  if (num <= 1)
    dfs(str, idx + 1, digits);
  else {
    for (var i = 0, len = tmp[num].length; i < len; i++)
      dfs(str + tmp[num][i], idx + 1, digits);
  }
}
var letterCombinations = function(digits) {
  if (!digits.length)
    return [];
  tmp = ['', '', 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz'],
  ans = [];
  dfs('', 0, digits);
  return ans;
};