由一个“双指针题目”引起的对平台的思考

5 篇文章 0 订阅
2 篇文章 0 订阅

由一个“双指针题目”引起的对平台的思考(“三数之和“)

先说题目吧,今天做了道“三数之和”

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

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

示例1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

我“定眼”一看!豁,好熟悉,dfs,然后一顿做,我的

思路是这样的:
  1. 确定好dfs参数
  2. 发现输出是有规律的,不能盲目搜索。-----加个排序
  3. 发现还要判重------转String 利用SET 。基操。
  4. 发现返回没参数了,歪日,list的深浅拷贝很细节。

结果 318个卡在了第315个上超时。

。。。

看来不只是简单的深搜啊

加”剪枝“。

经过一系列的压榨···还是超时。
不得不向题解低头,然后发现——>竟然又是双端指针。

我在”力扣“上遇到好多思路都是双指针,在洛谷刷题这么长时间以来,由于题目是洛谷上的,搜的题解,包括百度的思路,都是“洛谷化”。明显能感觉出两个平台的风格不同,解题思路不同,我一直以来以为算法思想万变不离其宗,其实由于设置的题型,出题团队的思考习惯,都能使得解题方法另辟蹊径。

所以以后多接触不同平台,然后多看其他的题解,扩展思路。

总结:
  • 双指针的优势可以在dfs的时候感觉到,因为剪枝只是做到单方向的剪枝。
  • 双指针更加简洁灵活。
  • 我的set处理判重并不漂亮。
  • 这里的while加指针很像快排。
  • 总结模板的话就是:当感觉线性,递增的问题时,或者能不能讲递归转化的时候,考虑一下双指针。
  • 还得多练找感觉。
我的深搜题解(315/318 超时)
import javafx.scene.effect.SepiaTone;
import java.util.*;
/**
 * @Auther Lizz
 * @Date 2021/10/8
 */
public class P15 {
    public static void main(String[] args) {
        
        Solution solutio = new Solution();
        int  [] num = {-1,0,1,2,-1,-4};
        List<List<Integer>> list = solutio.threeSum(num);
        for (int i = 0; i <list.size() ; i++) {
            for (int j = 0; j < list.get(i).size() ; j++) {
                System.out.print(list.get(i).get(j));
            }
            System.out.print("  ");
        }

    }
    static  class Solution {
        List<List<Integer>> ANS = new ArrayList();
        int vis[];
        int NUMS[];
        Set set  = new HashSet();
        public List<List<Integer>> threeSum(int[] nums) {
            vis = new int[nums.length];
            NUMS = nums;//深浅拷贝
            Arrays.sort(NUMS);
            List list = new ArrayList();
            dfs(0,0,list);//第几个数了,目前大小

            return ANS;
        }

        private void dfs(int i, int sum,List list) {
            if(sum>0 ||list.size()>3 || (list.size() == 3 && sum !=0)){
                return;
            }
            if(list.size()==3 && sum == 0 ){
                List<Integer> list1 = new ArrayList<>(3);
                String s = "";
                for (int j = 0; j < 3; j++) {
                    list1.add((Integer) list.get(j));
                    s+=list.get(j);
                }
                if( !set.contains(s)){
                    set.add(s);
                    ANS.add(list1);
                }

                return;
            }

            for (int j = i; j <NUMS.length ; j++) {
                // if((list.size()==2&&sum<0&&NUMS[j]<0)||(list.size()==2&&sum>0&&NUMS[j]>0)){
                //     continue;
                // }  int j = NUMS.length-1; j >=i &&sum<=0; j--
//这里是我为剪枝做出的尝试
                list.add(NUMS[j]);
                dfs(j+1,sum+NUMS[j],list);
                list.remove((Object) NUMS[j]);
            }

        }
    }
}

题解双指针:
import java.util.*;

/**
 * @Auther Lizz
 * @Date 2021/10/8
 */
public class P15_2 {

    public static void main(String[] args) {

        Solution solutio = new Solution();
        int  [] num = {-1,0,1,2,-1,-4};
        List<List<Integer>> list = solutio.threeSum(num);
        for (int i = 0; i <list.size() ; i++) {
            for (int j = 0; j < list.get(i).size() ; j++) {
                System.out.print(list.get(i).get(j));
            }
            System.out.print("  ");
        }

    }


    static  class Solution {
        List<List<Integer>> ANS = new ArrayList();
        int NUMS[];
        public List<List<Integer>> threeSum(int[] nums) {
            NUMS = nums;//深浅拷贝
            Arrays.sort(NUMS);
            int len = NUMS.length;
            for (int i = 0; i < len ; i++) {
                if(NUMS[i]>0){
                    return ANS;
                }
                //去重
                if(i>0 && NUMS[i]==NUMS[i-1]){
                   continue;
                }
                int curr = NUMS[i];
                int l = i+1;
                int r = len-1;
                while (l<r){
                   if(curr+NUMS[l]+NUMS[r]==0){
                        List list = new ArrayList();
                        list.add(NUMS[i]);
                        list.add(NUMS[l]);
                        list.add(NUMS[r]);
                        ANS.add(list);
                        while (l<r &&NUMS[l+1]==NUMS[l])l++;
                        while (l<r &&NUMS[r-1]==NUMS[r])r--;
                        l++;
                        r--;
                   }else if(curr+NUMS[l]+NUMS[r]>0){
                       r--;
                   }else {
                       l++;
                   }
                }
            }

            return ANS;
        }

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值