力扣刷题 day4

三数之和

15. 三数之和 - 力扣(LeetCode)

图一 :

在这里插入图片描述

图二:

在这里插入图片描述

图三:

在这里插入图片描述

java:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ret = new ArrayList<>();
        Arrays.sort(nums);
        for (int i = 0; i < nums.length;) {
            // 固定数 a
            int a = nums[i];
            int target = -a;
            // 小优化
            if (a > 0) {
                // 此时 left 和 right 表示的数都为正数
                break;
            }
            // 双指针
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                if (nums[left] + nums[right] < target) {
                    left++;
                } else if (nums[left] + nums[right] > target) {
                    right--;
                } else {
                    // 此时相等 --> 将数据填入到 ret 中
                    ret.add(Arrays.asList(nums[left], nums[right], a));
                    left++;
                    right--;
                    // 去重操作 --> left < right 是防止出现越界的情况
                    while (left < right && nums[left] == nums[left - 1]) {
                        left++;
                    }
                    while (left < right && nums[right] == nums[right + 1]) {
                        right--;
                    }
                }
            }
            // left 和 right 完成去重操作 对 a 进行去重操作
            i++;
            while (i < nums.length && nums[i] == nums[i - 1]) {
                i++;
            }
        }
        return ret;
    }
}

python:

class Solution(object):

    # 三数之和
    def threeSum(self, nums):
        ret = []
        nums.sort()
        i = 0
        while i < len(nums):
            # 固定一个数
            a = nums[i]
            # 三数之和相加为 0
            target = -a
            if a > 0:
                break
            # 双指针
            left = i + 1
            right = len(nums) - 1
            # 进行遍历
            while left < right:
                sum = nums[left] + nums[right]
                if sum < target:
                    left += 1
                elif sum > target:
                    right -= 1
                else:
                    # 此时找到了
                    ret.append([a, nums[left], nums[right]])
                    left += 1
                    right -= 1
                    # 去重操作
                    while left < right and nums[left] == nums[left - 1]:
                        left += 1
                    while left < right and nums[right] == nums[right + 1]:
                        right -= 1
            i += 1
            while i < len(nums) and nums[i] == nums[i - 1]:
                i += 1
        return ret


这里思路其实非常好像,就是 排序完后固定一个值,然后 双指针找一个数,但难在如何进行去重操作, 如果上面去重操作觉得有点问题的话,可以使用 set 来去重,set 里面存储的数据是唯一的.

java:

 // 1. 排序 2.双指针 3.去重
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        HashSet<List<Integer>> hashSet = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            int left = i + 1;
            int right = nums.length - 1;
            int a = nums[i];
            
            while (left < right) {
                List<Integer> list1 = new ArrayList<>();
                if (a + nums[left] + nums[right] == 0) {
                    list1.add(a);
                    list1.add(nums[left]);
                    list1.add(nums[right]);
                    hashSet.add(list1);
                    left++;
                    right--;
                } else if (a + nums[left] + nums[right] > 0) {
                    right--;
                } else {
                    left++;
                }
            }
        }
        return new ArrayList<>(hashSet);
    }

四数之和

18. 四数之和 - 力扣(LeetCode)


这道题是对三数之和的衍生, 这里 先固定一个数,接下来不就剩下三个数了吗,那么三个数就直接使用三数之和的思路不就好了.

java

class Solution {
    // 四数之和
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> ret = new ArrayList<>();
        Arrays.sort(nums);
        if(nums == null || nums.length < 4){
            return ret;
        }
        for (int i = 0; i < nums.length;) {
            // 固定第一个数
            int a = nums[i];
            if (a > 0 && target < 0) {
                break;
            }
            // 三数之和
            for (int j = i + 1; j < nums.length;) {
                // 固定第二个数
                int b = nums[j];
                long number =  (long)target - a - b;
                // 使用双指针
                int left = j + 1;
                int right = nums.length - 1;
                while (left < right) {
                    int cur1 = nums[left];
                    int cur2 = nums[right];
                    if (cur1 + cur2 > number) {
                        right--;
                    } else if (cur1 + cur2 < number) {
                        left++;
                    } else {
                        // 此时找到了 添加到 ret 中
                        ret.add(Arrays.asList(a, b, cur1, cur2));
                        left++;
                        right--;
                        // 去重操作
                        while (left < right && nums[left] == nums[left - 1]) {
                            left++;
                        }
                        while (left < right && nums[right] == nums[right + 1]) {
                            right--;
                        }
                    }
                }
                // 对三数固定的值进行去重
                j++;
                while (j < nums.length && nums[j] == nums[j - 1]) {
                    j++;
                }
            }

            // 此时对 第一个固定的数进行去重操作
            i++;
            while (i < nums.length && nums[i - 1] == nums[i]) {
                i++;
            }
        }
        return ret;
    }
}

