力扣大厂热门面试算法题 15-17

news2024/12/28 21:11:09

        15. 三数之和,16. 最接近的三数之和,17. 电话号码的字母组合,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.11 可通过leetcode所有测试用例。

目录

15. 三数之和

解题思路

完整代码

Java

Python

​编辑

16. 最接近的三数之和

解题思路

完整代码

Java

Python

17. 电话号码的字母组合

解题思路

完整代码

Java

Python


15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

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

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
 

解题思路

        为了找到所有和为0且不重复的三元组,我们可以使用双指针法。这个方法涉及到先对数组进行排序,然后遍历数组,对于每个元素,使用两个指针分别指向元素之后的开始位置和数组的末尾,向中间移动两个指针来找到和为0的三元组。这里有几个关键点需要注意:

  1. 排序:先对数组进行排序,这样可以方便地跳过重复的元素。
  2. 遍历:从数组的开始遍历到倒数第三个元素(因为我们需要的是三元组)。
  3. 双指针:对于每个遍历到的元素,将一个指针指向遍历元素的下一个位置,另一个指针指向数组的末尾。根据这两个指针指向的元素之和与当前遍历到的元素之和来移动指针。
  4. 跳过重复元素:在遍历过程中,如果遇到重复的元素,需要跳过,以避免重复的三元组。

完整代码

Java
public class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);  // 排序
        List<List<Integer>> res = new ArrayList<>();
        for (int i = 0; i < nums.length - 2; i++) {  // 遍历到倒数第三个元素
            if (i > 0 && nums[i] == nums[i - 1]) {  // 跳过重复元素
                continue;
            }
            int l = i + 1, r = nums.length - 1;
            while (l < r) {
                int sum = nums[i] + nums[l] + nums[r];
                if (sum < 0) {
                    l++;
                } else if (sum > 0) {
                    r--;
                } else {
                    res.add(Arrays.asList(nums[i], nums[l], nums[r]));
                    while (l < r && nums[l] == nums[l + 1]) l++;  // 跳过重复元素
                    while (l < r && nums[r] == nums[r - 1]) r--;  // 跳过重复元素
                    l++;
                    r--;
                }
            }
        }
        return res;
    }
}
Python
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()  # 排序
        result = []
        for i in range(len(nums)-2):  # 遍历到倒数第三个元素
            if i > 0 and nums[i] == nums[i-1]:  # 跳过重复元素
                continue
            l, r = i+1, len(nums)-1  # 双指针
            while l < r:
                s = nums[i] + nums[l] + nums[r]
                if s < 0:
                    l += 1
                elif s > 0:
                    r -= 1
                else:
                    result.append([nums[i], nums[l], nums[r]])
                    while l < r and nums[l] == nums[l+1]:  # 跳过重复元素
                        l += 1
                    while l < r and nums[r] == nums[r-1]:  # 跳过重复元素
                        r -= 1
                    l += 1; r -= 1
        return result

16. 最接近的三数之和

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

示例 1:

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:

输入:nums = [0,0,0], target = 1
输出:0
 

提示:

3 <= nums.length <= 1000
-1000 <= nums[i] <= 1000

解题思路

        为了找到和与目标值 target 最接近的三个整数的和,我们可以使用一种类似于解决“三数之和”问题的方法,即使用双指针法。基本思路如下:

  1. 排序:首先,对数组 nums 进行排序,这有助于使用双指针法。

  2. 初始化最接近的和:用一个变量记录当前找到的与 target 最接近的和,初始时可以设为第一个元素、第二个元素和最后一个元素的和,或者设置为一个较大的数。

  3. 遍历:遍历数组,对于每个元素 nums[i],使用两个指针分别指向 i 之后的元素和数组的最后一个元素。基于当前三元组的和与 target 的差距,移动指针。

  4. 移动双指针:如果三元组的和大于 target,为了使和更接近 target,应该减小和,因此将右指针左移。如果三元组的和小于 target,为了使和更接近 target,应该增加和,因此将左指针右移。

  5. 更新最接近的和:在每一步中,如果找到了更接近 target 的和,则更新记录的最接近的和。

  6. 返回结果:遍历结束后,记录的最接近的和即为所求。

