LeetCode 17电话号码的字母组合(搜索)&18四数之和

简介: 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

电话号码的字母组合



题目描述


给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。


示例:

输入:“23”

输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].


说明:

尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。


这种问题,明显就是搜索类的问题。你可以使用广度优先搜索bfs,借助一个队列储存字符串进行操作,也可以使用深度优先搜素。


在这里就用深度优先搜索,而使用dfs时候我们通常借助递归来实现,而递归又是一个回溯的过程,你可以每次创建新的字符串但是也可以使用StringBuilder进行重复使用。对于电话号码,你需要预储存,可以使用HashMap也可以使用List []数组完成。


具体代码为:


 List<String>value=new ArrayList<String>();
   String digitString;
   List<Character> list[];
  public  List<String> letterCombinations(String digits) {
    if(digits==null||"".equals(digits))return value;
    digitString=digits;
    list=new ArrayList[8];
    //初始化
    for(int i=0;i<list.length;i++)
    {
      list[i]=new ArrayList<Character>();
    }
    for(int i=0;i<5;i++)
    {
          for(int j=0;j<3;j++)
          {
            list[i].add((char) ('a'+i*3+j));
          }
    }
    list[5].add('p');list[5].add('q');list[5].add('r');list[5].add('s');
    list[6].add('t');list[6].add('u');list[6].add('v');
    list[7].add('w');list[7].add('x');list[7].add('y');list[7].add('z');
    dfs(new StringBuilder(""),0);
//    for(List<Character> a:list)//打印测试
//    {
//      System.out.println(a.toString());
//    }
    return value;
    }
  private  void dfs(StringBuilder stringBuilder, int index) {
    if(index==digitString.length()) 
    {value.add(stringBuilder.toString());return;}
    int va=digitString.charAt(index)-'2';
    for(int i=0;i<list[va].size();i++)
    {
      dfs(stringBuilder.append(list[va].get(i)), index+1);
      stringBuilder.deleteCharAt(index);
    } 
  }

20200901212332296.png


四数之和


描述

给定一个包含 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]

]


分析,前面我们做过三数之和。这里四数之和也采用比较相似的方法。

三数之和固定循环一层i,然后left和right从右侧向中间双指针试探


2020090121370362.png


分析


四个数之和可以转换为三数之和。a+b+c+d=targeta+b+c=target-d

在具体实现上,先排序,只需要i,j遍历然后用left,right双指针试探。双指针可以减少一层循环,使得最终复杂度为O(n3);


20200901213844136.png


具体实现上还需要考虑相同去重等细节:


  • nums[i]==nums[i-1]时候跳过,因为该数字作过最左侧。
  • nums[j]==nums[j-1]跳过,因为该数字作过第二个数字。
  • nums[i]+nums[j]+nums[left]+nums[right]==target时候left要向右到和右侧不同为止,right向左到左侧不同为止(去掉相同情况)。
  • 剪枝优化,开始时候过滤一些不可能情况直接返回结果减少计算


其他细节详细看代码。ac代码为:


public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
     List<List<Integer>> list = new ArrayList<List<Integer>>();
     if(nums.length<4)return list;
     if(nums[nums.length-1]+nums[nums.length-2]+nums[nums.length-3]+nums[nums.length-4]<target)return list; 
     for(int i=0;i<nums.length-3;i++)
     {
       if(i>0&&nums[i]==nums[i-1]) {continue;}//去重,这种情况不需要
       if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target) return list;//过滤不可能满足的
       for(int j=i+1;j<nums.length-2;j++)
       {
         if(j>i+1&&nums[j]==nums[j-1]) {continue;}//去重,这种情况不需要
         if(nums[i]+nums[j]+nums[j+1]+nums[j+2]>target)break;//过滤不可能满足的
         int left=j+1; int right=nums.length-1;
         while (left<right) { 
          int sum=nums[i]+nums[j]+nums[left]+nums[right];
          if(nums[i]+nums[j]+nums[left]+nums[left+1]>target)break;
          if(sum==target)
          {
            while (left<nums.length-1&&nums[left]==nums[left+1]) {left++;}
            while (right>0&&nums[right]==nums[right-1]) {right--;}
            List<Integer>list2=new ArrayList<Integer>();
            list2.add(nums[i]);list2.add(nums[j]);
            list2.add(nums[left]);list2.add(nums[right]);
            list.add(list2);
          }
          if(left>right)break;
          if(sum>target)
          {
            right--;
          }
          else {
            left++;
          }         
        }
       }
     }
     return list;
    }

20200901214638292.png


至于其他方法和优化欢迎分享


结语



原创不易,bigsai请你帮两件事帮忙一下:

  1. star支持一下, 您的肯定是我在平台创作的源源动力。
  2. 微信搜索「bigsai」,关注我的公众号,不仅免费送你电子书,我还会第一时间在公众号分享知识技术。加我还可拉你进力扣打卡群一起打卡LeetCode。


记得关注、咱们下次再见!

目录
相关文章
|
3月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
4月前
|
存储 算法
LeetCode第49题字母异位词分组
LeetCode第49题"字母异位词分组"的解题方法,通过将每个字符串的字符排序后作为键存储在HashMap中,有效地将所有字母异位词分组。
LeetCode第49题字母异位词分组
|
2月前
|
算法 索引
LeetCode(搜索插入位置)
如何使用二分查找算法来解决LeetCode上的“搜索插入位置”问题,确保时间复杂度为O(log n),并提供了详细的代码实现和分析。
16 2
|
2月前
|
存储
Leetcode第49题(字母异位词分组)
LeetCode第49题要求将字符串数组中的字母异位词分组,可以通过将每个字符串排序后作为键存入哈希表,最后将哈希表中的值添加到结果列表中来实现。
17 1
|
2月前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
24 0
Leetcode第三十三题(搜索旋转排序数组)
|
2月前
|
算法
Leetcode第十七题(电话号码的字母组合)
这篇文章介绍了如何使用深度优先搜索(DFS)算法来解决LeetCode第17题——电话号码的字母组合问题,通过递归方法生成所有可能的字母组合。
23 0
Leetcode第十七题(电话号码的字母组合)
|
2月前
|
索引
【LeetCode 11】242.有效的字母异位词
【LeetCode 11】242.有效的字母异位词
19 0
【LeetCode 11】242.有效的字母异位词
|
2月前
|
算法
【LeetCode 52】17.电话号码的字母组合
【LeetCode 52】17.电话号码的字母组合
42 0
|
2月前
【LeetCode 39】700.二叉搜索树中的搜索
【LeetCode 39】700.二叉搜索树中的搜索
16 0
|
4月前
|
算法
LeetCode第81题搜索旋转排序数组 II
文章讲解了LeetCode第81题"搜索旋转排序数组 II"的解法,通过二分查找算法并加入去重逻辑来解决在旋转且含有重复元素的数组中搜索特定值的问题。
LeetCode第81题搜索旋转排序数组 II