1、最大字典子序列
给一个字符串,从里面选取子序列,求新组成的最大字典序列。如“ABCAB”,最大字典子序为“CB”。(2018春-爱奇艺)
思路一:先遍历一遍,找到最大的字符C,第二趟从C右边开始遍历,找到最大的字符B,再从B右边开始遍历,右边没有了,结束。时间复杂度为 O(n2) O ( n 2 )
思路二:单调栈,时间复杂度为 O(n) O ( n )
import java.util.Scanner;
import java.util.Stack;
public class AiQYI1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s=in.nextLine();
Stack<Character> stack=new Stack<>();
int len=s.length();
for(int i=len-1;i>=0;i--){//从后往前遍历
if(stack.isEmpty()||stack.peek()<s.charAt(i)){
stack.push(s.charAt(i));
}
}
StringBuffer sb=new StringBuffer();
while(!stack.isEmpty()){
sb.append(stack.pop());
}
System.out.println(sb.toString());
}
}
2、放n种糖果进盒子
有n种糖果,每种糖果最少放min[i]个,最多放max[i]个 (0≤i<n) ( 0 ≤ i < n ) ,盒子里面需要放m个糖果,一共有多少种放法。(2018春-爱奇艺)
思路:先把每种最少需要放的糖果放进去,变成多重揹包问题。
来自牛客网@早就戒了。
import java.util.Scanner;
public class AiQYI3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();// 颜色种类
int m = scanner.nextInt();// 盒子放置m个糖果
int[] l = new int[n];
int[] r = new int[n];
int least = 0;
int[] avaliable = new int[n];// 表示每一种颜色剩余可以加的
for (int i = 0; i < r.length; i++) {
l[i] = scanner.nextInt();
r[i] = scanner.nextInt();
least += l[i];
avaliable[i] = r[i] - l[i];
}
int target = m - least; //dp[i][j]表示前i种糖果装满容量为j的揹包的方法数。一定要用long,不然会爆,只能过70%
long[][] dp = new long[n + 1][target + 1];
for (int i = 0; i < dp.length; i++) {
dp[i][0] = 1;//初始化
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= target; j++) {
for (int k = 0; k <= avaliable[i - 1]; k++) {
if (j - k >= 0)
dp[i][j] += dp[i - 1][j - k];
}
}
}
System.out.println(dp[n][target]);
}
}
3、给两个人分糖果
有一堆糖果,每个糖果重量不一定一样,分给两个人,两个人的糖果数量之差不超过1,求两个人分到的糖果的最小重量之差。(2018春-科大讯飞)
思路:找其中一份的重量之和与sum/2的最小之差
//转换为求其中一份与sum/2的最小值min,真实最小值为2*min
public class KDXF {
//全局变量
static float min=Integer.MAX_VALUE;//其中一份与sum/2的最小值min
static float half;//sum/2
public static void main(String[] args) {
//重量数组
float[] weight= {1,2,3,4,5,100,6};
//sum/2
half=(float) (sum(weight)/2.0);
//其中一份糖果重量 如果总数为奇数,为少的那一份
float[] a=new float[weight.length/2];
//回溯
back( weight.length/2,-1,weight, a );
System.out.println((int)(min*2));
}
//回溯 n为还需要选几个 i为上一次选取的糖果下标,这个是增序选择的 weight为所有糖果重量 a存放已经选取的糖果重量,倒叙存放,先放a[a.length-1]最后放a[0]
public static void back(int n,int i,float[] weight,float[] a ) {
if(n==0) {//当把数组a填满了就计算,计算回溯结束时此路径的min
if(Math.abs(sum(a)-half)<min) min=Math.abs(sum(a)-half);
}else {
for(i=i+1;i<weight.length;i++) {
//a倒叙存放这一份选取的糖果重量,正着放也可以,只不过用n-1方便一些
a[n-1]=weight[i];
back(n-1,i,weight, a );
}
}
}
//求和
public static float sum(float[] a) {
int sum=0;
for(int i=0;i<a.length;i++) {
sum+=a[i];
}
return sum;
}
}
4、求x^y的结果对N取余
(2018春-快手)
思路:直接累乘,线性时间复杂度不可取。二分,时间复杂度为 O(logn) O ( l o g n ) 。
import java.util.Scanner;
public class Kuaishou1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long x = in.nextLong();
long y = in.nextLong();
long N = in.nextLong();
if(y<0){
System.out.println((int)1/pow(x,-y));
}else {
System.out.println(pow(x,y,N));
}
}
public static long pow(long a,long b,long N){
if(b==0)return 1;
if(b==1)return a;
if(b%2==0){
return pow(a*a,b/2,N)%N;
}else {
return (pow(a*a,b/2,N)*a)%N;
}
}
}