1.两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
解法一:var twoSum = function (numbers, target) {for (var i = 0; i < numbers.length - 1; i++) {for (var j = i + 1; j < numbers.length; j++) {if (numbers[i] + numbers[j] === target) return [i, j];}}};解法二:var twoSum = function (nums, target) {const map = {};if (Array.isArray(nums)) {for (let i = 0; i < nums.length; i++) {if (map[target - nums[i]] != undefined) {return [map[target - nums[i]], i];} else {map[nums[i]] = i;}}}return [];};
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;
};
