題目1
題目描述
小易覺得高數課太無聊了,決定睡覺。不過他對課上的一些內容挺感興趣,所以希望老師講到有趣的地方的時候叫醒他一下。你知道了小易對一堂課每分鐘知識點的感興趣程度,並以分數量化,以及他在這堂課上每分鐘是否會睡着,你可以叫醒他一次,這會使得他在接下來的k分鐘內保持清醒。你需要選擇一種方案最大化小易這堂課聽到的知識點分值。
輸入描述
第一行n,k, (1 <= n, k <= 105),表示這堂課持續多少分鐘,以及叫醒小易一次使他能夠保持清醒的時間。
第二行 n個數,a1,a2,…,an(1<=ai<=104),表示小易對每分鐘知識點的感興趣評分。
第三行 n個數,t1,t2,…,tn,表示每分鐘小易是否清醒,1表示清醒。
輸出描述
小易這堂課聽到的知識點的最大興趣值。
示例
輸入
6 3
1 3 5 2 5 4
1 1 0 1 0 0
輸出
16
思路1
- 我的思路是統計所有爲 1 的 時間的興趣值,O(N)
- 再次遍歷,遇到爲 0 的時候,統計 之後的 k 個數,並且跳過爲 1 個數字不統計
- 比較並獲得最大值
- 這種方法的實質也算是暴力法,更好的方法應該是使用動態規劃
代碼: AC 90%
import java.util.Scanner;
public class testkeshui {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt(); sc.nextLine();
int[][] map = new int[n][2];
String[] str1 = sc.nextLine().split(" ");
String[] str2 = sc.nextLine().split(" ");
for (int i=0;i<n;i++){
map[i][0] = Integer.valueOf(str1[i]);
map[i][1] = Integer.valueOf(str2[i]);
}
int resultMax = 0;
int curMax = 0;
int wake = 0; //醒着的時間獲得的興趣值
for (int i=0;i<map.length;i++){
if (map[i][1] == 1){
wake += map[i][0];
}
}
for (int i=0;i<map.length;i++){
if (map[i][1] == 0){
if (map[i][1] == 0){
//從 i 開始,往後加上 k 個數
curMax = getSum(map,i,k);
curMax = curMax+wake;
}
resultMax = Math.max(resultMax,curMax);
}
}
resultMax = Math.max(resultMax,curMax);
System.out.println(resultMax);
}
private static int getSum(int[][] map, int i,int k){
int res = 0; //接下來的 k 包含當前嗎?
for (int j=0;j<k;j++){
if (i+j<map.length){
if (map[i+j][1] == 0)
res += map[i+j][0];
}
}
return res;
}
}
題目二
題目描述
又到了豐收的季節,恰好小易去牛牛的果園裏遊玩。 牛牛常說他多整個果園的每個地方都瞭如指掌,小易不太相信,所以他想考考牛牛。 在果園裏有N堆蘋果,每堆蘋果的數量爲ai,小易希望知道從左往右數第x個蘋果是屬於哪一堆的。 牛牛覺得問題太簡單了,所以希望你來替他回答。
輸入描述
第一行 一個數 n (1<= n <= 10^5)
第二行 n個數 ai (1<=ai<=1000),表示從左往右數第i堆有多少蘋果
第三行 一個數m (1<= m <= 10^5),表示有m次詢問
第四行 m個數qi, 表示小易希望知道第qi個蘋果屬於哪一堆。
輸出描述
m行,第i行輸出第qi個蘋果屬於哪一堆。
示例
輸入
5
2 7 3 4 9
3
1 25 11
輸出
1
5
3
思路
對蘋果數量求累加和,然後運用二分查找即可
- 採用 Arrays.binarySearch() 的返回值
import java.util.Arrays;
import java.util.Scanner;
public class fengshou {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] apple = new int[n+1];
int cur = 0;
for (int i=1;i<=n;i++){
cur += sc.nextInt();
apple[i] = cur;
}
int m = sc.nextInt();
while (m-->0){
//Arrays.binarySearch() 如果沒有查找到值: return -(low + 1); // key not found.
//只要拿到 low 的值即可輸出
int index = Arrays.binarySearch(apple,sc.nextInt());
if (index < 0){
System.out.println(-index-1);
}
else {
System.out.println(index);
}
}
}
}
- 自己實現二分查找
import java.util.Arrays;
import java.util.Scanner;
public class fengshou {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] apple = new int[n+1];
int cur = 0;
for (int i=1;i<=n;i++){
cur += sc.nextInt();
apple[i] = cur;
}
int m = sc.nextInt();
while (m-->0){
//Arrays.binarySearch() 如果沒有查找到值: return -(low + 1); // key not found.
//只要拿到 low 的值即可輸出
//int index = Arrays.binarySearch(apple,sc.nextInt());
int index = binarySearch(apple,sc.nextInt());
if (index < 0){
System.out.println(-index-1);
}
else {
System.out.println(index);
}
}
}
private static int binarySearch(int[] apple, int k){
int start = 1; int end = apple.length-1;
int mid = start - (start-end)/2;
while (start <= end){
if (apple[mid]>k){
end = mid-1;
}
else if (apple[mid]<k){
start = mid+1;
}
else {
return mid;
}
mid = start - (start-end)/2;
}
return start;
}
}
題目三
題目描述
給你n個a,m個z組成所有可能的字符串,並將字符串按字典序從小到大排列,輸出第k個字符串。
若不存在,輸出-1。
輸入描述
第一行爲三個數,分別爲a的個數n,z的個數m,第k個字符串。
輸出描述
第k個字符串
示例
輸入
2 2 6
輸出
zzaa
思路
- 最開始的思路,將 a 和 z 放到一個 char 數組中,然後執行回溯法,對組合全排列;AC 20%
import java.util.*;
public class test {
private static TreeSet<String> res = new TreeSet<>();
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {//注意while處理多個case
int n = in.nextInt();
int m = in.nextInt();
int k = in.nextInt();
char[] s = new char[n+m];
for (int i=0;i<n;i++){
s[i] = 'a';
}
for (int i=n;i<n+m;i++){
s[i] = 'z';
}
getMax(s,0,n+m-1);
Iterator itSet = res.iterator();
while (itSet.hasNext() && k-->0){
itSet.next();
if (k==1) System.out.println(itSet.next());
}
}
}
private static void getMax(char[] array,int i , int n){
//全排列,回溯法:遞歸+循環
if(i == array.length){//該組合排列完全,可以計算
res.add(String.valueOf(array));
}
else{
for(int k =i;k<=n;k++){//回溯
swap(array,k,i);
getMax(array,i+1,array.length-1);
swap(array,k,i);
}
}
}
private static void swap(char[] array,int i, int j){
char temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
- 網上看的,別人採用 DFS 的方式,進行剪枝
package Interview.wangyi.wangyi_0811;
import java.util.ArrayList;
import java.util.Scanner;
public class zifuchuan {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
int k = in.nextInt();
ArrayList<String> list = new ArrayList<>();
//深度優先存儲所有字符串,然後取出第k個字符串
dfs(n,m,list,"");
if (list.size()<k){
System.out.println(-1);
}
else {
System.out.println(list.get(k-1)); //從0開始
}
}
//此處DFS ,對它進行了剪枝,循環次數大大減少,但是依然不適合數據量大的時候
private static void dfs(int n , int m , ArrayList<String> list,String s){
if (m==0 && n==0){
list.add(s);
}
else {
if (n>0){
dfs(n-1,m,list,s+'a');
}
if (m>0){
dfs(n,m-1,list,s+'z');
}
}
}
}
- 動態規劃
import java.util.Scanner;
public class zifuchuan2 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
int k = in.nextInt();
//構建dp數組,計算每種選擇下的組合而成的字符串個數
int[][] dp = new int[n+1][m+1];
//假設dp[i][j]表示i個a和j個z的方案數,根據上面這個公式列表計算我們可以發現:d[i][j] = dp[i-1][j] + dp[i][j-1];
dp[0][0] = 1;
for (int i=0;i<=n;i++){
dp[i][0] = 1;
}
for (int j=0;j<=m;j++){
dp[0][j] = 1;
}
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
StringBuilder sb = new StringBuilder();
//假設我們現在考慮輸出字符串的第i個字符,如果當前選了a字符
//假設後面剩餘字符a和z的個數是m1,n1,那麼後面所能組成的字符串總數爲dp[m1][n1]
//如果k小於dp[m1][n1],那麼我們就能選a,因爲後面組成的數目大於k,我們要選字符a來縮小這個組合數
//否則,就選z,這時k -= dp[m1][n1],這是因爲要減去a形成的方案數
if (k>dp[n][m]){
System.out.println(-1);
}
else {//計算出 第 k 個字符
int n1 = n;
int m1 = m;
for (int i=0;i<m+n;i++){//字符串長度
if (n1>0 && k<=dp[n1-1][m1]){//可以添加 a 到字符串中
sb.append("a");
n1--;
}
else {
if (n1>0){//減去形成 a 形成的方案數
k -= dp[n1-1][m1];
}
sb.append("z");
m1--;
}
}
}
System.out.println(sb.toString());
}
}