【每日一题】 2024年1月汇编

🔥博客主页: A_SHOWY
🎥系列专栏:力扣刷题总结录 数据结构  云计算  数字图像处理  力扣每日一题_

【1.4】2397.被列覆盖的最多行数

2397. 被列覆盖的最多行数icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-rows-covered-by-columns/

这个题目真的太巧妙了,运用这种位运算来模拟这个数组,然后,将数组用位运算以后的二进制和存储,然后,用位运算设置limit,给while循环,1个数不够的还得continue了,最后按位与,整体结构都非常巧妙。

  1. 第一部分,存储每一行的二进制表示位,用一个数组把一个转为二进制存起来。
     vector<int> mask(m,0);//存储每一行的二进制表示位for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){mask[i] += matrix[i][j] << (n - j -1);}}
  2.  在判断的时候,用limit卡住界限,维护列变换的区间
     while((++cur) < limit){if(__builtin_popcount(cur) != numSelect) {continue;}
  3. 用了一个内置函数关于一个二进制中1 的个数的函数,还有0的个数的函数
    __builtin_popcount(cur) //1的个数
    __builtin_ctz(cur) //0的个数,count trailing zero
  4. 最后把每一行遍历一遍,与变换后的列的第一行按位与,看看能不能覆盖这一行的所有1
class Solution {
public:int maximumRows(vector<vector<int>>& matrix, int numSelect) {if(numSelect >= matrix[0].size()) return matrix.size();int m = matrix.size();int n = matrix[0].size();vector<int> mask(m,0);//存储每一行的二进制表示位for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){mask[i] += matrix[i][j] << (n - j -1);}}int res = 0;//记录最大行数int cur = 0;//最大列数int limit = (1 << n);while((++cur) < limit){if(__builtin_popcount(cur) != numSelect) {continue;}int t = 0;for(int j = 0; j < m; j++){//遍历一遍按位与if((mask[j] & cur) == mask[j]){t++;}}res = max(res,t);}return res;}
};

【1.14】83.删除排序链表中的重复元素

83. 删除排序链表中的重复元素icon-default.png?t=N7T8https://leetcode.cn/problems/remove-duplicates-from-sorted-list/

很久没有做到链表题目,但是这道确实简单,只需要注意一下while循环中除了cur非空,还要兼顾cur -> next非空。重复时,就让指针指向next -> next

class Solution {
public:ListNode* deleteDuplicates(ListNode* head) {ListNode* cur = head;while(cur != NULL && cur ->next != NULL){if(cur -> val == cur -> next -> val) {cur -> next = cur -> next -> next;}else cur = cur -> next;}return head;}
};

【1.15】82.删除排序链表中的重复Ⅱ

82. 删除排序链表中的重复元素 IIicon-default.png?t=N7T8https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/

与83题删除排序链表中元素的主要区别为此题要求将出现过的重复元素的所有元素均删除例如1,2,2,2将所有的2删除。需要引入头结点,因为头部可能也会被删除,统一操作。

class Solution {
public:ListNode* deleteDuplicates(ListNode* head) {ListNode*  dummyhead =  new ListNode(0); dummyhead -> next =head;ListNode* cur = dummyhead;   while(cur -> next && cur-> next -> next){if(cur -> next-> val == cur -> next -> next -> val){int x = cur -> next -> val;while(cur -> next && cur -> next -> val == x){//直到cur -> next 为空节点或者cur -> next 不为xcur -> next = cur -> next -> next;}}else cur = cur -> next;}head = dummyhead -> next;delete dummyhead;return head;}
};

 那么本题的总体思路也是比较简单,先设置一个虚拟头结点dummyhead,其具体步骤为

 ListNode*  dummyhead =  new ListNode(0); dummyhead -> next =head;ListNode* cur = dummyhead;   

如果节点的下一个等于其下一个的下一个,就说明重复,把重复的数字记下来,统一删除。while中判定条件是删除直到cur的下一个是空节点或者粗人的下一个的值不是x。最后再删除头结点。

【1.17】2744.最大字符串配对数目

2744. 最大字符串配对数目icon-default.png?t=N7T8https://leetcode.cn/problems/find-maximum-number-of-string-pairs/

该题目如果暴力做,二重循环思路比较简单,但是也可以用哈希法解决。

法一:暴力

class Solution {
public:int maximumNumberOfStringPairs(vector<string>& words) {int ans = 0;for(int i = 0; i < words.size();++i){for(int j = i + 1; j < words.size(); ++j){if(words[i][0] == words[j][1] && words[i][1] == words[j][0]) ans++;}}return ans;}
};

 法二:哈希

1.set.count 表示统计元素出现的次数不为0

2.用哈希值来存,题目限制是一个两位的字符串,同时都是小写字母,所以可以用第一位*100+第二位作为哈希值来存,两位互不影响。

class Solution {
public:int maximumNumberOfStringPairs(vector<string>& words) {unordered_set<int> set;int ans = 0;for(int i = 0; i < words.size(); i++){if(set.count(words[i][1] * 100 + words[i][0]))  ans++;set.insert(words[i][0] * 100 + words[i][1]);}return ans;}
};

如果把后边两部反过来会出现一些问题,先插入后判定,那么比如cc、aa、bb这种重叠的字符串就会被多算一次产生错误

            for(int i = 0; i < words.size(); i++){set.insert(words[i][0] * 100 + words[i][1]);if(set.count(words[i][1] * 100 + words[i][0]))  ans++;}

【1.18】2171.拿出最少数目的魔法豆 

2171. 拿出最少数目的魔法豆icon-default.png?t=N7T8https://leetcode.cn/problems/removing-minimum-number-of-magic-beans/

这道题目其实暴力做法非常容易,但是不通过,数据集太大了。如果想减少复杂度的话,可以先排序分段进行处理,也就是用排序+前缀和来解决 

方法一:暴力(不通过)

class Solution {
public:long long minimumRemoval(vector<int>& beans) {vector<long long> res(beans.size(),0);for(int i = 0; i < beans.size(); i++){for(int j = 0; j < beans.size(); j++){if(beans[j] >= beans[i]){res[i] += beans[j] - beans[i];}else{res[i] += beans[j];}}}long long ans = 9999999999;for(int i =0; i < beans.size();++i){if(res[i] < ans){ans = res[i];}}return ans;}
};

 暴力两个for直接不通过

方法二:排序 + 前缀和

//排序 + 前缀和
class Solution {
public:long long minimumRemoval(vector<int>& beans) {sort(beans.begin(),beans.end());//前缀和vector<long long> sum(beans.size() + 1,0);//让sum【0】 = 0for(int i = 0; i < beans.size(); i++){sum[i + 1] = sum[i] + beans[i];}long long res = LLONG_MAX/2;int n = beans.size();for(int i = 0; i < n; i++){res = min(res,sum[i] + sum[n] - sum[i + 1] - (n -1L -i) * beans[i]);}return res;}
};

先排序以后,创建一个数组储存前缀和,这时候要注意新数组的个数是size + 1,然后循环迭代赋值。

在后边的时候,设置res为LLONG_MAX/2,然后看图按照逻辑操作就行,比i这个地方的值小的一律置为0,比它大的置为beans【i】 

【1.20】2788.按分隔符拆分字符串

2788. 按分隔符拆分字符串icon-default.png?t=N7T8https://leetcode.cn/problems/split-strings-by-separator/

该题目是一个比较简单的模拟题,主要是积累getline函数的使用方法 

1.getline(ss, sub, separator) 的作用是从 std::stringstream 对象 ss 中读取一行(以 separator 为分隔符),并将结果存储在字符串 sub 中。istream& getline(istream& is, string& str, char delim);is: 输入流,str: 存储读取的行的字符串。delim: 指定的分隔符,getline 会根据这个分隔符进行拆分。 

class Solution {
public:vector<string> splitWordsBySeparator(vector<string>& words, char separator) {vector<string> res;for(string &word : words){//遍历输入的字符串数组stringstream ss(word);//使用字符串流 stringstream 对每个字符串进行处理,后边要用getlinestring str;while(getline(ss,str,separator)){if(!str.empty()) {res.push_back(str);}}}return res;}
};

2.记住&在这里是引用的意思,函数可以直接调用或者修改传递的字符串,而不是对其副本进行操作增加效率。

【1.21】410.分割数组的最大值

410. 分割数组的最大值icon-default.png?t=N7T8https://leetcode.cn/problems/split-array-largest-sum/

本题是一个hard题,分析题目,要求 最大值最小,确定思路不是二分就是dp,本题我们用二分求解。

先分析                                                                     每段和越小——》分出的段越多 ,

假设我分了                                       一个段落和最大值为sum 对应的段落为——》k1>k

代表着 段落分多了,减少分的段,就要每段和大一点。 所以小于等于sum那一部分就可以删掉了(因为要减少段,要每段和大一点)

这里的k个可以理解为至多。

class Solution {public:int splitArray(vector<int>& nums, int k) {auto maxElement = max_element(nums.begin(), nums.end());int l = *maxElement;int sum = 0;for(int i = 0; i< nums.size(); i++){sum += nums[i];}int r = sum;while(l <= r){int mid = l + ((r-l) / 2);if(check(nums,mid,k)) r = mid - 1;//如果能够分到k段,sum给大了else l = mid + 1;}return l;//当最后l,r,mid指向同一个点的时候,假如满足就是l,假如不满足,l=mid + 1,所以最后返回l}bool check(vector<int>& nums, int m, int k){int cnt = 1;//段数 int s = 0;for(int i = 0; i < nums.size(); i++){if(nums[i] + s <= m) s += nums[i];else{if(cnt++ == k) return false;else s = nums[i]; } }return true;}
};

这里面有很多值得注意的点,第一个是设置l和r,在设置r的时候就是最少的分段是一整个,所以直接求和,在左边的时候,最多的分段就是每个一段,所以直接找最大值,最大值的时候用一个迭代器,然后不要忘了求迭代器指向的具体值。

在二分法的时候,到了l,r,mid三个指向同一个点时候,考虑,假如这时候满足了,那么这三个点都能表示满足的最大值,如果不满足,那么l要mid+1,最后满足的还是l,所以要返回l。

在check函数中,注意先循环一手,如果小于这个值,就加进去s,如果不满足,先判断段落是不是够k了,如果够了直接false,否则新加一个cnt 

【1.22】670.最大交换

670. 最大交换icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-swap/

该题目主要考察灵活运用to_string 和stoi和swap函数,进行一次遍历。看题解以后,还有一种贪心的算法可以借鉴

方法一:遍历 

class Solution {
public:int maximumSwap(int num) {string stringNum = to_string(num);//to_string转成字符串int maxnum = num;int n = stringNum.size();for(int i = 0; i < n; i++){for(int j = i + 1; j < n; j++){swap(stringNum[i],stringNum[j]);maxnum = max(maxnum , stoi(stringNum));//stoi字符串转成intswap(stringNum[i],stringNum[j]);}} return maxnum;}
};

先把给的num转化成string形式,然后对字符串每一个字符进行两两交换,取最大值,在每一次循环中,交换过了要记得交换回来。 

方法二:贪心

只要让靠近右边的最大的数的索引和左边的比这个数小的数的索引交换位置就能保证换完的数是一个最大。先遍历一遍,找到最大的数,然后从右到左看数字是否比这个最大的数大。

但是注意保证在求maxId时候,尽量保证其靠近右侧。

class Solution {
public:int maximumSwap(int num) {string stringnum = to_string(num);int n = stringnum.size();int maxId = n - 1;int idx1 = -1;int idx2 = -1;for(int i = n - 1; i >= 0; i--){if(stringnum[i] > stringnum[maxId]){maxId = i;       } else if (stringnum[i] < stringnum[maxId]){idx1 = i;idx2 = maxId;}}if(idx1 >= 0){swap(stringnum[idx1],stringnum[idx2]);return stoi(stringnum);}else return num;}
};

【1.23】2765.最长交替子数组

2765. 最长交替子数组icon-default.png?t=N7T8https://leetcode.cn/problems/longest-alternating-subarray/

这道题目第一思路就是双重循环,类似于双指针,让后边的指针指向的数减去前面的数根据奇数偶数分为0和1即可。看题解以后,发现其实可以降低复杂度为o(n)

方法一: 双重循环 

class Solution {
public:int alternatingSubarray(vector<int>& nums) {int res = -1;for(int i = 0; i < nums.size(); i++){for(int j = i + 1; j < nums.size();j++){int length = j - i + 1;if(nums[j] - nums[i] == (length + 1) % 2){res = max(res,length);} else {break;}}}return res;}
};

 方法二: 单重循环 

考虑到当内层循环在第i个不满足条件时,不需要从初始+1外层循环继续开始,因为如果从初始 +1开始,到第i个一定会断,而且长度要比原来的要小。

所以可以直接从i+1继续遍历,但是要注意第i个断了以后,要考虑假如第i个减第i-1个正好是1的时候需要给在新的数组中算上。

class Solution {
public:int alternatingSubarray(vector<int>& nums) {int res = -1;int j = 0;//前指针for(int i = 1; i < nums.size(); i++){int length = i -j +1;if(nums[i] - nums[j] == (length + 1) % 2){res = max(res,length);} else {if(nums[i] - nums[i-1] == 1){j = i-1;res = max(res,2);  }else{j = i;}}}return res;}
};

【1.24】2865.美丽塔

【1.24】2866.美丽塔Ⅱ

2865. 美丽塔 Iicon-default.png?t=N7T8https://leetcode.cn/problems/beautiful-towers-i/

本题可以直接暴力求解,外层遍历让每一个值都当做峰值,内层循环从中间向两边都递减。 同时补充了一道美丽塔Ⅱ

方法一:暴力枚举 

class Solution {
public:long long maximumSumOfHeights(vector<int>& maxHeights) {long long res = 0;int n = maxHeights.size();for(int i = 0; i < n; i++){//外层分别设为峰顶int   pre = maxHeights[i];long long sum = pre;for(int j = i - 1 ;j >= 0; j--){pre = min(pre,maxHeights[j]);sum += pre;}int  suf = maxHeights[i];for(int j = i + 1; j < n; j++){suf = min(suf,maxHeights[j]);sum += suf;}res = max(res,sum);}return res;}
};

 值得注意的点数据类型要匹配,在函数种定义的maxheights 的值都是int类型,在比较min的过程中,要求两个数的定义都是int类型,而函数返回的是long long,所以定义的sum值是longlong类型。

整体思路是设置每一个值为峰值,然后都向左向右递减用最小值。然后对sum求最大值即可。

补充题目:2866.美丽塔22866. 美丽塔 IIicon-default.png?t=N7T8https://leetcode.cn/problems/beautiful-towers-ii/ 题目一模一样,唯一的区别就是数据量大,不让用枚举了。

这时候就用到第二个方法,单调栈。 

方法二:单调栈

由于题目要求一个峰值,然后两边都是单调的,而且两边逻辑一样,所以我们可以考虑一边,每一边都使用单调栈,对单调栈的操作,首先要进行一个while的pop,因为我们要求栈内元素单调递增的,当出现下边这种情况的时候,为了迁就后边的元素,前面的要弹出(但是要注意我们栈里存储的是下标index),弹出以后,如果这个栈是空的,就让i以前的数都等于maxHeights【i】即可,如果有元素,那么把以前的元素加着pre【top -1】,让后边的都等于maxHeights【i】即可。最后别忘了把下标push进去。然后右边是同理的,最后别忘了峰顶算了两次,减去一次。

class Solution {//单调栈解法,时间复杂度o(n)
public:long long maximumSumOfHeights(vector<int>& maxHeights) {int n = maxHeights.size();long long res = 0;vector<long long>pre(n), suf(n);stack<int> stk1,stk2;//两个栈存放当前峰值左/右构造的最大值for(int i = 0; i < n; ++i){while(!stk1.empty() && maxHeights[stk1.top()] > maxHeights[i]){ stk1.pop();}if(stk1.empty()){pre[i] = (long long )(i + 1) * maxHeights[i];}else{pre[i] = pre[stk1.top()] + (long long )(i - stk1.top()) * maxHeights[i];}stk1.push(i);//把下标push进去}for(int i = n -1; i >= 0; --i){while(!stk2.empty() && maxHeights[stk2.top()] > maxHeights[i]){stk2.pop();}if(stk2.empty()) {suf[i] = (long long )(n - i) * maxHeights[i];}else{suf[i] = suf[stk2.top()] + ((long long)(stk2.top() - i)) * maxHeights[i];}stk2.push(i);res = max(res,suf[i] + pre[i] - maxHeights[i]);//maxHeights[i]算了两遍}return res;}
};

【1.25】2859.计算k置下标对应元素的和

2859. 计算 K 置位下标对应元素的和icon-default.png?t=N7T8https://leetcode.cn/problems/sum-of-values-at-indices-with-k-set-bits/

 本题其实就是一个求二进制的简单题目,大概率会想到用位运算解决

在c++中&表示的是按位与运算。当计算二进制中有多少个1的时候,可以配合位元算

num & (1 << i);//统计每一位上有1的数
sum++;//配合sum++可以统计二进制中是1的位的个数

 注意一点这个循环的大小,因为是int类型,最高就是32位,直接小于32就行

class Solution {
public:int sumIndicesWithKSetBits(vector<int>& nums, int k) {int res = 0;for(int i = 0; i< nums.size();i++){if(count(i) == k){res+= nums[i];}}return res;}int count(int num){int sum = 0;for(int i = 0; i < 32; i++){if(num & (1 << i)){sum++;}} return sum;}
};

 除了位元算,还有一种可以求一个数二进制的置为1的个数方法

int count(int num){int sum = 0;while(num){sum += (num % 2);num /= 2;}return sum;}

【1.26】2846.边权重均等查询

2846. 边权重均等查询icon-default.png?t=N7T8https://leetcode.cn/problems/minimum-edge-weight-equilibrium-queries-in-a-tree/

2500+分hard题,超出水平范围太多,暂时跳过。 

【1.27】2861.最大合金数

2861. 最大合金数icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-number-of-alloys/

看题目“所有合金都需要由同一台机器制造。”又给了个最大值budget,让求取得的最大合金数,也满足二段性,那就是二分法求解了,因为设置这个mid,当我们最大数设置为mid,那么比mid小的数就都不能取了。

 1.设置这个二分,第一个点就是最大值可以稍微的小一点,我们可以设置为budget/1(单价最小就是1)+ 库存的最大量(其实根据木桶效应,应该是库存的最小量)

2.先置为false,遍历每一个机器的花费,再内层遍历每一个零件,求出每个零件加起来总共的spend,再和budget比对,如果比这个小,那么这个mid可以取,就进行变换,置为true,如果不行,再改right

3.在内层遍历的时候,要考虑if(composition[i][j] * (long)mid - stock[j] > 0),这个很关键,库存够了就置为0,不能是负数,我一直卡在这。

//花费小于budget,求能创造合金的最大值,二分
class Solution {
public:int maxNumberOfAlloys(int n, int k, int budget, vector<vector<int>>& composition, vector<int>& stock, vector<int>& cost) {int left = 0;
//右侧值不用设置太大,考虑最大值  auto max = max_element(stock.begin(),stock.end());   int right = *max + budget;int ans = 0;while(left <= right){int mid = left + ((right -left) / 2);//设置的最大值,当这个满足的时候,比他小的都不合适bool flag = false;//如果可以制造出就用true//遍历一遍每台机器花费for(int i = 0; i < k; i++){long spend = 0;for(int j = 0; j < n; j++){if(composition[i][j] * (long)mid - stock[j] > 0){spend += (composition[i][j] * (long)mid - stock[j]) * cost[j];}}if(budget >= spend){flag = true;break;//第i类就能搞定了}}if(flag){ans = mid;left = mid + 1;}else{right = mid -1;}}return ans;}
};

【1.28】365.水壶问题

365. 水壶问题icon-default.png?t=N7T8https://leetcode.cn/problems/water-and-jug-problem/

这个问题除了用深度优先搜索(也是刚会用的),还可以用数学方法更好操作,贝祖定理解决,但是需要考虑的问题比较多。

1.先分析一下,这些操作的实质其实这个水的总量变化只能是x或者是y,因为首先操作的结果至少有一个桶是空的有一个是满的(把一个倒掉,或者加满),假如说把一个半满的水加满或者倒掉是没有意义的,因为等价于一开始就把它置为0或者加满。

2.所以我们的目标变成了找到一堆数组a和b来满足ax + by = z,那么只需满足z <= x + y的情况下, 如果a >  0,b > 0一定ok,如果a  < 0,操作就是先给b加满,把b到给a,a倒掉,再把b剩下的到给a,如此反复。如果是b < 0 ,把操作反过来就行。

3.贝祖定理表示,如果要实现ax + by = z,只需要z整除x和y的最大公约数即可。

class Solution {
public:bool canMeasureWater(int jug1Capacity, int jug2Capacity, int targetCapacity) {if(jug1Capacity + jug2Capacity < targetCapacity){return false;}//这里贝组定理用之前考虑x或者y万一是0没有最大公约数if(jug1Capacity == 0 ||jug2Capacity ==0){return targetCapacity == 0 || jug1Capacity + jug2Capacity == targetCapacity; }else{return targetCapacity % gcd(jug1Capacity,jug2Capacity) == 0;}}
};

【1.29】514.自由之路

514. 自由之路icon-default.png?t=N7T8https://leetcode.cn/problems/freedom-trail/

这是一道困难题,思路能想到是用dp来解,但是解法还是有一定难度的。分为几个步骤,逻辑要清晰。

  1. 代码主要分为几个步骤,首先是对king进行字母到位置的映射,然后创建dp初始化,然后dp函数的实现。
  2. 创建位置索引的时候,这种映射的构建是为了在后续动态规划的过程中更方便地获取每个字符在环形拨盘上的位置信息。
  3. dp初始化初始值给个最大值

  4. 动态规划转移要分类,在i==0的时候第一个字符,不需要考虑前一个字符的位置,所以分开,对于不是第一个字符要进行一遍循环(对上一个字符的位置循环),进行dp函数的编写,最后输出dp最后一行的最小值

  5. 对于这种环形的可以顺时针逆时针转动的函数求最小值,这个函数值得记一下,加一个len就能完美解决负数问题。

    class Solution {
    public:int getMin(int len,int a, int b){return min((len + a - b) % len ,(len + b - a) % len);}int findRotateSteps(string ring, string key) {
    //第一步先建立ring中字母的位置索引vector<int> pos[26];for(int i = 0; i < ring.size(); i++){pos[ring[i] - 'a'].push_back(i);}//第二步,创建dp初始化vector<vector<int>> dp(key.size(),vector<int>(ring.size(),INT_MAX));//第三步 动态规划状态转移for(int i = 0; i < key.size(); i++){//遍历key的每个字符for(auto j : pos[key[i] - 'a']){//遍历key【i】在圆盘出现的每个位置if(i == 0){dp[i][j] = min(dp[i][j],0 + getMin(ring.size(),0,j) + 1);continue;}//如果不是第一个,遍历前一个的字符的位置状态for(auto k : pos[key[i - 1] - 'a']){dp[i][j] = min(dp[i][j],dp[i - 1][k] + getMin(ring.size(),k,j) + 1);} }}return *min_element(dp.back().begin(),dp.back().end());}
    };

 【1.30】2808.使循环数组所有元素相等的最少秒数

2808. 使循环数组所有元素相等的最少秒数icon-default.png?t=N7T8https://leetcode.cn/problems/minimum-seconds-to-equalize-a-circular-array/

1900分左右的题目,用哈希表解决,思路不算难,主要是昨天的题给了思路,一看题目就知道是一个圆环形状的,左右都能走。哈希表存一下出现的元素的索引i用数组存,因为可能有多个。按照圆环找mx/2的最小值就行。 

  1.  先搞个哈希表,每个nums【i】对应的i值存到数组里,为了后续遍历的时候用
  2. 按照圆的方案去找相邻最远的值,求每个nums【i】的数值里距离最远的值,然后找最小值求出来即可。
  3. 在找个遍历中,先+n为了找圆环情况两个的距离,后边遍历的是相邻的。
class Solution {
public:int minimumSeconds(vector<int>& nums) {unordered_map<int,vector<int>> map;int res = nums.size();//先搞个哈希表,每个nums【i】对应的i值存到数组里for(int i = 0; i < nums.size(); i++){map[nums[i]].push_back(i);}//不要忘了找圈for(auto&  s : map){int mx  = s.second[0] + nums.size() - s.second.back();for(int i = 1; i < s.second.size(); i++){mx = max(mx, s.second[i] - s.second[i - 1]);}res = min(res, mx/2);}return res;}
};

【1.31】2760.找出不同元素数目差数组

2670. 找出不同元素数目差数组icon-default.png?t=N7T8https://leetcode.cn/problems/find-the-distinct-difference-array/

哈希表,难点在于建立数组的时候的范围还有,运用哈希表去统计“从第i个数到最后一个数不同的数的数量”和“从第一个数到第i个数不同数的数量”

class Solution {
public:vector<int> distinctDifferenceArray(vector<int>& nums) {int n = nums.size();vector<int> res;unordered_set<int> st;vector<int> suf(n + 1);//为了满足后边运算的时候suf(n -1)for(int i =  n - 1; i > 0; i--){st.insert(nums[i]);suf[i] = st.size();//从第i开始到结尾不同值的数量}st.clear();for(int i = 0; i < n; i++){st.insert(nums[i]);//从第一个数开始到第i个数不同值的数量res.push_back(st.size() -suf[i + 1]);}return res;}
};

创建suf数组大小是n+1的时候,是为了后边满足运算的时候suf(n  - 1). 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/660141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

哪个牌子的头戴式耳机好?推荐性价比高的头戴式耳机品牌

随着科技的不断发展&#xff0c;耳机市场也呈现出百花齐放的态势&#xff0c;从高端的奢侈品牌到亲民的平价品牌&#xff0c;各种款式、功能的耳机层出不穷&#xff0c;而头戴式耳机作为其中的一员&#xff0c;凭借其优秀的音质和降噪功能&#xff0c;受到了广大用户的喜爱&…

ArrayList在添加元素时报错java.lang.ArrayIndexOutOfBoundException

一、添加单个元素数组越界分析 add源码如下 public boolean add(E e) {ensureCapacityInternal(size 1); // Increments modCount!!elementData[size] e;return true; } size字段的定义 The size of the ArrayList (the number of elements it contains). ArrayList的大…

雷达DoA估计的跨行业应用--麦克风阵列声源定位(Matlab仿真)

一、概述 麦克风阵列&#xff1a; 麦克风阵列是由一定数目的声学传感器&#xff08;麦克风&#xff09;按照一定规则排列的多麦克风系统&#xff0c;而基于麦克风阵列的声源定位是指用麦克风拾取声音信号&#xff0c;通过对麦克风阵列的各路输出信号进行分析和处理&#xff0c;…

力扣hot100 跳跃游戏 贪心

Problem: 55. 跳跃游戏 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考 挨着跳&#xff0c;记录最远能到达的地方 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( 1 ) O(1) O(1) Code class Solution {public boolean canJump(int[] nums)…

7 STL

1、STL简介 1.1基本概念 可复用利用的东西&#xff01; 面向对象和泛型编程&#xff08;模板&#xff09;的 目的->提升复用性 为了建立数据结构和算法的一套标准->STL横空出世 STL(Standard Template Liberary)标准模板库广义分&#xff1a;容器、算法、迭代器容器…

lwIP 初探(第一节)

一、TCP/IP 协议栈架构 网络协议有很多&#xff0c;如 MQTT、TCP、UDP、IP 等协议&#xff0c;这些协议组成了 TCP/IP 协议栈&#xff0c; 同时&#xff0c;这些协议具有层次性&#xff0c;它们分布在应用层&#xff0c;传输层和网络层。TCP/IP 协议栈的分层结 构和网络协议得…

百无聊赖之JavaEE从入门到放弃(十五)包装类

目录 一.包装类概念 二.自动装箱和拆箱 三.包装类的缓存问题 一.包装类概念 基本数据类型的包装类 我们前面学习的八种基本数据类型并不是对象&#xff0c;为了将基本类型数据和对象之间实现互 相转化&#xff0c;Java 为每一个基本数据类型提供了相应的包装类。 Java 是…

八斗学习笔记

1 初始环境安装 Anaconda安装(一款可以同时创建跟管理多个python环境的软件) https://blog.csdn.net/run_success/article/details/134656460 Anaconda创建一个新python环境(安装人工智能常用的第三方python包&#xff0c;如&#xff1a;tensorflow、keras、pytorch) https://…

12nm工艺,2.5GHz频率,低功耗Cortex-A72处理器培训

“ 12nm工艺&#xff0c;2.5GHz频率&#xff0c;低功耗Cortex-A72处理器培训” 本项目是真实项目实战培训&#xff0c;低功耗UPF设计&#xff0c;后端参数如下&#xff1a; 工艺&#xff1a;12nm 频率&#xff1a;2.5GHz 资源&#xff1a;2000_0000 instances 为了满足更多…

中科大计网学习记录笔记(二):网络核心

前言&#xff1a; 学习视频&#xff1a;中科大郑烇、杨坚全套《计算机网络&#xff08;自顶向下方法 第7版&#xff0c;James F.Kurose&#xff0c;Keith W.Ross&#xff09;》课程 该视频是B站非常著名的计网学习视频&#xff0c;但相信很多朋友和我一样在听完前面的部分发现信…

科技云报道:云原生PaaS,如何让金融业数字化开出“繁花”?

科技云报道原创。 在中国金融业数字化转型的历史长卷中&#xff0c;过去十年无疑是一部磅礴的史诗。 2017年&#xff0c;南京银行第一次将传统线下金融业务搬到了线上。那一年&#xff0c;它的互联网金融信贷业务实现了过去10年的业务总额。 2021年&#xff0c;富滇银行通过…

Parrot系统下ROS1试用CoCubeSim

Ubuntu 22.04安装和使用ROS1可行吗_ubuntu22.04安装ros1-CSDN博客 Parrot系统 如果你还不了解这个系统&#xff0c;如下文字就不用接着看了。 为何使用 为何更好的应用各类互联网信息&#xff0c;仅此而已。 开发利器 终端 ROS1和ROS2支持所有操作系统&#xff0c;支持的硬件…

【金蝶BI方案】用一张报表,分析生产完成情况

当老板问生产完成地怎样&#xff1f;难道还能拿出一叠报表让老板逐个细看&#xff1f;奥威-金蝶BI方案只用一张BI数据可视化报表就把整个生产完成情况给讲明白了。甚至还能满足老板想从不同角度进行分析的需求。 奥威-金蝶BI方案-BI生产完成情况报表 这张报表总结计算了生产合…

【CSS】css获取子元素的父元素,即通过子元素选择父元素(使用CSS伪类 :has() :not() )

这里写目录标题 一、:has获取第一个div获取包含 a.active 的 li获取第二个div 二、:not除了类名为active 的 a,其他的a的字体都为18px <div><h1>标题</h1></div><div><ul><li><a href"#" class"active">测…

微服务中间件 RabbitMq学习

1、为什么需要Mq 例如在用户注册业务中&#xff0c;用户注册成功后 需要发注册邮件和注册短信&#xff0c;传统的做法有两种 1.串行的方式&#xff1b;2.并行的方式 &#xff1b; 假设三个业务节点分别使用50ms&#xff0c;串行方式使用时间150ms&#xff0c;并行使用时间10…

如何编写具有完备性的测试用例 ? 具体思路是什么 ? 全套解决方案打包呈现给你 。

设计测试用例应该算是测试人员最为主要的工作之一 &#xff0c;好的测试用例往往具有覆盖性强 &#xff0c;扩展性高以及复用性好等特点 。该如何设计出好的测试用例 &#xff1f;是我们每一位测试人员需要重点思考的问题 &#xff0c;下面是我对设计测试用例设计的思考 &#…

代码随想录 Leetcode40.组合总和 II

题目&#xff1a; 代码&#xff08;首刷看解析 2024年2月1日&#xff09;&#xff1a; class Solution { public:vector<vector<int>> res;vector<int> path;void backtracking(vector<int>& candidates, int target, int startIndex, vector<…

opencv#41 轮廓检测

轮廓概念介绍 通常我们使用二值化的图像进行轮廓检测&#xff0c;对轮廓以外到内进行数字命名&#xff0c;如下图&#xff0c;最外面的轮廓命名为0&#xff0c;向内部进行扩展&#xff0c;遇到黑色白色相交区域&#xff0c;就是一个新的轮廓&#xff0c;然后依次对轮廓进行编号…

玛格全屋定制携手君子签,实现业务信息、流程、合同全面数字化

中国定制家居领导品牌——玛格全屋定制携手君子签&#xff0c;部署玛格业务系统&#xff0c;将电子签章系统与供应链上下游业务合同签署场景融合&#xff0c;通过无纸化、电子化的签署环境&#xff0c;打造业务“线上审批、签署、归档”闭环&#xff0c;助推业务减负提效。 电…

prometheus的alertmanager监控报警

监控告警&#xff1a; alert是一个单独的模块&#xff0c;需要我们单独的配置。 需要声明一个邮箱地址。配置是以configmap进行部署。 alert 实验&#xff1a; vim alert-cfg.yaml apiVersion: v1 kind: ConfigMap metadata:name: alertmanagernamespace: monitor-sa data…