1. 程式人生 > >[算法]2018年阿裏巴巴數據研發工程師編程題

[算法]2018年阿裏巴巴數據研發工程師編程題

equal 遍歷 分代 != bst 範例 是把 圖片 binary

題目:

技術分享圖片

技術分享圖片

技術分享圖片

思路:

這道題開始我完全沒明白在講啥,可能是我自己算法這塊訓練太少了吧,也是看了好久才明白。開始說“向三位同學提到。。。”,我以為除了兩位同學之外還有別人,額,好吧,並沒有。。。還有它的輸入輸出範例開始折疊著,完全沒看到好吧。。。並且輸入範例給的兩個參數,給的代碼模板的方法就傳了一個參數,也是醉了。。。這種其他因素影響了我很多時間,好了,不吐槽了,言歸正傳!

最開始的思路是利用四叉樹,如果0代表當天還清,1代表當天沒有還清,還有欠款。那麽第一天兩個人(小波和小錢)有四種情況00,01,10,11。第二天以此類推,總共有4的3次方種情況,也就是說遍歷四叉樹即可。但是這種方法太麻煩。

魏印福給出的另一種思路簡直太贊,一共需要做6種決策:1、第一天,給甲還不?2、第一天,給乙還不;3、第二天,給甲還不?4、第二天,給乙還不;。。。這樣總共有2的6次方種情況。他想的是用二進制的方式表示:0到63,用二進制表示成000000到111111,這樣一來我就可以第一位代表第一天是否還清小波,第二位代表第一天是否還清小錢,第三位代表第二天是否還清小波,第四位代表第二天是否還清小錢,第五位代表第三天是否還清小波,第六位代表第三天是否還清小錢。這樣一來他根據二進制的移位操作便可以算出三種規則累計的失信分。部分代碼如下:

package com.darrenchan;

import java.io.*;
import java.util.*; import java.text.*; import java.math.*; import java.util.regex.*; public class Main { static final int N = 1 << 6; /** * 某個人沒有還款,扣一分 */ static int rule0(int x) { int ans = 0; for (int i = 0; i < 6; i++) { if ((x & (1 << i)) != 0) { ans
++; } } return ans; } /** * 同一天內一點都沒還款,扣一分 */ static int rule1(int x) { int ans = 0; for (int i = 0; i < 6; i += 2) { if ((x & (1 << i)) != 0 && ((x & (1 << (i + 1))) != 0)) ans++; } return ans; } /** * 三天都存在逾期記錄,扣一分 */ static int rule2(int x) { int ans = 0; for (int i = 0; i < 6; i += 2) { if ((x & (1 << i)) != 0 || (x & (1 << (i + 1))) != 0) { ans++; } } if (ans == 3) return 1; else return 0; } /** * 給決策x進行打分 */ static int parse(int x) { return rule0(x) + rule1(x) + rule2(x); } public static void main(String[] args) { int sum = 1 << 6;//一共有64種情況 for (int i = 0; i < sum; i++) { System.out.println(Integer.toBinaryString(i) + ":" + parse(i)); } } }

根據其思路,我沒有用二進制的移位操作,而是把二進制轉成字符串,然後操作字符串,我想的代碼如下:

package com.darrenchan;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main2 {
    public static void main(String[] args) {
        int num = 1 << 6;// 一共情況
        List<String> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            String str = Integer.toBinaryString(i);
            // 如果不是6位,則進行補齊
            StringBuilder sb = new StringBuilder(str);
            if (str.length() < 6) {
                for (int j = 0; j < 6 - str.length(); j++) {
                    sb.insert(0, 0);
                }
            }
            list.add(sb.toString());
        }
        for (String item : list) {
            int score = getFinalScore(item);
            System.out.println(item + ":" + score);
        }
        
    }

    /**
     * 傳入字符串,獲取失信分數
     * @param list
     * @return
     */
    private static int getFinalScore(String item) {
        int score = 0;
        // 匹配rule1
        for (int i = 0; i < item.length(); i++) {
            if (‘1‘ == item.charAt(i)) {
                score++;
            }
        }
        // 匹配rule2
        if(item.substring(0, 2).equals("11")) score++;
        if(item.substring(2, 4).equals("11")) score++;
        if(item.substring(4).equals("11")) score++;
        // 匹配rule3
        int sum = 0;
        for (int i = 0; i < item.length(); i += 2) {
            sum += (item.charAt(i) == ‘1‘ || item.charAt(i + 1) == ‘1‘) ? 1 : 0;
        }
        if (sum == 3)
            score++;
        
        
        return score;
    }
}

結果展示為:

000000:0
000001:1
000010:1
000011:3
000100:1
000101:2
000110:2
000111:4
001000:1
001001:2
001010:2
001011:4
001100:3
001101:4
001110:4
001111:6
010000:1
010001:2
010010:2
010011:4
010100:2
010101:4
010110:4
010111:6
011000:2
011001:4
011010:4
011011:6
011100:4
011101:6
011110:6
011111:8
100000:1
100001:2
100010:2
100011:4
100100:2
100101:4
100110:4
100111:6
101000:2
101001:4
101010:4
101011:6
101100:4
101101:6
101110:6
101111:8
110000:3
110001:4
110010:4
110011:6
110100:4
110101:6
110110:6
110111:8
111000:4
111001:6
111010:6
111011:8
111100:6
111101:8
111110:8
111111:10

最後再根據題目要求轉換成需要輸出的字符串語句,並且寫一個求指定日期的後一天的方法,這個就不贅述了。

[算法]2018年阿裏巴巴數據研發工程師編程題