Leetcode关于数对的 题总结

大三了,要找工作了,呜呜所以来水一下leetcode

1877求数对相关的题总结

难度依次增加(三个题)

数组中最大数对和的最小值

在这里插入图片描述
题解:需要找到小的最大数对和
我们贪心的想,一个数列有很多元素,它们应该是有次序的,我们应该让最大的和最小的结合,然后依次向中间靠拢才能使整个数列数对的和最小(证明:如果最大值结合其他选手一定使结果变大了,然后最大确定了依次就是次大它所结合的也就确定了)
这也算是双指针的方法
代码

class Solution {
public:
    int minPairSum(vector<int>& nums) {
    sort(nums.begin(),nums.end());
    int sum=0;
    for(int i=0;i<nums.size();i++)
    {
    sum=max(nums[i]+nums[nums.size()-i-1],sum);
    }
   
    return sum;
    }
};

##1679. K 和数对的最大数目
在这里插入图片描述
解析:注意下后面给了范围所有元素都是>=1,对于这种我们需要找 和为k 的想法
最朴素:通俗的想法就是枚举,先枚举一个a在去找另外一个k-a,复杂度为O(n^2)

我们在想一下:我们枚举了一个a,我们只需要找到数组里面是否存在k-a就行,如果我们能快速知晓是否有k-a那么我们的算法就提升了
1.我们可以用数组vis[i]来标记 i 出现的次数,但是我们看题目的范围是1<=nums[i]<=1e9,所以空间太大了,不能够实现(如果题目改变范围就可以用这个方法类似于桶排序)
2 所以我们再继续想 nums.size的大小为 1e5 ,所以我们可以用map来记录数字nums[i]出现的次数,map可以让我们以O(1)的速度访问,所以提升了
这个题有特殊的一点,所有nums[i]都为正数 ,所以我们枚举a 的范围在 0—k中间(排序就找到哪些在这个范围了),我们先保存起来然后在去找 b=k-a,发现b的范围也在我们枚举的a内,直接计算就行 复杂度O(n log n)二分的复杂度(二分前提需要排序哦排序也是和二分一样复杂度,所以总的还是那么多
下面看代码(可能比较丑,用了c++11)
想一想为什么要除以2

//map存一下
class Solution {
public:
    int maxOperations(vector<int>& nums, int k) {
        int cnt=0;
        map<int ,int > map1;
     for(int i=0;i<nums.size();i++)
     if(nums[i]<k)   map1[nums[i]]++;
     
    for(auto it : map1){
	cnt+=min(it.second,map1[k-it.first]);
}
    return cnt/2;//算了俩次
    }
};

3.我们想我们枚举a,b,先枚举a然后我们需要寻找k-a是否在数列里面,是不是很熟悉?
查询数当然用 二分查找了,但是我们要注意的是k-a这个数可能出现多次,所以我们找到一个就标记下,然后下次不能找不就行了
二分答案也行,找最左和最右的数来(就不展开了)
因为我没有去实现orz

面试题 16.24. 数对和

在这里插入图片描述
前面我们学习了和为k的数对都有多少个那这里就是多了一步把它存下来,所以直接放代码了(写了俩种,第一种双指针挺巧的第二种就常规操作,看的题解然后写的)
代码方法1:
还是先排序哈
看指针那里
1、若nums[l] + nums[r] == target,则记录答案,并将左指针l++,右指针r–
2、若nums[l] + nums[r] > target,则说明此时结果太大了,则r–可以将结果缩小(后面r都无用了,去结合只能让结果更大,要找到和为k只有在更小的范围里面)
3、若nums[l] + nums[r] < target,则说明此时结果太小了,则l++可以将结果增大(与上面解释一样)

有人说不懂,可能是没有找到所有的,但是找到了(我不知道能讲懂不- _ -)
对于所有ai + bi = k 的数对肯定有次序关系,那么我们假设找到了一个数对 然后它的位置为 l和r
它让l++ ,那么我们找的是 更大的a的数对,那么它对应的b肯定是在更小的r所以肯定是对的,那对于之前的数对,在之前的寻找中肯定都被我寻找到了(递归一样。。)
当两个指针重合了 就结束,否则我们就会寻找重复了

class Solution {
public:
    vector<vector<int>> pairSums(vector<int>& nums, int target) {
     vector<vector<int>> G;
    
    sort(nums.begin(),nums.end());
    int l=0,r=nums.size()-1;
    //双指针O(n)
      while (l < r) {
          int flag=nums[l]+nums[r]-target;
            if (flag==0) {
               G.push_back({nums[l], nums[r]});
                l++,r--;
            }
            else if(flag>0)
                r--;
            else 
                l++;
        }
   return G;
    }
};

方法2:(常规就不解释了)
一点点细节,开始时wa了一发,,

class Solution {
public:
    vector<vector<int>> pairSums(vector<int>& nums, int target) {
     vector<vector<int>> G;
    map<int ,int > map1;
    int cnt=0;
    sort(nums.begin(),nums.end());

    //可能有负数
     for(int i=0;i<nums.size();i++)
       map1[nums[i]]++;
     
    for(auto it : map1){
	cnt=min(it.second,map1[target-it.first]);
    //特例
    if(it.first*2==target)  cnt/=2; 
    while(cnt--)   G.push_back({it.first,target-it.first});
   map1[target-it.first]=0;
}
   return G;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: LeetCode 的第一是 Two Sum。目描述是:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。 解法: 1. 暴力枚举法:对于每一个数,遍历整个数组,找到另一个数使得它们的和为 target。时间复杂度为 O(n^2)。 2. Hash 表法:遍历数组,对于每一个数,用 target 减去该数,判断差值是否在数组中出现过,如果出现过就返回该数的下标和差值的下标。时间复杂度为 O(n)。 在 LeetCode 中,你可以使用任意一种方法来解决该。 ### 回答2: leetcode第一是要求找出数组中两个数的和等于给定目标数的索引。可以使用哈希表来解决这个问。 首先,我们可以创建一个空的哈希表。然后,遍历整个数组,对于每一个元素,计算目标数减去当前元素的差值。接着,我们检查差值是否在哈希表中,如果存在,说明当前元素与差值的和等于目标数。我们可以直接返回当前元素和差值在哈希表中的索引。 如果差值不在哈希表中,我们将当前元素及其索引插入哈希表中,以便之后可以通过差值来找到当前元素的索引。遍历完成后,如果没有找到满足条件的索引,返回一个空数组或者其他指定的结果。 使用哈希表的解决方案可以将查找的时间复杂度降低到O(1)。整个算法的时间复杂度为O(n),其中n为数组的长度。算法的空间复杂度为O(n),因为需要额外的哈希表来存储元素及其索引。 总结起来,leetcode第一可以通过使用哈希表来解决,其中遍历数组并将元素及其索引存储在哈希表中,然后查找差值是否在哈希表中,找到满足条件的索引并返回。这个解决方案的时间复杂度为O(n),空间复杂度为O(n)。 ### 回答3: LeetCode是一个在线的编程库,第一是非常简单的算法。这个目要求我们在一个整数数组中找到两个数,使得它们的和等于目标数。解决这个问有几种方法。 一种简单的方法是使用双重循环来遍历数组中的每一对数,然后判断它们的和是否等于目标数。这样的时间复杂度是O(n^2),不是很高效。 另一种更优化的方法是使用哈希表。我们可以遍历一遍数组,将每个数与目标数的差值作为键,对应的索引作为值存放在哈希表中。然后再次遍历数组,每次都判断当前数在哈希表中是否存在,如果存在则说明找到了满足条件的两个数。这种方法的时间复杂度是O(n),空间复杂度也是O(n)。 还有一种更巧妙的方法是使用双指针。我们可以设置两个指针,一个指向数组的起始位置,一个指向数组的末尾位置,然后通过移动指针来逐渐缩小搜索范围。如果指针所指的两个数的和等于目标数,则找到了答案;如果和小于目标数,则将左指针右移一位;如果和大于目标数,则将右指针左移一位。这种方法的时间复杂度也是O(n),但空间复杂度是O(1),比哈希表方法更节省空间。 总之,这个目虽然很简单,但是解决的方法有多种。根据目要求和具体情况,我们可以选择适合的方法来解决这个问

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值