leetcode刷题日记
<day 2021/10/20>
453. 最小操作次数使数组元素相等 简单
给你一个长度为 n
的整数数组,每次操作将会使 n - 1
个元素增加 1
。返回让数组所有元素相等的最小操作次数。
示例 1:
输入:nums = [1,2,3]
输出:3
解释:
只需要3次操作(注意每次操作会增加两个元素的值):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
示例 2:
输入:nums = [1,1,1]
输出:0
提示:
n == nums.length
1 <= nums.length <= 105
-109 <= nums[i] <= 109
- 答案保证符合 32-bit 整数
解题思路:
因为是n-1个元素加一,所以也可以理解为一个元素减一,那么只需要找到最小值,并且便利容器每个元素减去最小值的结果相加就可以了。
实现代码:
class Solution {
public:
int minMoves(vector<int>& nums) {
int num=nums[0];
for(int i=0;i<nums.size();i++)
{
if(num>nums[i])
{
num=nums[i];
}
}
int res=0;
for(int i=0;i<nums.size();i++)
{
res+=nums[i]-num;
}
return res;
}
};
官方解法:
class Solution {
public:
int minMoves(vector<int>& nums) {
int minNum = *min_element(nums.begin(),nums.end());
int res = 0;
for (int num : nums) {
res += num - minNum;
}
return res;
}
};
很简洁了,使用的min_element找的最小值,原谅我刚看了c++ primer的vector也不知道有这个函数。
454. 四数相加 II 中等
给你四个整数数组 nums1
、nums2
、nums3
和 nums4
,数组长度都是 n
,请你计算有多少个元组 (i, j, k, l)
能满足:
- 0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
示例 1:
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
输出:2
解释:
两个元组如下:
1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
示例 2:
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
输出:1
提示:
n == nums1.length
n == nums2.length
n == nums3.length
n == nums4.length
1 <= n <= 200
-228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228
解题思路:
自己想了半天啥也没想出来,只好看了解题,大概思路就是将ab分为一组,cd分为另一组,并存入map容器中去,然后map中的key为a,b的两数之和,值为两数之和出现的次数,然后再求cd的两数之和,将其值的负数拿到ab储存的容器中查找,若存在说明符合题目条件。
实现代码:
class Solution {
public:
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
int res=0;
map<int,int>ab_map;
for(auto a:A)
{
for(auto b:B)
{
ab_map[a+b]++;
}
}
for(auto c:C)
{
for(auto d:D)
{
if(ab_map.find(0-(c+d))!=ab_map.end())
{
res+=ab_map[0-(c+d)];
}
}
}
return res;
}
};
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uK5x96MN-1635512165962)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211020221423403.png)]
不太行,再试试官方解法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-73R4e47n-1635512165963)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211020221800324.png)]
看了看代码,官方解法判断cd和的负数在ab的map容器中是否存在的方法是count函数,而我使用的是find函数,可能会更耗时。改了一下代码,发现事与愿违。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z7XgdVPu-1635512165965)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211020222132285.png)]
仔细看,发现官方解法使用的是unordered_map,也就是无序map容器,仔细一想,元素是否排序对本题并无帮助,所以排序的话反而会执行时间。改掉再试试。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ENBlfJY-1635512165966)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211020222400239.png)]
很不错,执行时间明显变快了。
大佬解法:
class Solution {
public:
int fourSumCount(vector<int> &A, vector<int> &B, vector<int> &C, vector<int> &D) {
int res = 0;
map<int, int> map;
for (const auto &a : A) for (const auto &b : B) ++map[a + b];
for (const auto &c : C) for (const auto &d : D) res += map[-(c + d)];
return res;
}
};
太简洁了!
66. 加一 简单
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 1:
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。
示例 2:
输入:digits = [4,3,2,1]
输出:[4,3,2,2]
解释:输入数组表示数字 4321。
示例 3:
输入:digits = [0]
输出:[1]
提示:
1 <= digits.length <= 100
0 <= digits[i] <= 9
解题思路:
怎么解呢?第一个想到的方法是将数组转化为整数,本来以为这是个简单的方法,转化为整数十分容易,可是再将其转化为vector数组时才发现,自己还得把开头为9进位的情况单独列出一个if判断,好的,我加,可是还是提交失败了,看了报错信息与输入失败的样例,我…,还是直接修改数组吧。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OTMCE0HV-1635512165966)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20211021100826251.png)]
太艰难了,先是在重新输入为数组的时候卡了半天,又在开头为9导致进位的情况卡了半天,最后系统给了个长度为10的数组样例,int型肯定放不下,我改成long long型,结果直接又来了个19位的数组,qaq。
实现代码:
class Solution { //这是第一遍用的转换为整数的放大,对于10位数以内的还是很有效的(不考虑执行时间和内存占用的话)
public:
vector<int> plusOne(vector<int>& digits) {
int i;
long long sum, n=1;
for(i=0,sum=0;i<digits.size();i++)
{
n*=10;
sum*=10;
sum+=digits[i];
}
n/=10;
sum++;
if(sum/n==10)
{
n*=10;
digits.push_back(0);
}
for(i=0;i<digits.size();i++)
{
digits[i]=(int)(sum/n);
sum%=n;
n/=10;
}
return digits;
}
};
官方解法
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
int n = digits.size();
for (int i = n - 1; i >= 0; --i) {
if (digits[i] != 9) {
++digits[i];
for (int j = i + 1; j < n; ++j) {
digits[j] = 0;
}
return digits;
}
}
// digits 中所有的元素均为 9
vector<int> ans(n + 1);
ans[0] = 1;
return ans;
}
};
思路很简单,若最后一位不为9,加个一就完事了,为9的话,一直往前找到不为9的数,加一并把后面的数(也就是都为9的数)置0就可以了。
67. 二进制求和 简单
给你两个二进制字符串,返回它们的和(用二进制表示)。
输入为 非空 字符串且只包含数字 1
和 0
。
示例 1:
输入: a = "11", b = "1"
输出: "100"
示例 2:
输入: a = "1010", b = "1011"
输出: "10101"
提示:
- 每个字符串仅由字符
'0'
或'1'
组成。 1 <= a.length, b.length <= 10^4
- 字符串如果不是
"0"
,就都不含前导零。 </