1、瞌睡:
已知小易对一堂课每分钟知识点的感兴趣程度,并以分数量化,以及他在这堂课上每分钟是否会睡着,你可以叫醒他一次,这会让他在接下来的k分钟内保持清醒。求一种方案最大化他听到知识点的最大兴趣值。
第一行:输入n,k(1<=n,k<10^5),表示这堂课持续的时间,以及叫醒小易能让他保持清醒的时间。
第二行:n个数,a1,a2,a3..an(1--10^4)表示对每分钟知识点的兴趣评分
第三行:n个数,t1,t2....tn表示每分钟小易是否清醒,1表示清醒,0表示睡着。
输出:听到知识点的最大兴趣值。
6 3
1 3 5 2 5 4
1 1 0 1 0 0
16
代码如下:
首先,清醒的时候的兴趣值是必须要加上的;有个最优值就是:睡着之后被叫醒。
看他说这是贪心,还得看看。==》90%
import java.util.Scanner;
public class LastT1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int i=0;
int[] scores = new int[n];
while(i<n){
scores[i] = sc.nextInt();
i++;
}
int[] wake = new int[n];
i = 0;
while (i<n){
wake[i] = sc.nextInt();
i++;
}
int maxValue = 0;//睡着后被叫醒的最大收益
int sum = 0;//没睡觉时候的收益,这是必须的
for(int j=0;j<n;j++){
if(wake[j] == 0){
int tmp = 0;//睡着了,但叫醒后的收益
for(int t=j;t<j+k;t++){//叫醒后的k分钟清醒
if(t >= n)break;//超过数组长度,结束就好
if(wake[t] == 0)//如果为0,表示之前瞌睡,加上该值
tmp += scores[t];
}
if(maxValue < tmp)
maxValue = tmp;
}else {//此时没睡着
sum += scores[j];
}
}
System.out.println(maxValue + sum);
}
}
参考:https://www.nowcoder.com/discuss/93132
第二种方法,使用滑动窗口
import java.util.Scanner;
public class LastT1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int i=0;
int[] scores = new int[n];
while(i<n){
scores[i] = sc.nextInt();
i++;
}
int[] wake = new int[n];
i = 0;
while (i<n){
wake[i] = sc.nextInt();
i++;
}
int sum = 0;
i=0;
for(;i<n;i++){//为1的肯定要加上
if(wake[i] == 1)
sum += scores[i];
}
i = 0;
for(;i<k;i++){//设大小为k的滑动窗口**保证大小为k的窗口
if(wake[i] == 0){
sum += scores[i];
}
}
int max = sum;
for(i=k;i<n;i++){//k之后。。。
if(wake[i-k] == 0)//如果第一个为0,减去第一个
sum -= scores[i-k];
if(wake[i] == 0){//当前这个为0,加上这一个
sum += scores[i];
if(max < sum)
max = sum;
}
}
System.out.println(max);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int i=0;
int[] scores = new int[n];
while(i<n){
scores[i] = sc.nextInt();
i++;
}
int[] wake = new int[n];
i = 0;
while (i<n){
wake[i] = sc.nextInt();
i++;
}
int sum = 0;
i=0;
for(;i<n;i++){
if(wake[i] == 1)
sum += scores[i];
}
int slow = 0;
int fast = k-1;
int max = 0;
i= 0;
for(;i<=fast;i++){//当slow为0的时候
if(wake[i] == 0){
sum += scores[i];
}
}
max = sum;
fast++;
while(fast < scores.length){
if(wake[slow] ==0)
sum -= scores[slow];
if(wake[fast] == 0){
sum += scores[fast];
if(max < sum)
max = sum;
}
slow++;
fast++;
}
System.out.println(max);
}
我更喜欢这样两个指针的滑动窗口!注意前k个数组还是得手动的往里加!然后从fast++开始遍历。
我也不知道为啥,我的第一反应是递归,没做出来。这种情况下,想不出来关于k分钟清醒参数如何进行使用的途径,==》反正用递归不合适!
2、苹果堆,将前面的数相加,然后进行搜索即可!但是这样会超时===》此时已经是有序数组了,所以使用二分查找即可!
示例
输入
5
2 7 3 4 9
3
1 25 11
输出
1
5
3
import java.util.Scanner;
public class T2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = Integer.parseInt(scanner.nextLine().trim());
int []IndexOfApple = new int[n];
String[] rawDatas = scanner.nextLine().trim().split(" ");
IndexOfApple[0] = Integer.parseInt(rawDatas[0]);
for (int i = 1; i < n ; i++) {
int tmp = Integer.parseInt(rawDatas[i]);
IndexOfApple[i] = IndexOfApple[i-1] + tmp;
}
int m = Integer.parseInt(scanner.nextLine().trim());
int []number = new int[m];
int []res = new int[m];
rawDatas = scanner.nextLine().trim().split(" ");
for (int i = 0; i < m ; i++) {
number[i] = Integer.parseInt(rawDatas[i]);
}
for (int i = 0; i < m; i++) {
//System.out.println(function(IndexOfApple,number[i]));
//System.out.println(binarySearch(IndexOfApple,number[i]) + 1);
System.out.println(function1(IndexOfApple,number[i]) + 1);
}
}
private static int function1(int[]IndexOfApple, int value){
int low = 0;
int high = IndexOfApple.length - 1;
while(low <= high){
int mid = (low + high) / 2;
if(IndexOfApple[mid] > value){
high = mid - 1;
}else if(IndexOfApple[mid] < value){
low = mid + 1;
}else{
return mid;
}
}
return low;
}
public static int binarySearch(int[] a,int fromIndex,int toIndex,int value){
int low=fromIndex;
int high=toIndex-1;
while(low<high){
int mid=(low+high)>>>1;
int midVal=a[mid];
if(midVal<value)
low=mid+1;
else
high=mid;
}
return low;
}
private static int function(int[]IndexOfApple, int index){
if (index <= 0)
return -1;
int res = 0;
for (int i=0;i<IndexOfApple.length;i++) {
if(index <= IndexOfApple[i]){
res = i;
break;
}
}
return res+1;
}
}
3、每个单词都包含n个‘a’,m个‘z’,并且所有单词按字典序排列。请找出第k个单词。若无解,返回-1===》n个a和m个z组成的字典序字符串集,查找第k个字是什么?
输入描述
第一行为三个数,分别为a的个数n,z的个数m,第k个字符串。
输出描述
第k个字符串
示例
输入
1
2 2 6
输出
1
zzaa
直接想法就是,使用全排列,然后排序即可=》这样只能通过20%。
全排列的算法如下(模板):
static ArrayList<String> list = new ArrayList<>();
public static void permutation(char[] arr,int start,int end){
if(start == end){
String str = new String(arr);
if(list.indexOf(str) == -1)
list.add(str);
}else{
for(int i=0;i<arr.length;i++){
swap(arr,start,i);
permutation(arr,start+1,end);
swap(arr,start,i);
}
}
}
重点信息:只有a,z!
动态规划:dp[i][j]表示i个a和j个z的方案数=》这个我不会
参考:https://www.nowcoder.com/discuss/93285
https://fengxc.me/2018%E7%BD%91%E6%98%93%E7%AC%94%E8%AF%95%E9%A2%98%E5%8F%8A%E8%A7%A3%E7%AD%94-Java.html#more
https://www.nowcoder.com/questionTerminal/12b1b8ef17e1441f86f322b250bff4c0 这个讲解最好
https://blog.youkuaiyun.com/jiang199235jiangjj/article/details/7432601排列组合 为什么呢?