【c++笔试强训】(第四十三篇)

目录

最⻓上升⼦序列(⼆)(贪⼼+⼆分)

题目解析

讲解算法原理

编写代码

爱吃素(数学)

题目解析

讲解算法原理

编写代码


最⻓上升⼦序列(⼆)(贪⼼+⼆分)

题目解析

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");
 }
 }
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值