完整代码

Java
public class Solution {
    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int closestSum = nums[0] + nums[1] + nums[nums.length - 1];  // 初始化最接近的和
        for (int i = 0; i < nums.length - 2; i++) {
            int l = i + 1, r = nums.length - 1;
            while (l < r) {
                int currentSum = nums[i] + nums[l] + nums[r];
                if (currentSum == target) {  // 如果等于target,直接返回
                    return currentSum;
                }
                
                // 更新最接近的和
                if (Math.abs(currentSum - target) < Math.abs(closestSum - target)) {
                    closestSum = currentSum;
                }
                
                // 根据和与target的比较,移动双指针
                if (currentSum < target) {
                    l++;
                } else {
                    r--;
                }
            }
        }
        return closestSum;
    }
}
Python
class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        closest_sum = sum(nums[:3])  # 初始化最接近的和
        for i in range(len(nums) - 2):
            l, r = i + 1, len(nums) - 1
            while l < r:
                current_sum = nums[i] + nums[l] + nums[r]
                if current_sum == target:  # 如果等于target,直接返回
                    return current_sum
                
                # 更新最接近的和
                if abs(current_sum - target) < abs(closest_sum - target):
                    closest_sum = current_sum
                    
                # 根据和与target的比较,移动双指针
                if current_sum < target:
                    l += 1
                else:
                    r -= 1
        return closest_sum

17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

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

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字。

解题思路

        可以使用回溯法。回溯法是一种通过探索所有可能的候选解来找出所有的解的算法。如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化来丢弃该解,即回溯并尝试另一个可能的解。

        具体到这个问题,可以将每个数字对应到其可以代表的所有字母,然后通过回溯遍历这些字母的所有可能组合。

  1. 创建一个映射表,将每个数字映射到相应的字母。
  2. 创建一个函数来实现回溯机制,该函数将接受当前组合的字符串和接下来处理的数字字符串。
  3. 从输入字符串的第一个数字开始,将其映射到对应的所有字母,并对每个字母,添加到当前的组合字符串中,并进行下一轮回溯,即再处理下一个数字。
  4. 如果数字字符串为空,表示所有的数字都已处理完毕,此时的组合字符串为一个完整的解,将其添加到答案列表中。
  5. 重复步骤3和4,直到遍历完所有的数字,找出所有可能的字母组合。

完整代码

Java
public class Solution {
    public List<String> letterCombinations(String digits) {
        List<String> combinations = new ArrayList<>();
        if (digits == null || digits.length() == 0) {
            return combinations;
        }
        
        String[] phoneMap = {
            "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"
        };

        backtrack(combinations, phoneMap, digits, 0, new StringBuilder());
        return combinations;
    }

    public void backtrack(List<String> combinations, String[] phoneMap, String digits, int index, StringBuilder path) {
        if (index == digits.length()) {
            combinations.add(path.toString());
            return;
        }
        
        String possibleLetters = phoneMap[digits.charAt(index) - '0'];
        for (char letter : possibleLetters.toCharArray()) {
            path.append(letter);
            backtrack(combinations, phoneMap, digits, index + 1, path);
            path.deleteCharAt(path.length() - 1); // 回溯
        }
    }
}
Python
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits:
            return []

        phoneMap = {
            "2": "abc", "3": "def", "4": "ghi", "5": "jkl",
            "6": "mno", "7": "pqrs", "8": "tuv", "9": "wxyz"
        }

        def backtrack(index, path):
            # 如果路径长度与输入数字长度相同,将其添加到结果中
            if len(path) == len(digits):
                combinations.append("".join(path))
                return
            
            # 获取当前数字对应的所有可能的字母
            possible_letters = phoneMap[digits[index]]
            for letter in possible_letters:
                # 添加当前字母到路径中,并进入下一层回溯
                path.append(letter)
                backtrack(index + 1, path)
                path.pop()  # 回溯,移除路径最后一个字母

        combinations = []
        backtrack(0, [])
        return combinations

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1509004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解锁App推广新姿势:Xinstall专属二维码,让推广更高效!

