三数之和 -双指针解法

该博客详细介绍了如何使用双指针法解决寻找数组中三数之和的问题。首先通过三重循环的常规解法给出基础思路,然后重点讲解双指针解法,包括简化问题为两数之和,对数组排序,以及利用左右指针在中间遍历找到所有满足条件的序列。博客还总结了双指针问题的三种常见思想:左右指针、快慢指针和后序指针,并给出了具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

三数之和 --双指针解法

题目:

在这里插入图片描述

一般解法

三重循坏,分别取三个数,查看和是否为0即可,是就加入集合,不是进入下次迭代。

双指针解法

思路:
  • 本题是解决集合内三数之和的问题,可以将问题简化为求两数之和的问题。只需要在第一次循环确定第一个数,二三次循环的数的和为总和减去第一个数即可。由于结果不唯一,且不能重复,我们可以先对数组进行排序,再用双指针操作数组得到所有和为目标值的序列。

  • 解决双指针问题三种常用思想:

    1. 左右指针:需要两个指针,一个指向开头,一个指向末尾,然后向中间遍历,直到满足条件或者两个指针相遇
    2. 快慢指针:需要两个指针,开始都指向开头,根据条件不同,快指针走得快,慢指针走的慢,直到满足条件或者快指针走到结尾
    3. 后序指针:常规指针操作是从前向后便利,对于合并和替换类型题,防止之前的数据被覆盖,双指针需从后向前便利
    4. 记忆口诀:左右指针中间夹,快慢指针走到头,后序指针往回走
    • 这里使用的是左右指针
  • 实现代码:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        qsort(nums, 0, nums.length-1);    //为了防止重复结果,故对初始数组进行了排序
        List<List<Integer>> ret = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        for(int i=0;i<nums.length-2;i++){
            if(nums[0] > 0)  //最小的都为正数,加起来一定没结果,排除
                break;
            if(i!=0 && nums[i] == nums[i-1])  //对相同的多个数,只用处理第一个就可以了,其余可以略过
                continue;
            List<List<Integer>> twoSumList = twoSum(nums, i+1, -1*nums[i]);  //在余下的数组中查找是否有和为-nums[i]的两个数,返回结果列表
            for(List<Integer> alist:twoSumList){ //将两数之和计算得到的列表的数据加入到三数之和结果表中
                ret.add(new ArrayList<>(Arrays.asList(nums[i], nums[alist.get(0)], nums[alist.get(1)])));
            }
        }

        return ret;
    }
	/**
	*求一个数组后半段指定区域和为target的两个数的序列
	*
	*/
    public List<List<Integer>> twoSum(int[] nums, int left, int target){
        int i=left;
        int j=nums.length-1;
        List<List<Integer>> ret = new ArrayList<>();
        while(i<j){   //当左右指针相遇时返回,反之没有相遇时一直循环
            if(nums[i]+nums[j] == target){  //如果找到了和为target的两个数
                ret.add(new ArrayList<>(Arrays.asList(i, j)));
                //找到数后,不管怎么样都要先至少指针移动一下
                i++;  	//左指针右移
                j--;	//右指针左移
                while(i<j && nums[i] == nums[i-1]){ //去重
                    i++;
                }
                while(i<j && nums[j] == nums[j+1]){	//去重
                    j--;
                }
            }else if(nums[i]+nums[j] < target){	//和小于target,左指针右移
                i++;
            }else{	//和大于target,右指针左移
                j--;
            }
        }
        return ret;
    }
	
	//快速排序
    public void qsort(int[] nums, int low, int high){
        if(low>=high)
            return;
        int key=nums[low];
        int i=low;
        int j=high+1;
        while(true){
            while(nums[++i] < key){
                if(i==high)
                    break;
            }
            while(nums[--j] > key){
                if(j==low)
                    break;
            }
            if(i>=j)
                break;
            int tmp = nums[j];
            nums[j] = nums[i];
            nums[i] = tmp;
        }

        int tmp = nums[j];
        nums[j] = key;
        nums[low] = tmp;

        qsort(nums, low, j-1);
        qsort(nums, j+1, high);
    }
}
《餐馆点餐管理系统——基于Java和MySQL的课程设计解析》 在信息技术日益发达的今天,餐饮行业的数字化管理已经成为一种趋势。本次课程设计的主题是“餐馆点餐管理系统”,它结合了编程语言Java和数据库管理系统MySQL,旨在帮助初学者理解如何构建一个实际的、具有基本功能的餐饮管理软件。下面,我们将深入探讨这个系统的实现细节及其所涉及的关键知识点。 我们要关注的是数据库设计。在“res_db.sql”文件中,我们可以看到数据库的结构,可能包括菜品表、订单表、顾客信息表等。在MySQL中,我们需要创建这些表格并定义相应的字段,如菜品ID、名称、价格、库存等。此外,还要设置主键、外键来保证数据的一致性和完整性。例如,菜品ID作为主键,确保每个菜品的唯一性;订单表中的顾客ID和菜品ID则作为外键,与顾客信息表和菜品表关联,形成数据间的联系。 接下来,我们来看Java部分。在这个系统中,Java主要负责前端界面的展示和后端逻辑的处理。使用Java Swing或JavaFX库可以创建用户友好的图形用户界面(GUI),让顾客能够方便地浏览菜单、下单。同时,Java还负责与MySQL数据库进行交互,通过JDBC(Java Database Connectivity)API实现数据的增删查改操作。在程序中,我们需要编写SQL语句,比如INSERT用于添加新的菜品信息,SELECT用于查询所有菜品,UPDATE用于更新菜品的价格,DELETE用于删除不再提供的菜品。 在系统设计中,我们还需要考虑一些关键功能的实现。例如,“新增菜品和价格”的功能,需要用户输入菜品信息,然后通过Java程序将这些信息存储到数据库中。在显示所有菜品的功能上,程序需要从数据库获取所有菜品数据,然后在界面上动态生成列表或者表格展示。同时,为了提高用户体验,可能还需要实现搜索和排序功能,允许用户根据菜品名称或价格进行筛选。 另外,安全性也是系统设计的重要一环。在连接数据库时,要避免SQL注入攻击,可以通过预编译的PreparedStatement对象来执行SQL命令。对于用户输入的数据,需要进行验证和过滤,防止非法字符和异常值。 这个“餐馆点餐管理系统”项目涵盖了Java编程、数据库设计与管理、用户界面设计等多个方面,是一个很好的学习实践平台。通过这个项目,初学者不仅可以提升编程技能,还能对数据库管理和软件工程有更深入的理解。在实际开发过程中,还会遇到调试、测试、优化等挑战,这些都是成长为专业开发者不可或缺的经验积累
在ARM架构上遇到"ImportError: libpython3.7m.so.1.0"的错误,通常是因为缺少或者无法找到对应的Python库文件。该错误的解决方法如下: 1. 检查Python库文件路径:首先,确保你的系统中已经正确安装了Python3.7版本,并且库文件"libpython3.7m.so.1.0"位于正确的库文件路径下。可以通过以下命令查看库文件路径:`ldconfig -p | grep libpython3.7m.so.1.0`。如果未找到该文件,那么可能是因为Python3.7版本缺失或者安装路径不正确。 2. 更新LD_LIBRARY_PATH:如果库文件路径不正确,可以尝试更新系统的LD_LIBRARY_PATH环境变量,将正确的库文件路径添加到其中。可以使用以下命令进行修改:`export LD_LIBRARY_PATH=/path/to/python3.7/libs:$LD_LIBRARY_PATH`。其中,"/path/to/python3.7/libs"是Python3.7库文件的路径。 3. 检查依赖库:除了检查Python库文件,还需要确保该错误不是由于其他依赖库缺失所致。使用`ldd /path/to/your/arm/bin`命令来检查可执行文件所依赖的库文件,确保所有的依赖库都存在且路径正确。 4. 重新编译或安装:如果上述方法仍无法解决问题,可以尝试重新编译或安装相关软件或库。特别是在使用交叉编译时,需要确保交叉编译环境正确配置。 总之,"ImportError: libpython3.7m.so.1.0"错误通常是由于ARM架构下的Python库文件缺失或路径不正确所导致的。根据具体情况,可以通过检查库文件路径、更新LD_LIBRARY_PATH、检查依赖库以及重新编译或安装软件来解决该问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值