IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode 两数之和 & 三数之和& 四数之和 -> 正文阅读

[数据结构与算法]LeetCode 两数之和 & 三数之和& 四数之和

一、两数之和

在这里插入图片描述

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        // val, index
        unordered_map<int, int> mp;
        for(int i = 0; i < nums.size(); i++){
            if(mp.find(target - nums[i]) != mp.end()){
                return {i, mp[target - nums[i]]};
            }
            mp[nums[i]] = i;
        }
        return {};
    }
};

二、四数相加 II

在这里插入图片描述
本题是使用哈希法的经典题目,而0015.三数之和 (opens new window),0018.四数之和 (opens new window)并不合适使用哈希法,因为三数之和和四数之和这两道题目使用哈希法在不超时的情况下做到对结果去重是很困难的,有很多细节需要处理

而这道题目是四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑有重复的四个元素相加等于0的情况,所以相对于题目18. 四数之和,题目15.三数之和,还是简单了不少!

如果本题想难度升级:就是给出一个数组(而不是四个数组),在这里找出四个元素相加等于0,答案中不可以包含重复的四元组,大家可以思考一下,后续的文章我也会讲到的。

本题解题步骤:

  • 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数
  • 遍历A和B数组,统计两个数组元素之和,和出现的次数,放到map中
  • 定义int变量count,用来统计 a+b+c+d = 0 出现的次数
  • 在遍历C和D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来
class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        // val, cnt
        unordered_map<int, int> mp;
        for(int a : nums1){
            for(int b : nums2){
                mp[a+b]++;
            }
        }
        int cnt = 0;
        for(int c : nums3){
            for(int d : nums4){
                if(mp.find(0 - c - d) != mp.end()){
                    cnt += mp[0 - c - d];
                }
            }
        }
        return cnt;
    }
};

三、赎金信

在这里插入图片描述
说人话就是magazine必须要包含ransomNote中所有的字符,对于任意出现在ransomNote中的字符,magazine都能找到对应的,并且数量不能小于ransomNote中该字符出现的数量

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        unordered_map<char, int> mp;
        for(char c : magazine){
            mp[c]++;
        }
        for(char c : ransomNote){
            mp[c]--;
            if(mp[c] < 0){
                return false;
            }
        }
        return true;
    }
};

四、三数之和

在这里插入图片描述
拿这个nums数组来举例,首先将数组排序,然后有一层for循环,i从下标0的地方开始,同时定一个下标left 定义在i+1的位置上,定义下标right 在数组结尾的位置上

依然还是在数组中找到 abc 使得a + b +c =0,我们这里相当于 a = nums[i],b = nums[left],c = nums[right]

接下来如何移动left 和right呢, 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些

如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了,left 就向右移动,才能让三数之和大一些,直到left与right相遇为止

vector<vector<int>> threeSum(vector<int>& nums) {
    sort(nums.begin(), nums.end(), less<int>());
    vector<vector<int>> ans;
    for (int start = 0; start < nums.size() - 2; start++) {
        if (start > 0 && nums[start] == nums[start - 1]) {
            continue;
        }
        if (nums[start] > 0) {
            break;
        }
        int l = start + 1;
        int r = nums.size() - 1;
        while (l < r) {
            int sum = nums[start] + nums[l] + nums[r];
            if (sum == 0) {
                vector<int> tmp = { nums[start], nums[l], nums[r] };
                ans.push_back({ nums[start], nums[l], nums[r] });
                l++;
                r--;
                while (l < r && nums[l] == nums[l - 1]) {
                    l++;
                }
                while (l < r && nums[r] == nums[r + 1]) {
                    r--;
                }
            }
            else if (sum > 0) {
                r--;
                while (l < r && nums[r] == nums[r + 1]) {
                    r--;
                }
            }
            else {
                l++;
                while (l < r && nums[l] == nums[l - 1]) {
                    l++;
                }
            }
        }
    }
    return ans;
}

五、最接近的三数之和

在这里插入图片描述
依然是固定最前面的指针,用另外两个指针寻找最接近的三数和,和三数之和一样去重即可

int threeSumClosest(vector<int>& nums, int target) {
    long ans = INT_MAX;
    sort(nums.begin(), nums.end(), less<int>());
    for(int i = 0; i < nums.size() - 2; i++){
        if(i > 0 && nums[i] == nums[i-1]){
            continue;
        }
        int l = i + 1;
        int r = nums.size() - 1;
        while(l < r){
            int sum = nums[i] + nums[l] + nums[r];
            ans = abs(ans-target) < abs(sum-target) ? ans : sum; 
            if(sum == target){
                break;
            }else if(sum < target){
                l++;
                while(l < r && nums[l] == nums[l-1]){
                    l++;
                }
            }else{
                r--;
                while(l < r && nums[r] == nums[r+1]){
                    r--;
                }
            }
        }
    }
    return ans;
}

六、四数之和

在这里插入图片描述

在这里插入图片描述
三数之和固定一个指针,用两个指针寻找三元组;四数之和固定两个指针,用两个指针寻找四元组

思路和三数之和完全一样,去重操作也一样,除了剪枝操作不一样

我们不能像三数之和一样,用第一个指针大于target就退出,因为后面指针指向的值可能是负数,四个指针之和依然有可能满足等于target的条件。为了避免后面的指针为负数,我们加一个前面指针不小于0的条件

vector<vector<int>> fourSum(vector<int>& nums, int target) {
    vector<vector<int>> ans;

    if(nums.size() < 4){
        return ans;
    }
    sort(nums.begin(), nums.end(), less<int>());
    // 元素不少于4
    for(int i = 0; i <= nums.size() - 4; i++){
        if (i > 0 && nums[i] == nums[i - 1]) {
            continue;
        }
        // 不能只用(nums[i] > target)作为退出条件,nums[i]比target大,也许数组后面还有负数,不能退出
        if (nums[i] > target && nums[i] >= 0) {
            break;
        }
        for(int j = i + 1; j <= nums.size() - 3; j++){
            if (j > i + 1 && nums[j] == nums[j - 1]) {
                continue;
            }
            if (nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) {
                break;
            }

            int left = j + 1;
            int right = nums.size() - 1;
            while(left < right){
                long sum = long(nums[i]) + long(nums[j]) + long(nums[left]) + long(nums[right]);
                if(sum == target){
                    vector<int> tmp = {nums[i], nums[j], nums[left], nums[right]};
                    ans.push_back(tmp);
                    left++;
                    right--;
                    while(left < right && nums[left] == nums[left - 1]){
                        left++;
                    }
                    while(left < right && nums[right] == nums[right + 1]){
                        right--;
                    }
                }else if(sum < target){
                    left++;
                    while(left < right && nums[left] == nums[left - 1]){
                        left++;
                    }
                }else{
                    right--;
                    while(left < right && nums[right] == nums[right + 1]){
                        right--;
                    }
                }
            }
        }
    }
    return ans;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 02:14:53  更:2022-09-15 02:17:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:33:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码