【刷题汇总 -- 排序子序列、消减整数、最长上升子序列(二)】

C++日常刷题积累

今日刷题汇总 - day026

1、排序子序列

1.1、题目

1.2、思路

读完题知道,让把一个长度为n的数组划分为排序子序列,其中定义排序子序列为一个数组中一段连续的子序列,并且这段子序列是非递增或者非递减排序的。求最少可以划分多少个排序子序列。

那么,根据题意和示例分析,既然要划分最少的情况,那么直接把连续上升的区间加上相等的都划分为一个上升区间,把连续下降的区间加上相等的区间也规划为一个区间,最后利用ret计数区间即可,为了直观理解画个图:

接下来,就是程序实现。

1.3、程序实现

首先,按照题目要求写好输入,然后利用下标 i 遍历,如果相邻的元素是存在上升或下降的且相等的,那么直接i++直到遇到转折,再比较下一组相邻元素同理,同时ret遇到转折就ret++,最后遍历到i = n-1时为最后一个元素,就不用再与后面相邻元素比较了,直接ret++结束即可。值得注意的是,刚开始序列处于相等的情况就只需要i++,而ret需要等待上升转下降或者下降转升序的转折时才++。

cpp 复制代码
#include <iostream>
using namespace std;

const int N = 1e5 + 10;
int arr[N];

int main()
{
    int n;
    cin >> n;
    for(int i = 0;i < n;i++)
        cin >> arr[i];
    
    int ret = 0;
    int i = 0;
    while(i < n)
    {
        if(i == n-1)//遍历到最后一个元素了
        {
            ret++;
            break;
        }
        //一开始不相等
        if(arr[i] < arr[i+1])
        {
            //升序且相等就划为一个序列
            while(i + 1 < n && arr[i] <= arr[i+1])
                i++;
            //遇见转折ret++
            ret++;
        }
        else if(arr[i] > arr[i+1])
        {
            //降序且相等就划为一个序列
            while(i + 1 < n && arr[i] >= arr[i+1])
                i++;
            //遇见转折ret++
            ret++;
        }
        else//一开始就相等,就只管i++即可
        {
            while(i + 1 < n && arr[i] == arr[i+1])
                i++;
        }
        //继续遍历
        i++;
    }
    cout << ret << endl;
    return 0;
}

2、消减整数

2.1、题目

2.2、思路

读完题直到,让处理一个整数,让其作减法,最终使其恰好减为0,其中每次减的数字都必须和上一次相同或者是上一次的两倍,求最少需要几次能把H恰好减到0。那么根据题目和示例分析,想到蛮力法就是枚举所有减法的可能统计执行的次数,但是对于数据量太大时会超时,所以结合贪心思想很容易想到需要尽可能多的利用减去上个数字的两倍的方案,但是题目中要求需要最终恰好减为0,那么就存在不能为0的情况,比如8 ,第一次只能减1,变成7,然后贪心减两倍,7-2=5,再贪心,5-22 = 1,那么此时1无论如何也无法通过减去4或42变成0,所以需要对贪心进行进一步的思考,既然要求减去两倍,恰好变成0,那么对于数字8,先执行第一次减1,8-1=7,然后判断7是否满足7 % 2*1 = 0?,如果等于0,则执行减2倍的方案,否则执行减上一次相同数字即可。那么接下来,就是程序实现。

2.3、程序实现 -- 贪心策略

首先,按照题目要求写好输入,然后为了逻辑分明,程序健壮性封装一个func函数执行统计操作的次数,然后func中,按照思路分析对于整数,判断能否满足贪心策略,能则减2倍,否则减上一次的数即可,直到h减恰好减到0结束。

cpp 复制代码
#include <iostream>
using namespace std;

int func(int h)
{
    int count = 0;//执行次数
    int a = 1;//初始减数 1
    while(h)
    {
        h -= a;
        count++;
        //判断能否执行贪心策略,下一次减2倍,否则还是减上次的数
        if(h % (2*a) == 0)
        {
            a = 2*a;
        }
    }
    return count;
}

int main()
{
    int T;
    cin >> T;
    int H;
    while(T--)
    {
        cin >> H;
        cout << func(H) << endl;
    }
    return 0;
}


3、最长上升子序列(二)

3.1、题目

3.2、思路

读完题知道,给定一个长度为 n 的数组a,求它的最长严格上升子序列的长度。所谓子序列,指一个数组删掉一些数(也可以不删)之后,形成的新数组。例如 [1,5,3,7,3] 数组,其子序列有:[1,3,3]、[7] 等。但 [1,6]、[1,3,5] 则不是它的子序列。其中,定义一个序列是 严格上升 的,当且仅当该序列不存在两个下标 i 和 j 满足 i < j 且ai > aj。根据题目和示例分析,要满足子序列最长,那么贪心策略尽可能要求序列按照越接近越相邻的规则存放才会最长,为了方便理解画个图:

那么接下来,就是程序实现。

3.3、程序实现-- 贪心策略+二分

cpp 复制代码
class Solution
{
  public:
    int dp[100010] = { 0 }; // dp[i] 表⽰:⻓度为 i 的最⼩末尾
    int pos = 0;
    int LIS(vector<int>& a)
    {
        for (auto x : a)
        {
            // 查找 x 应该放在哪个位置
            if (pos == 0 || x > dp[pos]) 
            {
                dp[++pos] = x;//pos == 0,dp[1]长度为1,末尾为x;
                //x > dp[pos]
                //对于最大元素,就增加到末尾,长度+1
            } 
            else
            {
                // ⼆分查找插⼊位置
                int left = 1, right = pos;
                while (left < right)
                {
                    int mid = (left + right) / 2;
                    if (dp[mid] >= x)
                        right = mid;
                    else 
                        left = mid + 1;
                }
                //插入的位置
                dp[left] = x;
            }
        }
        return pos;

    }
};

4、题目链接

🌟排序子序列

🌟消减整数

🌟最长上升子序列(二)

相关推荐
pianmian14 小时前
python数据结构基础(7)
数据结构·算法
好奇龙猫6 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
sp_fyf_20247 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
香菜大丸7 小时前
链表的归并排序
数据结构·算法·链表
jrrz08287 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time7 小时前
golang学习2
算法
南宫生8 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步9 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara9 小时前
函数对象笔记
c++·算法
泉崎10 小时前
11.7比赛总结
数据结构·算法