2021-12-22每日刷题打卡

2021-12-22每日刷题打卡

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题库

实现一个单链表,链表初始为空,支持三种操作:

  1. 向链表头插入一个数;
  2. 删除第 k 个插入的数后面的数;
  3. 在第 k 个插入的数后插入一个数。

现在要对该链表进行 M 次操作,进行完所有操作后,从头到尾输出整个链表。

注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 22 个插入的数,…第 n 个插入的数。

输入格式

第一行包含整数 M,表示操作次数。

接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:

  1. H x,表示向链表头插入一个数 x。
  2. D k,表示删除第 k 个插入的数后面的数(当 k 为 0 时,表示删除头结点)。
  3. 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:

exx1.jpg (322×182) (leetcode.com)

输入: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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值