目录
最⻓上升⼦序列(⼆)(贪⼼+⼆分)
题目解析
1.题目链接:最长上升子序列(二)_牛客题霸_牛客网
2.题目描述
描述
给定一个长度为 n 的数组a,求它的最长严格上升子序列的长度。
所谓子序列,指一个数组删掉一些数(也可以不删)之后,形成的新数组。例如 [1,5,3,7,3] 数组,其子序列有:[1,3,3]、[7] 等。但 [1,6]、[1,3,5] 则不是它的子序列。
我们定义一个序列是 严格上升 的,当且仅当该序列不存在两个下标 ii 和 jj 满足 i<ji<j 且 a_i \geq a_jai≥aj。
数据范围: 0\leq n \leq 10^50≤n≤105,-10^9<=a[i]<=10^9−109<=a[i]<=109
要求:时间复杂度 O(nlogn)O(nlogn), 空间复杂度 O(n)O(n)
示例1
输入:
[1,4,7,5,6]
返回值:
4
说明:
最长上升子序列为 [1,4,5,6] ,长度为4。
讲解算法原理
解法:
算法思路:
我们在考虑最⻓递增⼦序列的⻓度的时候,其实并不关⼼这个序列⻓什么样⼦,我们只是关⼼最后⼀个元素是谁。这样新来⼀个元素之后,我们就可以判断是否可以拼接到它的后⾯。
因此,我们可以创建⼀个数组,统计⻓度为 x 的递增⼦序列中,最后⼀个元素是谁。为了尽可能
的让这个序列更⻓,我们仅需统计⻓度为 x 的所有递增序列中最后⼀个元素的「最⼩值」。统计的过程中发现,数组中的数呈现「递增」趋势,因此可以使⽤「⼆分」来查找插⼊位置。
编写代码
c++算法代码:
class Solution
{
int dp[100010] = { 0 }; // dp[i] 表⽰:⻓度为 i 的最⼩末尾 int pos = 0;
public:
int LIS(vector<int>& a)
{
for(auto x : a)
{
// 查找 x 应该放在哪个位置 if(pos == 0 || x > dp[pos]) {
dp[++pos] = x;
}
else
{
// ⼆分查找插⼊位置 int l = 1, r = pos; while(l < r) {
int mid = (l + r) / 2; if(dp[mid] >= x) r = mid; else l = mid + 1; } dp[l] = x;
}
}
return pos;
}
};
java算法代码:
import java.util.*;
public class Solution
{
public int LIS (int[] a)
{
int n = a.length;
int[] dp = new int[n + 1]; // dp[i] 表⽰⻓度为 i 的最⼩末尾
int pos = 0;
for(int x : a)
{
// 找 x 应该放在哪⾥
if(pos == 0 || x > dp[pos])
{
dp[++pos] = x;
}
else
{
// ⼆分查找插⼊位置 int l = 1, r = pos; while(l < r) {
int mid = (l + r) / 2; if(dp[mid] >= x) r = mid; else l = mid + 1; } dp[l] = x;
}
}
return pos;
}
}
爱吃素(数学)
题目解析
1.题目链接:登录—专业IT笔试面试备考平台_牛客网
2.题目描述
牛妹是一个爱吃素的小女孩,所以很多素数都害怕被她吃掉。
一天,两个数字aaa和bbb为了防止被吃掉,决定和彼此相乘在一起,这样被吃掉的风险就会大大降低,但仍有一定的可能被吃掉,请你判断他们相乘后是否仍有被吃掉的风险。
也就是说,请你判断a×ba\times ba×b是否是素数。
素数是指大于111的正整数中,有且仅有两个因子的数。输入描述:
输入第一行是一个整数T(1≤T≤10)T(1\leq T\leq 10)T(1≤T≤10),表示测试组数。
接下来TTT行,每一行两个整数a,b(1≤a,b≤1011)a,b(1\leq a,b\leq 10^{11})a,b(1≤a,b≤1011)。
输出描述:
对于每一行输入,若输入满足a×ba\times ba×b是素数,输出一行"YES",否则输出一行"NO"(没有引号)。
示例1
输入
3 2 3 1 7 1 4
3
2 3
1 7
1 4输出
NO YES NO
NO
YES
NO
讲解算法原理
解法:
算法思路:
判断两数相乘是否是素数。
◦ 不能直接乘起来然后判断,因为数据量太⼤了,不仅存不下,⽽且会超时;◦ 因此根据素数的性质,分类讨论。
编写代码
c++算法代码:
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
bool isprim(LL x)
{
if(x < 2) return false; for(int i = 2; i <= sqrt(x); i++) { if(x % i == 0) return false; } return true;
}
int main()
{
int t;
cin >> t;
while(t--)
{
LL a, b;
cin >> a >> b; if((a == 1 && isprim(b)) || (b == 1 && isprim(a))) { cout << "YES" << endl; } else
{
cout << "NO" << endl;
}
}
return 0;
}
java算法代码:
import java.util.*;
public class Main
{
public static boolean isprim(long x)
{
if(x < 2) return false; for(int i = 2; i <= Math.sqrt(x); i++) { if(x % i == 0) return false; } return true;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in); int t = in.nextInt(); while(t-- != 0)
{
long a = in.nextLong(), b = in.nextLong(); if((a == 1 && isprim(b)) || (b == 1 && isprim(a))) {
System.out.println("YES");
}
else
{
System.out.println("NO");
}
}
}
}