2022-02-20每日刷题打卡
力扣——每日一题
717. 1比特与2比特字符
有两种特殊字符:
第一种字符可以用一个比特 0 来表示
第二种字符可以用两个比特(10 或 11)来表示、
给定一个以 0 结尾的二进制数组 bits ,如果最后一个字符必须是一位字符,则返回 true 。
示例 1:
输入: bits = [1, 0, 0]
输出: true
解释: 唯一的编码方式是一个两比特字符和一个一比特字符。
所以最后一个字符是一比特字符。
一个个遍历,如果遍历到是0就遍历下一个(可以把它看成单字符),如果遇到1,就跳过下一个字符,如果跳过的下一个字符是最后一个字符,说明最后一个字符不能当作单字符,返回false。反之返回true。顺便可以一开始就判断一下最后一个字符是不是0,如果不是0那肯定不算单字符。
class Solution {
public:
bool isOneBitCharacter(vector<int>& bits) {
int n=bits.size();
if(bits[n-1]!=0)return false;
for(int i=0;i<n-1;i++)
{
if(bits[i]==0)
continue;
else
{
i++;
if(i==n-1)return false;
}
}
return true;
}
};
6012. 统计各位数字之和为偶数的整数个数
给你一个正整数 num ,请你统计并返回 小于或等于 num 且各位数字之和为 偶数 的正整数的数目。
正整数的 各位数字之和 是其所有位上的对应数字相加的结果。
示例 1:
输入:num = 4
输出:2
解释:
只有 2 和 4 满足小于等于 4 且各位数字之和为偶数。
就这么写咯,遍历然后一个个判断数的各位和是否是偶数
class Solution {
public:
bool get_num(int num)
{
int res = 0;
string str = to_string(num);
for (int i = 0; i < str.size();i++)
{
res += str[i] - '0';
}
if (res % 2 == 0)return true;
return false;
}
int countEven(int num) {
int n=num, res = 0;
for (int i = 1; i <= n; i++)
{
if (get_num(i))
{
res ++;
}
}
return res;
}
};
6013. 合并零之间的节点
给你一个链表的头节点 head ,该链表包含由 0 分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足 Node.val == 0 。
对于每两个相邻的 0 ,请你将它们之间的所有节点合并成一个节点,其值是所有已合并节点的值之和。然后将所有 0 移除,修改后的链表不应该含有任何 0 。
返回修改后链表的头节点 head 。
示例 1:
输入:head = [0,3,1,0,4,5,2,0]
输出:[4,11]
解释:
上图表示输入的链表。修改后的链表包含:
- 标记为绿色的节点之和:3 + 1 = 4
- 标记为红色的节点之和:4 + 5 + 2 = 11
遍历链表,计算非0节点的总和,如果遇到0节点且计算的总和不为0,就用总和创建一个节点,然后总和清零继续遍历链表。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeNodes(ListNode* head) {
ListNode*p=head;
ListNode*q=new ListNode();
ListNode*m=q;
int res=0;
while(p!=NULL)
{
if(p->val!=0)
res+=p->val;
else
{
ListNode*o=new ListNode(res);
res=0;
q->next=o;
q=q->next;
}
p=p->next;
}
if(res!=0)
{
ListNode*o=new ListNode(res);
res=0;
q->next=o;
q=q->next;
}
return m->next->next;
}
};
5996. 统计数组中相等且可以被整除的数对
给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 k ,请你返回满足 0 <= i < j < n ,nums[i] == nums[j] 且 (i * j) 能被 k 整除的数对 (i, j) 的 数目 。
示例 1:
输入:nums = [3,1,2,2,2,1,3], k = 2
输出:4
解释:
总共有 4 对数符合所有要求:
- nums[0] == nums[6] 且 0 * 6 == 0 ,能被 2 整除。
- nums[2] == nums[3] 且 2 * 3 == 6 ,能被 2 整除。
- nums[2] == nums[4] 且 2 * 4 == 8 ,能被 2 整除。
- nums[3] == nums[4] 且 3 * 4 == 12 ,能被 2 整除。
从左往右遍历数组,每次以一个地方为起点遍历数组,判断是否符合题目要求,满足则计数器++,最后返回计数器。
class Solution {
public:
int countPairs(vector<int>& nums, int k) {
int n=nums.size(),res=0;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(nums[i]==nums[j]&&i*j%k==0)res++;
}
}
return res;
}
};
5997. 找到和为给定整数的三个连续整数
给你一个整数 num ,请你返回三个连续的整数,它们的 和 为 num 。如果 num 无法被表示成三个连续整数的和,请你返回一个 空 数组。
示例 1:
输入:num = 33
输出:[10,11,12]
解释:33 可以表示为 10 + 11 + 12 = 33 。
10, 11, 12 是 3 个连续整数,所以返回 [10, 11, 12] 。
计算一个平均数,如果是三个连续整数相加,那么这三个整数的平均数也是整数且平均数也是中位数,很简单的证明,三个连续的整数是:a-1,a,a+1,总和就是3a,平均数就是:3a/3=a,也是中间数a。
那么我们就直接对num/3,看得到的数是否是整数(但因为计算机的计算有问题,10/3这种的也会得到整数,此时我们把得到的除数*3看是否等于num即可),然后得到的数就是三个连续数的中位数,再依次把数存入数组里即可。
class Solution {
public:
vector<long long> sumOfThree(long long num) {
long long ans=num/3;
vector<long long>v;
if(ans*3==num)
return {ans-1,ans,ans+1};
return {};
}
};
5998. 拆分成最多数目的偶整数之和
给你一个整数 finalSum 。请你将它拆分成若干个 互不相同 的偶整数之和,且拆分出来的偶整数数目 最多 。
比方说,给你 finalSum = 12 ,那么这些拆分是 符合要求 的(互不相同的偶整数且和为 finalSum):(2 + 10) ,(2 + 4 + 6) 和 (4 + 8) 。它们中,(2 + 4 + 6) 包含最多数目的整数。注意 finalSum 不能拆分成 (2 + 2 + 4 + 4) ,因为拆分出来的整数必须互不相同。
请你返回一个整数数组,表示将整数拆分成 最多 数目的偶整数数组。如果没有办法将 finalSum 进行拆分,请你返回一个 空 数组。你可以按 任意 顺序返回这些整数。
示例 1:
输入:finalSum = 12
输出:[2,4,6]
解释:以下是一些符合要求的拆分:(2 + 10),(2 + 4 + 6) 和 (4 + 8) 。
(2 + 4 + 6) 为最多数目的整数,数目为 3 ,所以我们返回 [2,4,6] 。
[2,6,4] ,[6,2,4] 等等也都是可行的解。
贪心解法,有两点:
一是要注意finalSum必须是偶数,毕竟一堆偶数绝不可能组合出一个奇数。
二是因为要求数目最多,所以我们从最小的偶数2开始组合,同样的finalSum,只要组合的数小,那数目就会多。
我们从2开始循环,每次加2,计算所有遍历过的数的总和,并且用哈希表记录下来,如果总和等于finalSum了结束循环,从哈希表里把用过的数全部取出来存入一个数组里返回。如果总和小于finalSum就继续算,如果大于了finalSum的话,就把总和和finalSum的差值的数去掉,比如finalSum是18,2+4+6+8=20,我们就把20-18=2去掉(在哈希表里,把那个数的出现次数减为0,这样在从哈希表里取数时就不会取到它了),最后就是4 6 8.然后因为减完后总和等于finalSum,我们就把用过的数都存入数组返回。
class Solution {
public:
vector<long long>v;
vector<long long> maximumEvenSplit(long long finalSum) {
if(finalSum%2==1)return v;
long long res=0;
unordered_map<long long,int>mymap;
for(int i=2;i<=finalSum;i+=2)
{
res+=i;
if(res==finalSum)
{
mymap[i]++;
break;
}
else if(res<finalSum)
{
mymap[i]++;
}
else if(res>finalSum)
{
mymap[i]++;
mymap[res-finalSum]--;
break;
}
}
for(auto i:mymap)
{
if(i.second!=0)v.push_back(i.first);
}
return v;
}
};
一本通——动态规划
1258:【例9.2】数字金字塔
【题目描述】
观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。
在上面的样例中,从1313到88到2626到1515到2424的路径产生了最大的和8686。
【输入】
第一个行包含R(1≤R≤1000)R(1≤R≤1000),表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
所有的被供应的整数是非负的且不大于100100。
【输出】
单独的一行,包含那个可能得到的最大的和。
【输入样例】
5
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11
【输出样例】
86
我们从下往上走,每次取两个相邻数的最大值加到上一层,直到加到最顶上,那个就是可以得到的最大总和。
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<string.h>
#include<string>
#include<unordered_map>
#include<math.h>
#include<queue>
const int N = 1010;
int f[N][N],h[N][N];
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
for (int j = 0; j <= i; j++)
{
cin >> f[i][j];
}
}
for (int i = n; i >=0 ; i--)
{
for (int j = 0; j < n; j++)
{
f[i][j] += max(f[i + 1][j], f[i + 1][j + 1]);
}
}
cout << f[0][0] << endl;
return 0;
}
1265:【例9.9】最长公共子序列
【题目描述】
一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X=<x1,x2,…,xm>X=<x1,x2,…,xm>,则另一序列Z=<z1,z2,…,zk>Z=<z1,z2,…,zk>是X的子序列是指存在一个严格递增的下标序列<i1,i2,…,ik><i1,i2,…,ik>,使得对于所有j=1,2,…,k有:
Xij=ZjXij=Zj
例如,序列Z=<B,C,D,B>是序列X=<A,B,C,B,D,A,B>的子序列,相应的递增下标序列为<2,3,5,7>。给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X=<A,B,C,B,D,A,B>和Y=<B,D,C,A,B,A>,则序列<B,C,A>是X和Y的一个公共子序列,序列 <B,C,B,A>也是X和Y的一个公共子序列。而且,后者是X和Y的一个最长公共子序列.因为X和Y没有长度大于4的公共子序列。
给定两个序列X=<x1,x2,…,xm>X=<x1,x2,…,xm>和Y=<y1,y2….yn>Y=<y1,y2….yn>.要求找出X和Y的一个最长公共子序列。
【输入】
共有两行。每行为一个由大写字母构成的长度不超过1000的字符串,表示序列X和Y。
【输出】
第一行为一个非负整数。表示所求得的最长公共子序列的长度。若不存在公共子序列.则输出文件仅有一行输出一个整数0。
【输入样例】
ABCBDAB
BDCABA
【输出样例】
4
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<string.h>
#include<string>
#include<unordered_map>
#include<math.h>
#include<queue>
const int N = 1010;
int f[N][N];
int main()
{
string str1, str2;
cin >> str1 >> str2;
int n = str1.size(), m = str2.size();
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (str1[i - 1] == str2[j - 1])f[i][j] = f[i - 1][j - 1] + 1;
else f[i][j] = max(f[i - 1][j], f[i][j - 1]);
}
}
cout << f[n][m];
return 0;
}
蓝桥杯——历届真题
历届真题 成绩分析【第十一届】【省赛】【B组】
注意的地方就是输出两位小数。
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<string.h>
#include<string>
#include<unordered_map>
#include<math.h>
#include<queue>
int main()
{
int n, min_score = INT_MAX, max_score = 0, num;
double res = 0;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> num;
min_score=min(num, min_score);
max_score = max(num, max_score);
res += num;
}
cout << max_score << endl;
cout << min_score << endl;
res /= n;
printf("%.2f", res );
return 0;
}