泉港网站建设推广服务公司,长治在网络做推广,在线ppt网站,常用的软件开发的工具题目 题目链接#xff1a; https://www.nowcoder.com/practice/4af96fa010c44638a7e112abf65f7237
思路
贪心二分 所谓贪心#xff0c;就是往死里贪#xff0c;所以对于最大上升子序列#xff0c;结尾元素越小#xff0c;越有利于后面接上其他的数#xff0c;也就可能变…题目 题目链接 https://www.nowcoder.com/practice/4af96fa010c44638a7e112abf65f7237
思路
贪心二分 所谓贪心就是往死里贪所以对于最大上升子序列结尾元素越小越有利于后面接上其他的数也就可能变得更长所以贪心的做法是建立一个dp数组,dp[i[表示长度为i的LIS结尾元素的最小值因此我们只需要维护dp数组即可对于每一个数组的数我们对他们进行判断如果他大于等于dp[ans]的值就把他放在数组后面dp[ans] tr[i]否则就在dp中去找大一个大于等于他的位置posdp[pos] tr[i]。如果从头扫一遍数组时间复杂度还是On^2这与曹贼何异通过观察我们知道这次维护的dp数组是单调递增的所以就可以使出秘技二分之lower_bound来找pos的位置我们举个栗子tr[] 2 5 18 3 4 7 10 9 11 8 15dp[1] 2;5大于2所以dp[2] 518大于5所以dp[3] 183小于18所以二分去找pos是2所以dp[2] 34小于18所以二分去找pos是3所以dp[3] 47大于4所以dp[4] 710大于7所以dp[5] 109小于10所以二分去找pos是5dp[5] 911大于9所以dp[6] 118小于11所以二分去找pos是5dp[5] 815大于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中去找大一个大于等于他的位置posdp[pos] tr[i]。如果从头扫一遍数组时间复杂度还是On^2这与曹贼何异通过观察我们知道这次维护的dp数组是单调递增的所以就可以使出秘技二分之lower_bound来找pos的位置我们举个栗子tr[] 2 5 18 3 4 7 10 9 11 8 15dp[1] 2;5大于2所以dp[2] 518大于5所以dp[3] 183小于18所以二分去找pos是2所以dp[2] 34小于18所以二分去找pos是3所以dp[3] 47大于4所以dp[4] 710大于7所以dp[5] 109小于10所以二分去找pos是5dp[5] 911大于9所以dp[6] 118小于11所以二分去找pos是5dp[5] 815大于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中去找大一个大于等于他的位置posdp[pos] tr[i]。如果从头扫一遍数组时间复杂度还是On^2这与曹贼何异通过观察我们知道这次维护的dp数组是单调递增的所以就可以使出秘技二分之lower_bound来找pos的位置我们举个栗子tr[] 2 5 18 3 4 7 10 9 11 8 15dp[1] 2;5大于2所以dp[2] 518大于5所以dp[3] 183小于18所以二分去找pos是2所以dp[2] 34小于18所以二分去找pos是3所以dp[3] 47大于4所以dp[4] 710大于7所以dp[5] 109小于10所以二分去找pos是5dp[5] 911大于9所以dp[6] 118小于11所以二分去找pos是5dp[5] 815大于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, n1)idx : 1dp[idx] a[0]//利用贪心二分查找进行更新for i : 1; i n; i {if dp[idx] a[i] {idxdp[idx] a[i]} else {l : 1r : idxpos : 0for l r {mid : (l r) 1if dp[mid] a[i] {pos midl mid 1} else {r mid - 1}}dp[pos1] 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中去找大一个大于等于他的位置posdp[pos] tr[i]。如果从头扫一遍数组时间复杂度还是On^2这与曹贼何异通过观察我们知道这次维护的dp数组是单调递增的所以就可以使出秘技二分之lower_bound来找pos的位置我们举个栗子tr[] 2 5 18 3 4 7 10 9 11 8 15dp[1] 2;5大于2所以dp[2] 518大于5所以dp[3] 183小于18所以二分去找pos是2所以dp[2] 34小于18所以二分去找pos是3所以dp[3] 47大于4所以dp[4] 710大于7所以dp[5] 109小于10所以二分去找pos是5dp[5] 911大于9所以dp[6] 118小于11所以二分去找pos是5dp[5] 815大于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($n1){return $n;}$dp [0];$idx 1;$dp[$idx] $a[0];// 利用贪心 二分查找进行更新for($i1;$i$n;$i){if($dp[$idx] $a[$i]){$idx;$dp[$idx] $a[$i];}else{$l1;$r $idx;$pos0;while ($l$r){$mid ($l$r) 1;if($dp[$mid] $a[$i]){$pos $mid;$l$mid1;}else{$r $mid-1;}}$dp[$pos1] $a[$i];}}return $idx;
}C代码
class Solution {public:/*** 代码中的类名、方法名、参数名已经指定请勿修改直接返回方法规定的值即可** 该数组最长严格上升子序列的长度* param a int整型vector 给定的数组* return int整型*/int LIS(vectorint a) {//https://blog.csdn.net/weixin_51216553/article/details/114678534/*贪心二分所谓贪心就是往死里贪所以对于最大上升子序列结尾元素越小越有利于后面接上其他的数也就可能变得更长所以贪心的做法是建立一个dp数组,dp[i[表示长度为i的LIS结尾元素的最小值因此我们只需要维护dp数组即可对于每一个数组的数我们对他们进行判断如果他大于等于dp[ans]的值就把他放在数组后面dp[ans] tr[i]否则就在dp中去找大一个大于等于他的位置posdp[pos] tr[i]。如果从头扫一遍数组时间复杂度还是On^2这与曹贼何异通过观察我们知道这次维护的dp数组是单调递增的所以就可以使出秘技二分之lower_bound来找pos的位置我们举个栗子tr[] 2 5 18 3 4 7 10 9 11 8 15dp[1] 2;5大于2所以dp[2] 518大于5所以dp[3] 183小于18所以二分去找pos是2所以dp[2] 34小于18所以二分去找pos是3所以dp[3] 47大于4所以dp[4] 710大于7所以dp[5] 109小于10所以二分去找pos是5dp[5] 911大于9所以dp[6] 118小于11所以二分去找pos是5dp[5] 815大于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;}vectorint 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;}
};