`

前后指针的妙用之3 SUM

 
阅读更多

题目意思 :

   在一个数组中,无重复元素,找出所有 组合 他们的和 == 0 即 a + b + c = 0;

   组合满足的条件 :

     1 . a < b < c

     2 . 组合不能重复

 

题目思路:

   如果是暴力求解话,那么就得有三个for循环,时间复杂度为 O(n^3);

   而下面的方法,为O(n^2)

   首先对数组排序;

   然后可以借鉴暴力求解的方法;

   比如说,对数组 - 1 ,0, 1, 2 ;

   当 i = -1 , j = 0 , 看k = 1 或 者 k = 2 是否满足条件

   然后就是 i = -1 , j= 1 , 看 k = 2 是否满足条件

 

   这里我们就可以得出一条结论:i+j 搭配,j后的元素只可能存在一个k 使得i+j+k = 0 (数组排好序,而且无重复元素)

   如果i + j + k > 0 那么 k 之后的与 i + j 相加也必然 > 0 , 所以,此时,只能使 j , k 某个 减小 才能使得 i + j + k == 0  , 所以 k--;

   同理i + j + k < 0 因为k 是往前移的,所以只能j++,才有可能 === 0;

  

   好的算法,不会做无意义的重复的事情;

   就拿这个方法与暴力方法比较;

   对于 -1 , 0 ,1 ,2 ,3 , 4

   暴力 : i = -1 , j = 0 ,  k = 1 , i + j + k == 0 , 明显对于 i = -1 , j = 0 的情况,不可能再有其他的元素使得i+j+k=0,所以接下来的k = 2 , k = 3 ,

   是完全没有必要的操作,但是暴力方法,仍然在傻乎乎的计算,所以就慢了;

  但是对于运用前后指针的方法,就不会这么傻乎乎的了,当i + j + k == 0 , 它知道对于i+j 这种情况不可能再有别的结果了,所以j++;

  那么此时 i+j + k 必然 > 0 , 所以 , k--; 再计算,不就成功跳过了那些没意义的操作了吗?

 

实现代码 (来自DISCUSS)

 

public class Solution {
    // 三个数的和为0 看下面这种让人叹为观止的方法
    // 前后指针的妙处!
    // excellent
    public List<List<Integer>> threeSum(int[] arr) {
        List<List<Integer>>lists = new ArrayList<List<Integer>> ();
        HashSet<List<Integer>> set = new HashSet<> ();
        int len = arr.length;
        if(len < 3) return lists;
        Arrays.sort(arr);
        for(int i = 0 ; i < len - 2; i++) {
            // 定义前后指针 
            for(int j = i + 1 , k = len - 1; j < k ; ) {
                int count = arr[i] + arr[j] + arr[k];
                // (i+j) 相对k 太大
                if(count < 0) j++;
                else if(count > 0) k--;
                else {
                    List<Integer> list = new ArrayList<> ();
                    list.add(arr[i]);
                    list.add(arr[j]);
                    list.add(arr[k]);
                    if(set.add(list)) lists.add(list);
                    // 这里如果是contains就不行了,因为他会遍历这个数组进行比较
                    // if(!lists.contains(list)) lists.add(list);
                    // 对于(i + j)来说,只可能存在一个k使得他们 == 0 (无重复元素)
                    j++;
                    k--;
                }
            }
        }
        return lists;
    }    
 }

 

   其实我第一想法,是hash , 数组排序,然后遍历一边数组,把每一个元素的相反数作为key 放入,map,

   那么两层for循环遍历数组,找到所以的两个元素的组合,看他们的和是否在map,如果在,再

  进行相应的重复检查,放入lists中

    无奈超时了..........

      

 

分享到:
评论

相关推荐

    函数指针数组的妙用

    ### 函数指针数组的妙用:提升代码效率与可读性 在计算机编程领域,尤其是在C语言中,函数指针是一种高级特性,它允许程序员将函数视为变量进行操作,从而实现更灵活的编程方式。当我们将这一概念进一步扩展到函数...

    文档python数组双指针算法求和问题LeetCode2sum3sum4sum含代码

    本文档主要介绍了在Python编程语言中如何运用双指针算法解决LeetCode上的2Sum、3Sum及4Sum求和问题,并提供了相应的代码实现。LeetCode是一个非常受欢迎的在线编程平台,用于练习算法题目,尤其适合准备技术面试的...

    python数组双指针算法求和问题LeetCode2sum3sum4sum含代码

    本文将深入探讨如何使用Python实现双指针算法来解决LeetCode中的2sum、3sum和4sum问题,并提供相关代码示例。 首先,我们来看2sum问题。给定一个整数数组`nums`和一个目标值`target`,我们需要找到数组中两个数的...

    3sum-hard问题的综述

    3Sum-Hard问题是由经典的3Sum问题扩展而来的,3Sum问题要求在一个整数数组中找到三个元素,使得它们的和等于一个给定的目标值。而3Sum-Hard问题则是在3Sum的基础上增加了一些复杂性和难度。 3Sum问题的基本算法通常...

    3-sum算法求解 python

    标题中的“3-sum算法求解 python”指的是在Python编程语言中实现一个经典的计算机科学问题——三数之和(3Sum)问题。这个问题来源于算法和数据结构领域,通常出现在面试和编程竞赛中。它的核心是找到一个整数数组中...

    c语言指针的妙用c语言指针的妙用

    ### C语言指针的妙用 C语言作为一种广泛使用的编程语言,在软件开发、系统编程等领域占据着重要地位。其中,指针是C语言的核心概念之一,对于理解和掌握C语言至关重要。本文将深入探讨C语言中指针的应用及其妙用。 ...

    彻底理解指针,指针数组和数组指针,指针函数和函数指针

    ### 彻底理解指针,指针数组和数组指针,指针函数和函数指针 #### 一、基础知识 在计算机编程中,指针是一个非常重要的概念,尤其是在C/C++这样的语言中更是如此。简单来说,指针是一种变量,但它存储的不是普通的...

    void 指针的妙用

    在"void 指针的妙用"这个主题中,我们主要探讨的是`void`指针在链表实现中的应用,特别是在阅读操作系统如uC/OS-II的源码时所体现的优势。 链表是一种动态数据结构,它由一系列节点组成,每个节点包含数据和指向下...

    3D动态旋转鼠标指针.rar

    3. 替换或导入:然后,你需要将这些文件导入到系统中,或者替换现有的鼠标指针设置。在Windows系统中,这通常通过控制面板的“鼠标”设置来完成,选择“指针”选项卡,然后浏览并应用新指针主题。 4. 验证和设置:...

    3D动态旋转鼠标指针,很好看的

    【3D动态旋转鼠标指针】是一种个性化的电脑设置,主要应用于Windows操作系统中,通过替换默认的二维静态鼠标指针,使用户界面更加生动、有趣。这种动态效果的鼠标指针通常包含多个不同状态下的3D动画,如移动、点击...

    win7 3D旋转鼠标指针

    3. 更改鼠标指针设置:进入控制面板,选择“硬件和声音” -&gt; “鼠标”,在弹出的“鼠标属性”窗口中,有“指针”选项卡。在这里,你可以选择新的3D指针方案,通常包括箭头、等待、帮助等不同类型的指针。 4. 应用...

    指针 指针教程 指针练习

    3. 多级指针:可以声明指向指针的指针,如`int **pp;`,`pp`是一个指向指针的指针,可用于处理多级结构。 四、动态内存分配与释放 1. 动态分配:使用`malloc()`和`calloc()`函数动态分配内存,返回的是内存块的起始...

    二级指针的妙用1

    在本文中,我们将深入探讨二级指针在编程中的妙用,特别是在处理链表数据结构时的高效性。林纳斯·托瓦兹(Linus Torvalds)在他的讨论中强调了理解指针和二级指针的重要性,他认为这是核心底层编程的基础。他指出,...

    用指针实现二维数组的转置

    总结起来,用指针实现二维数组的转置是一个涉及数组遍历和指针操作的过程。通过理解指针的工作原理,以及如何在内存中表示和访问二维数组,我们可以有效地编写出高效的转置算法。这个过程不仅锻炼了我们的逻辑思维...

    Starcraft 3D [Blue]鼠标指针

    3. **鼠标使用说明.txt**:这个文本文件可能提供了关于如何安装和使用“Starcraft 3D [Blue]”鼠标指针主题的详细步骤,帮助用户避免在安装过程中遇到的任何困难。 使用这样的鼠标指针主题,不仅能满足游戏爱好者对...

    C++双指针示例

    例如,寻找数组中的最大值和最小值,可以分别用一个指针指向最小值,另一个指针指向最大值,遍历数组更新这两个指针。 2. **字符串处理**:在处理字符串时,双指针可以用来检查回文串,或者比较两个字符串的相似度...

    一般函数指针和类的成员函数指针

    在C++编程语言中,函数指针是一种强大的特性,它允许程序员通过指针来间接调用函数,从而实现代码的灵活性和复用性。然而,当涉及到类的成员函数时,事情变得稍微复杂一些,因为类的成员函数通常包含一个隐含的参数...

    透明鼠标指针 透明鼠标指针透明鼠标指针

    透明鼠标指针 透明鼠标指针透明鼠标指针透明鼠标指针透明鼠标指针透明鼠标指针透明鼠标指针

    指针,指针类型,指针函数

    声明指针时,通常会先声明指针类型,然后用星号(*)表示它是指针,如`int *p`,其中`p`是一个指向整型数据的指针。其他类型的指针,如字符指针`char *`、浮点指针`float *`等,也以此类推。 ### 2. 初始化指针 初始...

    200款鼠标指针库-鼠标指针设置-鼠标指针方案.zip

    "个性鼠标指针"是这个压缩包的核心内容之一,它指的是那些不同于默认样式,具有独特设计的鼠标指针。这些个性化的指针可能有各种各样的主题,如卡通人物、动物形象、电影元素等,使用户在使用电脑时能感受到与众不同...

Global site tag (gtag.js) - Google Analytics