这道题 力扣 很 恶心 弄出来两个溢出的情况,只需要使用 Long 即可.

python:


class Solution(object):
    # 四数之和
    def fourSum(self, nums, target):
        ret = []
        nums.sort()
        if nums is None or len(nums) < 4:
            return ret
        i, j = 0, 0
        while i < len(nums):
            a = nums[i]
            if a > 0 > target:
                break
            j = i + 1
            while j < len(nums):
                b = nums[j]
                left, right = j + 1, len(nums) - 1
                number = target - a - b
                while left < right:
                    sum = nums[left] + nums[right]
                    if sum < number:
                        left += 1
                    elif sum > number:
                        right -= 1
                    else:
                        # 此时相等
                        ret.append([a, b, nums[left], nums[right]])
                        left += 1
                        right -= 1
                        # 去重
                        while left < right and nums[left] == nums[left - 1]:
                            left += 1
                        while left < right and nums[right] == nums[right + 1]:
                            right -= 1

                # 对 j 进行去重
                j += 1
                while j < len(nums) and nums[j] == nums[j - 1]:
                    j += 1
            # 对 i 进行去重
            i += 1
            while i < len(nums) and nums[i] == nums[i - 1]:
                i += 1
        return ret

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于力扣刷C++常用操作,我可以给你一些常见的操作和技巧: 1. 使用 STL 容器和算法库:STL(Standard Template Library)是 C++ 标准库中的一个重要组成部分,包含了许多常用的容器和算法。在力扣刷中,使用 STL 可以大大提高代码的效率和可读性。例如,vector 可以用来存储动态数组,sort 可以用来排序等等。 2. 使用 auto 关键字:auto 关键字可以自动推导变量类型,可以减少代码量和提高可读性。例如,auto x = 1; 可以自动推导出 x 的类型为 int。 3. 使用 lambda 表达式:lambda 表达式是 C++11 中引入的一种匿名函数,可以方便地定义一些简单的函数对象。在力扣刷中,使用 lambda 表达式可以简化代码,例如在 sort 函数中自定义比较函数。 4. 使用位运算:位运算是一种高效的运算方式,在力扣刷中经常会用到。例如,左移运算符 << 可以用来计算 2 的幂次方,右移运算符 >> 可以用来除以 2 等等。 5. 使用递归:递归是一种常见的算法思想,在力扣刷中也经常会用到。例如,二叉树的遍历、链表的反转等等。 6. 使用 STL 中的 priority_queue:priority_queue 是 STL 中的一个容器,可以用来实现堆。在力扣刷中,使用 priority_queue 可以方便地实现一些需要维护最大值或最小值的算法。 7. 使用 STL 中的 unordered_map:unordered_map 是 STL 中的一个容器,可以用来实现哈希表。在力扣刷中,使用 unordered_map 可以方便地实现一些需要快速查找和插入的算法。 8. 使用 STL 中的 string:string 是 STL 中的一个容器,可以用来存储字符串。在力扣刷中,使用 string 可以方便地处理字符串相关的问。 9. 注意边界条件:在力扣刷中,边界条件往往是解决问的关键。需要仔细分析目,考虑各种边界情况,避免出现错误。 10. 注意时间复杂度:在力扣刷中,时间复杂度往往是评判代码优劣的重要指标。需要仔细分析算法的时间复杂度,并尽可能优化代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值