在移动互联网时代&#xff0c;App推广的重要性不言而喻。然而&#xff0c;推广的过程中往往伴随着各种痛点&#xff0c;如何准确追踪用户来源、如何提高安装转化率等&#xff0c;一直是广告主和开发者们关注的焦点。今天&#xff0c;我们要为大家介绍一款专业的App全渠道统计服…

Java基于SpringBoot+Vue的人事管理系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Linux——文件缓冲区与模拟实现stdio.h

前言 我们学习了系统层面上的文件操作&#xff0c;也明白了重定向的基本原理&#xff0c;在重定向中&#xff0c;我们使用fflush(stdout)刷新了缓冲区&#xff0c;当时我们仅仅知道重定向需要刷新缓冲区&#xff0c;但是不知道其所以然&#xff0c;今天我们来见识一下。 一、…

vue自定义主题皮肤方案

方案一&#xff1a;CSS变量换肤&#xff08;推荐&#xff09; 利用css定义变量的方法&#xff0c;用var在全局定义颜色变量&#xff08;需将变量提升到全局即伪类选择器 :root&#xff09;然后利用js操作css变量&#xff0c;document.getElementsByTagName(‘body’)[0].style…

nodejs版本过高导致vue-cli项目无法正常运行解决方案

95% emitting CompressionPlugin ERROR Error: error:0308010C:digital envelope routines::unsupported 方法一&#xff1a;在使用 npm run dev之前使用 set NODE_OPTIONS--openssl-legacy-provider Error: error:0308010C:digital envelope routines::unsupported 解决方法…

UI自动化、性能、API测试一体平台:RunnerGo

UI自动化测试已经成为现代软件开发过程中不可或缺的一部分。它能够提供诸多优势&#xff0c;包括提高测试效率、减少人力成本、提升软件质量等。同时&#xff0c;可视化工具为UI自动化测试带来了更多便利和灵活性。RunnerGo近期上线脚本录制器&#xff0c;根据你的测试操作直接…

【基础计算机网络2】物理层——通信基础

【前言回顾】 【考纲内容】 一、物理层的基本概念 1.1 物理层的主要任务 物理层解决如何在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的传输媒介。物理层的主要任务&#xff1a;确定与传输媒体接口有关的一些特性。 1.2 物理层的一些特性 机械特性…

前端报错404,nginx正常、gateway没有转发请求

问题描述&#xff1a;前端报错 404 Not Found 原因&#xff1a;nacos中对应服务没有上线&#xff0c;下线后&#xff0c;可以启动本地服务&#xff0c;然后在测试上调试代码。&#xff01;&#xff01; 记住重启对应服务&#xff0c;也不会自动上线。

STM32CubeMX 配置 STM32F103 工程:通过DAC输出正弦波

说明&#xff1a;STM32CubeMX 配置 STM32F103 工程&#xff0c;通过DAC输出正弦波&#xff0c;参考代码可自动计算频率&#xff0c;自动计算正弦数据。 先参考这篇文章配置时钟、工程输出的设置&#xff1a; STM32CubeMX 配置 STM32F103 工程&#xff1a;通过DAC生成三角波、…

基于PLC的城市智能交通灯三路口控制系统设计26.06

摘要 可编程控制器(Programmable Logic Controller)简称PLC。是一种综合了通讯、自动控制和计算机技术发展而来的主要用于工业生产的自动控制系统。PLC运用数字运算操作系统&#xff0c;采用可编程序存储器&#xff0c;来于储存内部程序。执行逻辑运算、定时控制、顺序控制、计…

