代码随想录二刷 day07 |哈希表 之 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和

news/2024/11/24 7:33:07/

day07

      • 454 四数相加II
      • 383 赎金信
      • 15. 三数之和
      • 18. 四数之和

454 四数相加II

题目链接
解题思路: 类似两数相加的变形。将四数变成两组,这样的时间复杂度O(n²)是最小的。
不用考虑有重复的四个元素相加等于0的情况,

class Solution {
public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {unordered_map <int ,int>  umap; //key:a+b的数值,value:a+b数值出现的次数// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中for(int a:nums1){for(int b:nums2){umap[a + b]++;  // a+b结果相等 value + 1}} int count = 0;// 统计a+b+c+d = 0 出现的次数 在遍历nums3和nums4数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。for(int c:nums3){for(int d:nums4){auto iter = umap.find(0-(c+d)); //模仿两数相加,定义了一个中间值if(iter != umap.end()){count += iter->second;}}}return count;}
};

383 赎金信

题目链接
解题思路: 这个题和 242.有效的字母异位词 基本一直,思路也基本上差不多。

// 时间复杂度: O(n)
// 空间复杂度:O(1)
class Solution {
public:bool canConstruct(string ransomNote, string magazine) {int record[26] = {0};//addif (ransomNote.size() > magazine.size()) {return false;}for (int i = 0; i < magazine.length(); i++) {// 通过recode数据记录 magazine里各个字符出现次数record[magazine[i]-'a'] ++;}for (int j = 0; j < ransomNote.length(); j++) {// 遍历ransomNote,在record里对应的字符个数做--操作record[ransomNote[j]-'a']--;// 如果小于零说明ransomNote里出现的字符,magazine没有if(record[ransomNote[j]-'a'] < 0) {return false;}}return true;}
};

15. 三数之和

题目链接
解题思路: 看到题目想使用一下哈希表,但是试了一下,太麻烦了,有些细节没想清楚,时间复杂度也挺高的。然后 想到了使用双指针,一个左指针,一个右指针。
数组中找到 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相遇为止。
根据题目要求还得进行去重操作。

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> result;sort(nums.begin(), nums.end());// 找出a + b + c = 0// a = nums[i], b = nums[left], c = nums[right]for (int i = 0; i < nums.size(); i++) {// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了if (nums[0] > 0) {return result;}// 错误去重a方法,将会漏掉-1,-1,2 这种情况/*if (nums[i] == nums[i + 1]) {continue;}*/// 正确去重a方法if (i > 0 && nums[i] == nums[i - 1]) {continue;}int left = i + 1;int right = nums.size() - 1;while (right > left) {// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right<=left 了,从而漏掉了 0,0,0 这种三元组/*while (right > left && nums[right] == nums[right - 1]) right--;while (right > left && nums[left] == nums[left + 1]) left++;*/if (nums[i] + nums[left] + nums[right] > 0) right--;else if (nums[i] + nums[left] + nums[right] < 0) left++;else {result.push_back(vector<int>{nums[i], nums[left], nums[right]});// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重while (right > left && nums[right] == nums[right - 1]) right--;while (right > left && nums[left] == nums[left + 1]) left++;// 找到答案时,双指针同时收缩right--;left++;}}}return result;}
};

18. 四数之和

题目链接
解题思路: 和15.三数之和 是一个思路,都是使用双指针法, 基本解法就是在15.三数之和 的基础上再套一层for循环。

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> result;sort(nums.begin(), nums.end());for (int k = 0; k < nums.size(); k++) {// 剪枝处理if (nums[k] > target && nums[k] >= 0) {break; // 这里使用break,统一通过最后的return返回}// 对nums[k]去重if (k > 0 && nums[k] == nums[k - 1]) {continue;}for (int i = k + 1; i < nums.size(); i++) {// 2级剪枝处理if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {break;}// 对nums[i]去重if (i > k + 1 && nums[i] == nums[i - 1]) {continue;}int left = i + 1;int right = nums.size() - 1;while (right > left) {// nums[k] + nums[i] + nums[left] + nums[right] > target 会溢出if ((long) nums[k] + nums[i] + nums[left] + nums[right] > target) {right--;// nums[k] + nums[i] + nums[left] + nums[right] < target 会溢出} else if ((long) nums[k] + nums[i] + nums[left] + nums[right]  < target) {left++;} else {result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});// 对nums[left]和nums[right]去重while (right > left && nums[right] == nums[right - 1]) right--;while (right > left && nums[left] == nums[left + 1]) left++;// 找到答案时,双指针同时收缩right--;left++;}}}}return result;}
};

http://www.ppmy.cn/news/108151.html

相关文章

若依如何修改超级管理员登录密码

文章目录 修改方法方法一&#xff1a;不需要手动改数据库方法二&#xff1a;手动改数据库 为什么密码要加密存储BCryptPasswordEncoder介绍 修改方法 若依等Spring Boot 后台管理框架使用了Spring Security进行身份认证和授权&#xff0c;可以通过以下步骤修改超级管理员密码&…

离散数学_十章-图 ( 4 ):图的表示和图的同构

&#x1f4f7;10.4 图的表示和图的同构 1. 图的表示1.1 邻接表1.1.1 简单图的邻接表1.1.2 有向图的邻接表 1.2 邻接矩阵❗在邻接表和邻接矩阵之间取舍1.3 关联矩阵 2. 图同构3. ⚡判断两个简单图是否同构 图的表示方式有很多种&#xff0c;选择最方便的表示有助于对图的处理~ …

C++中变量、指针、引用、函数和类的内存机制

变量&#xff1a;变量在内存中是一个存储器单元&#xff0c;它能够保存数据&#xff0c;并且可以通过变量名来访问。变量的内存空间大小与其数据类型有关。 指针&#xff1a;指针实际上是一个变量&#xff0c;它存储的是内存中另一个变量的地址。指针在内存中本身也有存储器单…

这篇文章把MOS管的基础知识讲透了

MOS管&#xff08;Metal-Oxide-Semiconductor field-effect transistor&#xff09;是一种常见的半导体器件&#xff0c;它在数字电路、模拟电路、功率电子等领域都有广泛的应用。本文将从MOS管的基本结构、工作原理、参数特性等方面讲解MOS管的基础知识。 一、MOS管的基本结构…

Python3数据分析与挖掘建模(6)离散分布分析示例

1. 离散分布分析示例 相关库&#xff1a; pandas详细用法 numpy详细用法 1.1 引入算法库 # 引入 pandas库 import pandas as pd # 引入 numpy库 import numpy as np# 读取数据 dfpd.read_csv("data/HR.csv")# 查看数据 df Out[6]: satisfaction_level last_eval…

Mybaits Oracle CLob类型处理

问题描述: 使用的是Oracle 数据库, 表中有一个字段类型为clob类型 问题 : 当使用mybatis查询返回map类型时, 该字段的值为clob对象,而不是数据库里面的字符串 解决方案: 1.手动进行转换,把clob类型转换为字符串(这种比较简单) if(map.get("MAIN_BIZ") instanceo…

代码随想录补打卡 647 回文子串 516 最长回文子序列

647 回文子串 代码如下 func countSubstrings(s string) int { //dp[i][j]数组的含义是i-j这个范围的元素是否为回文串 dp : make([][]bool,len(s)) for i,_ : range dp { dp[i] make([]bool,len(s)) } res : 0 for i : len(s)-1 ; i > 0 ; i-- { 因为dp[i…

点成分享丨ELISA实验的类型及原理

ELISA实验&#xff0c;即酶联免疫吸附测定&#xff08;Enzyme-Linked Immunosorbent Assay&#xff09;实验&#xff0c;是免疫学中的经典实验之一&#xff0c;它是一种利用抗原抗体特异性结合进行免疫反应的定性和定量检测方法&#xff0c;目前已被广泛应用于生物学、医学、植…