網易2018內推筆試編程題

題目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. 我的思路是統計所有爲 1 的 時間的興趣值,O(N)
  2. 再次遍歷,遇到爲 0 的時候,統計 之後的 k 個數,並且跳過爲 1 個數字不統計
  3. 比較並獲得最大值
  4. 這種方法的實質也算是暴力法,更好的方法應該是使用動態規劃

代碼: 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

思路

對蘋果數量求累加和,然後運用二分查找即可

  1. 採用 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);
         }

        }
    }
}
  1. 自己實現二分查找
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

思路

  1. 最開始的思路,將 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;
    }
}
  1. 網上看的,別人採用 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');
            }
        }
    }
}
  1. 動態規劃
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());
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章