2021-11-20每日刷题打卡
力扣——每日一题
594. 最长和谐子序列
和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。
现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。
数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。
示例 1:
输入:nums = [1,3,2,2,5,2,3,7]
输出:5
解释:最长的和谐子序列是 [3,2,2,2,3]
这题一开始没想到的点是可以对nums排序,因为想着子序列是不能改变顺序的,所以就没想到排序来写。但后来发现可以对nums排序,因为我们要找的只是序列里相减小于等于1的序列,比如举个例子来说1 2 5 3 1 2 3 5 2 3,这段的最长子序列是6,即2 3 2 3 2 3 ,中间的5 1 我们都不理他,而且因为只相差了1,所以排序起来他们也是的相邻,即222333,所以可以进行排序。
我们先用sort对nums进行排序,然后准备两个指针l和r,一开始都指向0,在准备一个存储最大子序列长度的变量max_len,开始遍历,当l>=nums.size()时结束遍历,每次遍历r先走,然后判断nums[r]-nums[l]是否小于等于1,如果满足那么r继续走,如果不满足就拿r-l判断当前子序列的长度,然后和max_len做对比取较大的,然后l++,并让r回到l的位置进行下一次遍历。最后返回最大值max_len。
class Solution {
public:
int findLHS(vector<int>& nums) {
sort(nums.begin(), nums.end());
int l = 0, r = 0, n = nums.size(), max_len = 0;
while (l < n)
{
if (r < n && nums[r] - nums[l] <= 1)r++;
else
{
if (nums[r-1] - nums[l] == 1)max_len = max(max_len, r - l);
r = ++l;
}
}
return max_len;
}
};
AcWing——算法基础
826. 单链表 - AcWing题库
实现一个单链表,链表初始为空,支持三种操作:
- 向链表头插入一个数;
- 删除第 k 个插入的数后面的数;
- 在第 k 个插入的数后插入一个数。
现在要对该链表进行 M 次操作,进行完所有操作后,从头到尾输出整个链表。
注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 22 个插入的数,…第 n 个插入的数。
输入格式
第一行包含整数 M,表示操作次数。
接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:
H x
,表示向链表头插入一个数 x。D k
,表示删除第 k 个插入的数后面的数(当 k 为 0 时,表示删除头结点)。I k x
,表示在第 k 个插入的数后面插入一个数 x(此操作中 k 均大于 0)。
输出格式
共一行,将整个链表从头到尾输出。
数据范围
1≤M≤100000
所有操作保证合法。
输入样例:
10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6
输出样例:
6 4 6 5
简单的一道实现连标题,但是这里我们不能用以往的方式来new节点一个个连,因为new的效率实在太慢,我们这里有10w次操作肯定要超时,这里我们采用另一种方式来写链表。
我们用两个数组来实现链表,一个数组e来存链节点的值,一个数组ne来存对应链节点的next,比如这样一个链表2 1 4 3,这就是e里面存的值,然后ne存的是{1,2,3,-1}(-1代表结尾),意思是第一个节点在e的位置为0,值为2,它的next指针存在ne里,因为他在e的位置为0,所以它的next的位置也为0,ne[0]等于1,说明这个节点的next指向的是下标为1的节点,在e里,下标为1的是1,然后这个e[1]节点的next指针指向的是ne[1]=2。就是这么简单,然后删除操作插入操作就按照这个格式来。(你要看不懂那就直接看代码吧)
#include<iostream>
using namespace std;
const int N=100010;
int head,idx,e[N],ne[N];
void init()
{
head=-1;
idx=0;
}
void push_head(int x)
{
e[idx]=x;
ne[idx]=head;
head=idx++;
}
void del_node(int k)
{
ne[k-1]=ne[ne[k-1]];
}
void push_node(int k,int x)
{
e[idx]=x;
ne[idx]=ne[k-1];
ne[k-1]=idx++;
}
int main()
{
int T;
cin>>T;
init();
while(T--)
{
char s;
int k,x;
cin>>s;
if(s=='H')
{
cin>>x;
push_head(x);
}
else if(s=='D')
{
cin>>k;
if(!k)head=ne[head];
else del_node(k);
}
else if(s=='I')
{
cin>>k>>x;
push_node(k,x);
}
}
for(int i=head;i!=-1;i=ne[i])cout<<e[i]<<" ";
return 0;
}
124. 二叉树中的最大路径和
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 root ,返回其 最大路径和 。
示例 1:
输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6
这题还是递归遍历root,准备一个sum存储最大路径和,每次把左子树和右子树分别送去下一次递归,以求得左子树和右子树谁的路径和最大,每次计算路径和有三选择,一种是左子树+root然后返回到上面的根节点,一种是右子树+root,还有一种是左子树+root+右子树。每次比较这三个值的大小,取最大的和sum作比较,如果大于sum就把sum更新。每次递归返回当前节点值和左子树或右子树的和(取最大)给上一级的节点,然后不断比较sum。当递归全部结束后把sum返回。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int sum=INT_MIN;
int maxPathSum(TreeNode* root) {
dfs(root);
return sum;
}
int dfs(TreeNode*root)
{
if(!root)return 0;
int l=max(dfs(root->left),0);
int r=max(dfs(root->right),0);
int ans=root->val+max(l,r);
sum=max(sum,max(ans,root->val+r+l));
return ans;
}
};