Elastic Stack--08--SpringData框架

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 SpringData[官网&#xff1a; https://spring.io/projects/spring-data](https://spring.io/projects/spring-data) Spring Data Elasticsearch 介绍 1.SpringData-…

Python速度大比拼:与主流编程语言的速度对决

在评估用于具体业务的编程语言时&#xff0c;经常考虑的一个关键指标之一是执行速度。Python以其简单性和可读性而闻名&#xff0c;但有时却因其性能而受到质疑。在这个领域&#xff0c;我们需要深入比较分析Python在执行速度方面与其他流行的编程语言相比的情况。 程语言执行速…

lucky-canvas实现老虎机、九宫格和大转盘抽奖

lucky-canvas是一款开源免费的基于 jscanvas 的前端插件&#xff0c;UI精美&#xff0c;功能强大&#xff0c;使用起来比较方便。 lucky-canvas官网https://100px.net/ 一、使用 注意&#xff1a;下例是vue中的应用&#xff0c;具体还有js和uniapp中的应用&#xff0c;详细查…

pandas plot函数:数据可视化的快捷通道

一般来说&#xff0c;我们先用pandas分析数据&#xff0c;然后用matplotlib之类的可视化库来显示分析结果。而pandas库中有一个强大的工具--plot函数&#xff0c;可以使数据可视化变得简单而高效。 1. plot 函数简介 plot函数是pandas中用于数据可视化的一个重要工具&#xff0…

2.ElasticSearch 高级查询语法Query DSL实战

1. ES高级查询Query DSL ES中提供了一种强大的检索数据方式,这种检索方式称之为Query DSL&#xff08;Domain Specified Language 领域专用语言&#xff09; , Query DSL是利用Rest API传递JSON格式的请求体(RequestBody)数据与ES进行交互&#xff0c;这种方式的丰富查询语法让…

药业“钉”上云端:与钉钉共舞数字化新时代

在信息化、智能化的时代背景下&#xff0c;药业行业的经营管理面临着巨大的机遇与挑战。一家药业公司经营范围广泛&#xff0c;拥有各种传统药物配方&#xff0c;同时现代化的新物流线和ERP系统支持公司能够更好的运营。该药业公司与无雀科技商谈后&#xff0c;决定与钉钉平台合…

<Linux> 初识线程

目录 前言&#xff1a; 一、什么是线程 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;线程理解 &#xff08;三&#xff09;线程与进程的关系 &#xff08;四&#xff09;简单实用线程 &#xff08;五&#xff09;重谈虚拟地址空间 1. 页表的大小 2…

信息安全、网络安全以及数据安全三者之间的区别

随着信息技术的飞速发展&#xff0c;网络安全、信息安全、数据安全等词汇在平时出现的频率越来越高&#xff0c;尤其是数据安全&#xff0c;是大家都关心的一个重要话题。事实上&#xff0c;有很多人对网络安全、信息安全、数据安全的概念是区分不清的&#xff0c;下面由我帮大…

Yolov8-pose关键点检测:特征融合涨点篇 | 广义高效层聚合网络(GELAN) | YOLOv9

💡💡💡本文独家改进:即结合用梯度路径规划(CSPNet)和(ELAN)设计了一种广义的高效层聚合网络(GELAN),高效结合YOLOv8-pose,实现涨点。 将GELAN添加在backbone和head处,提供多个yaml改进方法 Yolov8-Pose关键点检测专栏介绍:https://blog.csdn.net/m0_6377421…

二维数组的传递和返回

指针和二维数组 指针存储的是内存单元的地址&#xff0c;当使用引用运算符 *&#xff0c;或者变址运算符 [ ] 时才能将指针所指向的内存单元中的值取出。 指针有两个关键属性&#xff1a; 1.它存储的是内存地址 2.它存储的是什么类型变量的内存地址&#xff0c;这一点非常…