牛客NC164 最长上升子序列(二)【困难 贪心+二分 Java/Go/PHP/C++】

news2024/9/20 21:39:33

题目

在这里插入图片描述
题目链接:
https://www.nowcoder.com/practice/4af96fa010c44638a7e112abf65f7237

思路

贪心+二分

    所谓贪心,就是往死里贪,所以对于最大上升子序列,结尾元素越小,越有利于后面接上其他的数,
    也就可能变得更长
    所以贪心的做法是,建立一个dp数组,dp[i[表示长度为i的LIS结尾元素的最小值,
    因此我们只需要维护dp数组即可

    对于每一个数组的数,我们对他们进行判断,如果他大于等于dp[ans]的值,就把他放在数组后面,
    dp[++ans] = tr[i],
    否则,就在dp中去找大一个大于等于他的位置pos,dp[pos] = tr[i]。如果从头扫一遍数组,
    时间复杂度还是O(n^2),
    这与曹贼何异?!通过观察我们知道,这次维护的dp数组是单调递增的,
    所以就可以使出秘技二分之lower_bound来找pos的位置
    我们举个栗子:

        tr[] = 2 5 18 3 4 7 10 9 11 8 15
        dp[1] = 2;
        5大于2,所以dp[2] = 5
        18大于5,所以dp[3] = 18
        3小于18,所以二分去找,pos是2,所以dp[2] = 3
        4小于18,所以二分去找,pos是3,所以dp[3] = 4
        7大于4,所以dp[4] = 7
        10大于7,所以dp[5] = 10
        9小于10,所以二分去找,pos是5,dp[5] = 9
        11大于9,所以dp[6] = 11
        8小于11,所以二分去找,pos是5,dp[5] = 8
        15大于11,所以dp[7] = 15

    所以最长上升子序列的长度为7
    注意:dp数组得到的不一定是真正的LIS
    比如:tr[] = 1 4 7 2 5 9 10 3
    得到的是1 2 3 9 10,而真正的LIS是1 2 5 9 10
    因此dp数组得到的不一定是真正的LIS,他只表示最长子序列长度的排好序的最小序列,
    对于最后一半将5换成3的意义是记录最小序列,便于后续数据的处理

Java代码

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 该数组最长严格上升子序列的长度
     * @param a int整型一维数组 给定的数组
     * @return int整型
     */
    public int LIS (int[] a) {
        //https://blog.csdn.net/weixin_51216553/article/details/114678534
        /*
        贪心+二分

        所谓贪心,就是往死里贪,所以对于最大上升子序列,结尾元素越小,越有利于后面接上其他的数,也就可能变得更长
        所以贪心的做法是,建立一个dp数组,dp[i[表示长度为i的LIS结尾元素的最小值,因此我们只需要维护dp数组即可

        对于每一个数组的数,我们对他们进行判断,如果他大于等于dp[ans]的值,就把他放在数组后面,dp[++ans] = tr[i],
        否则,就在dp中去找大一个大于等于他的位置pos,dp[pos] = tr[i]。如果从头扫一遍数组,时间复杂度还是O(n^2),
        这与曹贼何异?!通过观察我们知道,这次维护的dp数组是单调递增的,所以就可以使出秘技二分之lower_bound来找pos的位置
        我们举个栗子:

            tr[] = 2 5 18 3 4 7 10 9 11 8 15
            dp[1] = 2;
            5大于2,所以dp[2] = 5
            18大于5,所以dp[3] = 18
            3小于18,所以二分去找,pos是2,所以dp[2] = 3
            4小于18,所以二分去找,pos是3,所以dp[3] = 4
            7大于4,所以dp[4] = 7
            10大于7,所以dp[5] = 10
            9小于10,所以二分去找,pos是5,dp[5] = 9
            11大于9,所以dp[6] = 11
            8小于11,所以二分去找,pos是5,dp[5] = 8
            15大于11,所以dp[7] = 15

        所以最长上升子序列的长度为7
        注意:dp数组得到的不一定是真正的LIS
        比如:tr[] = 1 4 7 2 5 9 10 3
        得到的是1 2 3 9 10,而真正的LIS是1 2 5 9 10
        因此dp数组得到的不一定是真正的LIS,他只表示最长子序列长度的排好序的最小序列,对于最后一半将5换成3的意义是记录最小序列,便于后续数据的处理
         */
        int n = a.length;
        if (n <= 1) return n;

        int[] dp = new int[n + 1];
        int idx = 1;
        dp[idx] = a[0];
        // 利用贪心 + 二分查找进行更新
        for (int i = 1; i < n ; i++) {
            if (dp[idx] < a[i]) {
                idx++;
                dp[idx] = a[i];
            } else {
                int l = 1;
                int r = idx;
                int pos = 0;

                while (l <= r) {
                    int mid = (l + r) >> 1;
                    if (dp[mid] < a[i]) {
                        pos = mid;
                        l = mid + 1;
                    } else {
                        r = mid - 1;
                    }
                }
                dp[pos + 1] = a[i];
            }
        }
        return idx;
    }
}

Go代码

package main

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 该数组最长严格上升子序列的长度
 * @param a int整型一维数组 给定的数组
 * @return int整型
 */
func LIS(a []int) int {
	//https://blog.csdn.net/weixin_51216553/article/details/114678534
	/*
	   贪心+二分

	   所谓贪心,就是往死里贪,所以对于最大上升子序列,结尾元素越小,越有利于后面接上其他的数,也就可能变得更长
	   所以贪心的做法是,建立一个dp数组,dp[i[表示长度为i的LIS结尾元素的最小值,因此我们只需要维护dp数组即可

	   对于每一个数组的数,我们对他们进行判断,如果他大于等于dp[ans]的值,就把他放在数组后面,dp[++ans] = tr[i],
	   否则,就在dp中去找大一个大于等于他的位置pos,dp[pos] = tr[i]。如果从头扫一遍数组,时间复杂度还是O(n^2),
	   这与曹贼何异?!通过观察我们知道,这次维护的dp数组是单调递增的,所以就可以使出秘技二分之lower_bound来找pos的位置
	   我们举个栗子:

	       tr[] = 2 5 18 3 4 7 10 9 11 8 15
	       dp[1] = 2;
	       5大于2,所以dp[2] = 5
	       18大于5,所以dp[3] = 18
	       3小于18,所以二分去找,pos是2,所以dp[2] = 3
	       4小于18,所以二分去找,pos是3,所以dp[3] = 4
	       7大于4,所以dp[4] = 7
	       10大于7,所以dp[5] = 10
	       9小于10,所以二分去找,pos是5,dp[5] = 9
	       11大于9,所以dp[6] = 11
	       8小于11,所以二分去找,pos是5,dp[5] = 8
	       15大于11,所以dp[7] = 15

	   所以最长上升子序列的长度为7
	   注意:dp数组得到的不一定是真正的LIS
	   比如:tr[] = 1 4 7 2 5 9 10 3
	   得到的是1 2 3 9 10,而真正的LIS是1 2 5 9 10
	   因此dp数组得到的不一定是真正的LIS,他只表示最长子序列长度的排好序的最小序列,对于最后一半将5换成3的意义是记录最小序列,便于后续数据的处理
	*/
	n := len(a)
	if n <= 1 {
		return n
	}

	dp := make([]int, n+1)
	idx := 1
	dp[idx] = a[0]

	//利用贪心+二分查找进行更新
	for i := 1; i < n; i++ {
		if dp[idx] < a[i] {
			idx++
			dp[idx] = a[i]
		} else {
			l := 1
			r := idx
			pos := 0
			for l <= r {
				mid := (l + r) >> 1
				if dp[mid] < a[i] {
					pos = mid
					l = mid + 1
				} else {
					r = mid - 1
				}
			}
			dp[pos+1] = a[i]
		}
	}

	return idx
}

PHP代码

<?php


/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 该数组最长严格上升子序列的长度
 * @param a int整型一维数组 给定的数组
 * @return int整型
 */
function LIS( $a )
{
      //https://blog.csdn.net/weixin_51216553/article/details/114678534
    /*
       贪心+二分

       所谓贪心,就是往死里贪,所以对于最大上升子序列,结尾元素越小,越有利于后面接上其他的数,也就可能变得更长
       所以贪心的做法是,建立一个dp数组,dp[i[表示长度为i的LIS结尾元素的最小值,因此我们只需要维护dp数组即可

       对于每一个数组的数,我们对他们进行判断,如果他大于等于dp[ans]的值,就把他放在数组后面,dp[++ans] = tr[i],
       否则,就在dp中去找大一个大于等于他的位置pos,dp[pos] = tr[i]。如果从头扫一遍数组,时间复杂度还是O(n^2),
       这与曹贼何异?!通过观察我们知道,这次维护的dp数组是单调递增的,所以就可以使出秘技二分之lower_bound来找pos的位置
       我们举个栗子:

           tr[] = 2 5 18 3 4 7 10 9 11 8 15
           dp[1] = 2;
           5大于2,所以dp[2] = 5
           18大于5,所以dp[3] = 18
           3小于18,所以二分去找,pos是2,所以dp[2] = 3
           4小于18,所以二分去找,pos是3,所以dp[3] = 4
           7大于4,所以dp[4] = 7
           10大于7,所以dp[5] = 10
           9小于10,所以二分去找,pos是5,dp[5] = 9
           11大于9,所以dp[6] = 11
           8小于11,所以二分去找,pos是5,dp[5] = 8
           15大于11,所以dp[7] = 15

       所以最长上升子序列的长度为7
       注意:dp数组得到的不一定是真正的LIS
       比如:tr[] = 1 4 7 2 5 9 10 3
       得到的是1 2 3 9 10,而真正的LIS是1 2 5 9 10
       因此dp数组得到的不一定是真正的LIS,他只表示最长子序列长度的排好序的最小序列,对于最后一半将5换成3的意义是记录最小序列,便于后续数据的处理
    */
     $n = count($a);
    if($n<=1){
        return $n;
    }

    $dp =[0];
    $idx = 1;
    $dp[$idx] = $a[0];

    // 利用贪心 + 二分查找进行更新
    for($i=1;$i<$n;$i++){
        if($dp[$idx] <$a[$i]){
            $idx++;
            $dp[$idx] = $a[$i];
        }else{
            $l=1;
            $r =$idx;
            $pos=0;
            while ($l<=$r){
                $mid = ($l+$r) >>1;
                if($dp[$mid] <$a[$i]){
                    $pos = $mid;
                    $l=$mid+1;
                }else{
                    $r = $mid-1;
                }
            }

            $dp[$pos+1] = $a[$i];
        }
    }
    return $idx;
}

C++代码

class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 该数组最长严格上升子序列的长度
     * @param a int整型vector 给定的数组
     * @return int整型
     */
    int LIS(vector<int>& a) {
        //https://blog.csdn.net/weixin_51216553/article/details/114678534
        /*
        贪心+二分

        所谓贪心,就是往死里贪,所以对于最大上升子序列,结尾元素越小,越有利于后面接上其他的数,也就可能变得更长
        所以贪心的做法是,建立一个dp数组,dp[i[表示长度为i的LIS结尾元素的最小值,因此我们只需要维护dp数组即可

        对于每一个数组的数,我们对他们进行判断,如果他大于等于dp[ans]的值,就把他放在数组后面,dp[++ans] = tr[i],
        否则,就在dp中去找大一个大于等于他的位置pos,dp[pos] = tr[i]。如果从头扫一遍数组,时间复杂度还是O(n^2),
        这与曹贼何异?!通过观察我们知道,这次维护的dp数组是单调递增的,所以就可以使出秘技二分之lower_bound来找pos的位置
        我们举个栗子:

            tr[] = 2 5 18 3 4 7 10 9 11 8 15
            dp[1] = 2;
            5大于2,所以dp[2] = 5
            18大于5,所以dp[3] = 18
            3小于18,所以二分去找,pos是2,所以dp[2] = 3
            4小于18,所以二分去找,pos是3,所以dp[3] = 4
            7大于4,所以dp[4] = 7
            10大于7,所以dp[5] = 10
            9小于10,所以二分去找,pos是5,dp[5] = 9
            11大于9,所以dp[6] = 11
            8小于11,所以二分去找,pos是5,dp[5] = 8
            15大于11,所以dp[7] = 15

        所以最长上升子序列的长度为7
        注意:dp数组得到的不一定是真正的LIS
        比如:tr[] = 1 4 7 2 5 9 10 3
        得到的是1 2 3 9 10,而真正的LIS是1 2 5 9 10
        因此dp数组得到的不一定是真正的LIS,他只表示最长子序列长度的排好序的最小序列,对于最后一半将5换成3的意义是记录最小序列,便于后续数据的处理
         */
        int n = a.size();
        if (n <= 1) {
            return n;
        }

        vector<int> dp(n + 1, 0);
        int idx = 1;
        dp[idx] = a[0];
        // 利用贪心 + 二分查找进行更新
        for (int i = 1; i < n; i++) {
            if (dp[idx] < a[i]) {
                dp[++idx] = a[i];
            } else {
                int l = 1;
                int r = idx;
                int pos = 0;
                while (l <= r) {
                    int mid = (l + r) >> 1;
                    if (dp[mid] < a[i]) {
                        pos = mid;
                        l = mid + 1;
                    } else {
                        r = mid - 1;
                    }
                }
                dp[pos + 1] = a[i];
            }
        }
        return idx;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1703182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

麒麟系统firewalld限制指定的ip访问指定的端口

先开放所有端口 然后第三个限制会把第四个第五个拦住 so 这个是错误案例 accecpt 接受 reject 拒绝

为什么短剧突然爆火?背后究竟谁在为流量买单?

为什么短剧突然爆火&#xff1f;背后究竟谁在为流量买单&#xff1f; 文丨微三云营销总监胡佳东&#xff0c;点击上方“关注”&#xff0c;为你分享市场商业模式电商干货。 - 今年很多朋友交流的更多的商业热门话题就是“短剧”&#xff0c;目前我国拥有超10亿的短视频用户&a…

利用ESP32(Arduino IDE)向匿名上位机发送欧拉角

文章目录 一. 匿名上位机介绍二. 匿名协议说明1. 匿名协议官方说明文档2. 协议说明 三. 向匿名上位机发送数据(基于Arduino IDE的esp32)四. 运行效果 一. 匿名上位机介绍 匿名上位机官方介绍视频 匿名上位机官方下载 二. 匿名协议说明 1. 匿名协议官方说明文档 官方对于协…

2024年短视频评论区批量爬取采集软件

一、背景说明 前言 评论区引流&#xff0c;顾名思义&#xff0c;是通过在视频下方进行留言评论、回复评论&#xff0c;吸引用户的注意&#xff0c;从而和你的账号产生互动、交易。比如&#xff0c;在一个关于健身的视频下方&#xff0c;留言分享自己的健身经验或者提出问题。…

西门子S7-1200加入MRP 环网用法

MRP&#xff08;介质冗余&#xff09;功能概述 SIMATIC 设备采用标准的冗余机制为 MRP&#xff08;介质冗余协议&#xff09;&#xff0c;符合 IEC62439-2 标准&#xff0c;典型重新组态时间为 200ms&#xff0c;每个环网最多支持 50个设备。​博途TIA/WINCC社区VX群 ​博途T…

springboot+vue+mybatis基于java web的公益网站的设计与实现+jsp+PPT+论文+讲解+售后

现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本公益网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&#xff0c;使…

docker搭建gitlab及默认密码修改及配置修改

推荐官方文档 https://docs.gitlab.com/17.0/ee/install/docker.html 我使用的是docker run的方式&#xff0c;官方文档后面有docker-compose、swarm、k8s的部署文档 版本说明 1&#xff1a;可以部署gitlab-ce社区版和gitlab-ee企业版&#xff0c;然后&#xff0c;鉴于是个人…

上海AI lab发布MathBench,GPT-4o的数学能力有多强?

大模型数学能力哪家强&#xff1f; 最近&#xff0c;上海AI lab构建了一个全面的多语言数学基准——MathBench。与现有的基准不同的是&#xff0c;MathBench涵盖从小学、初中、高中、大学不同难度&#xff0c;从基础算术题到高阶微积分、统计学、概率论等丰富类别的数学题目&a…

基于51单片机的函数发生器设计

一.硬件方案 此函数信号发生器是基于单片机AT89C51设计而成的&#xff0c;能够产生频率范围在0Hz—535Hz的锯齿波、正弦波、三角波、矩形波四种波形&#xff0c;并且能够通过液晶屏1602显示各自的波形类型以及频率数值。电路主要由51单片机最小系统DA0832模数转换模块运放模块…

Star CCM+绘图显示设置

前言 如前文介绍&#xff0c;根据报告创建监视器与绘图后&#xff0c;在绘图中会出现报告绘图。此处可以自定义绘图的格式&#xff0c;如网格显示、字体大小、曲线的粗细等。同时也可以根据需要创建右坐标&#xff0c;分别监测不同类型的函数数值。为此方便后期输出仿真报告。…

nginx文件解析漏洞测试

环境条件:ubuntu14,已安装docker,docker pull ubuntu:14.04.5 一、Nginx配置 1、使用docker启动容器&#xff1a; docker run -itd --name ubuntu -p 8088:80 ubuntu:14.04.5 2、进入容器&#xff1a; docker exec -it ubuntu /bin/bash 3、然后使用以下语句安装相关环境…

超详细的前后端实战项目(Spring系列加上vue3)前后端篇(四)(一步步实现+源码)

兄弟们&#xff0c;继昨天的代码之后&#xff0c;继续完成最后的用户模块开发&#xff0c; 昨天已经完成了关于用户的信息编辑页面这些&#xff0c;今天再完善一下&#xff0c; 从后端这边开始吧&#xff0c;做一个拦截器&#xff0c;对用户做身份校验&#xff0c; 拦截器 这…

无线蓝牙耳机品牌推荐:倍思M2s Pro,让旅途更添乐趣

随着端午节的临近,许多人开始规划起出游计划。出游除了要做好行程安排,还需准备一些实用的物品来提升旅途的舒适度。特别是在高铁等长途旅行中,一款优质的降噪蓝牙耳机无疑是消磨时光、享受音乐的绝佳选择。那么,在众多的无线蓝牙耳机品牌中,有哪些值得推荐的呢?今天,我们就来…

javascript 防抖 节流

在前端开发中&#xff0c;性能优化是提升用户体验的关键环节。防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;作为两种常见的优化技术&#xff0c;能够有效管理和控制频繁触发的事件&#xff0c;减少不必要的计算和资源消耗。无论是在处理用户输…

Samtec技术漫谈 | 电动自行车中的传感器和信号传输技术

【摘要/前言】 电动自行车&#xff0c;大家熟悉吗&#xff1f; 今天的话题似乎是可以唤起大家心底骑车的美好回忆&#xff0c;我们也曾骑车探索过大自然和社区&#xff0c;自行车也是我们曾经不可或缺的便捷交通工具。 怀旧思潮的影响&#xff0c;加持科技的进步&#xff0c…

spring boot3整合邮件服务实现邮件发送功能

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 目录 内容概要 开通服务 依赖引入 配置属性 创建邮件发送工具类 测试 最近发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家…

一维数组基础(题目+答案)

第1题 反向输出 时限&#xff1a;1s 空间&#xff1a;256m 输入n个数&#xff0c;要求程序按输入时的逆序把这n个数打印出来&#xff0c;已知整数不超过100个。也就是说&#xff0c;按输入相反顺序打印这n个数。 输入格式 第一行&#xff1a;一个整数n&#xff0c;代表…

《QT实用小工具·六十六》基于QT开发的界面收缩栏

1、概述 源码放在文章末尾 该项目实现了一个界面收缩栏的效果&#xff0c;该收缩栏包含如下功能&#xff1a; 1、可以在收缩栏中添加若干个界面 2、鼠标点击收缩栏可以展开或收起界面 3、鼠标拖动收缩栏可以和其他界面互换位置 项目demo演示如下所示&#xff1a; 使用方式&…

时隔1年,我终于弄懂了Java 中的 AOP操作

1. AOP概述 2. AOP快速入门 依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>${spring-boot.version}</version></dependency> 示例:记…