acm刷题记录 (2020.4.2)

本文记录了解决LeetCode上的两道题目——三数之和(15题)和最接近的三数之和(16题)的过程。通过设定指针并根据三数之和的正负调整指针方向来找到符合条件的不重复三元组。在15题中,通过避免重复数据和处理特殊情况如[0,0,0],实现了高效解决方案。在16题中,同样利用指针策略找到与目标值最接近的三数之和。" 111422468,10296027,使用Python解析Newick格式计算进化树中结点距离,"['Python', '数据解析', '进化树', '生物学', '算法']
摘要由CSDN通过智能技术生成

leetcode 15
三数之和

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

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

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

此题和之前做过的一样,动用指针的思路。
值得分析的问题有两个:
1.对于有序数组,三数之和>0,则其中数字应该增大还是减小?
三数之和<0,则其中数字应该增大还是减小?

显然当三数之和>0,数应该减小。
三数之和<0,数应该增大。

所以可以采用指针,固定开头r遍历一遍,在剩余的数组里定义左指针t为开头,右指针l为结尾。
当三数之和>0,数应该减小,所以l–;
当三数之和<0,数应该增加,所以t++;
当t>=l时,r++;

2.无重复的集合。
一开始我选择使用set来解决,但是后来发现只要规避掉重复的数据就可以了。
当指针移动时,如果数据重复则继续移动。
对于[0,0,0]问题
由于指针一开始就分开,则必然遍历过如此情况。

code:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        //指针法
        List<List<Integer>> list=new LinkedList<List<Integer>>();
        if(nums.length<3) return list;
        Arrays.sort(nums);
        int r=0;
        int t=1;
        int l=nums.length-1;
        while(t<=nums.length-1)
        {
            if(r>nums.length-3) break;
            int p=nums[r]+nums[t]+nums[l];
            if(p==0)
            {
                List<Integer> al=new ArrayList<Integer>();
                al.add(nums[r]);
                al.add(nums[t]);
                al.add(nums[l]);
                list.add(al);
                while(l>t&&nums[l]==nums[--l]);
                while(l>t&&nums[t]==nums[++t]);
            }
            else if(p>0)
            {
                while(l>t&&nums[l]==nums[--l]);
            }
            else if(p<0)
            {
                while(l>t&&nums[t]==nums[++t]);
            }
            if(t>=l)
            {
                while(r<=nums.length-3&&nums[r]==nums[++r]);
                t=r+1;
                l=nums.length-1;
            }
        }
        return list;
    }
}

执行用时 :34 ms, 在所有 Java 提交中击败了58.39%的用户
内存消耗 :44.5 MB, 在所有 Java 提交中击败了98.17%的用户

leetcode 16
最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

这道题和上面一道思路相同,不多赘述。

code:

class Solution {
    public int threeSumClosest(int[] nums, int target) {
        if(nums.length<3) return 0;
        Arrays.sort(nums);
        int r=0;
        int t=1;
        int l=nums.length-1;
        int tar=100000;
        while(true)
        {
            if(r>nums.length-3) break;
            int p=nums[r]+nums[t]+nums[l];
            if(Math.abs(target-p)<Math.abs(tar))  tar=target-p;
            if(p==target) return target;
            else if(p<target)
            {
                while(l-1>t&&nums[t]==nums[++t]);
            }
            else if(p>target)
            {
                while(l-1>t&&nums[l]==nums[--l]);
            }
            if(t==l-1)
            {
                p=nums[r]+nums[t]+nums[l];
                if(Math.abs(target-p)<Math.abs(tar))  tar=target-p;
                while(r<=nums.length-3&&nums[r]==nums[++r]);
                t=r+1;
                l=nums.length-1;;
            }
        }
        return target-tar;
    }
}

执行用时 :7 ms, 在所有 Java 提交中击败了55.62%的用户
内存消耗 :39.2 MB, 在所有 Java 提交中击败了5.25%
的用户

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值