1. 程式人生 > >java 彩票走勢圖演算法

java 彩票走勢圖演算法

一、演算法介紹 本博文主要寫了彩票走勢圖中的遺漏值、出現總次數、平均遺漏值、最大遺漏值、最大連出值的計算邏輯。

二、圖文簡介 [這是XX網雙色球的彩票走勢圖,博主這裡是將彩票資料分割槽展示,以雙色球為例,分了五個區域,本博文中的遺漏值是按照期數的降序排列計算的如下圖]

三、工具類簡介(請仔細看完工具類簡介)

彩票走勢圖的工具類**LotteryTrend**中將彩票的名稱彩票的id,及其對應的數字域資料域id,每個區域的起始數字,每個區域的長度等資料按照順序一一對應定義。

另一個工具類**MissValue**就是彩票遺漏值的工具類,裡面是具體的**彩票遺漏值、出現總次數、平均遺漏值、最大遺漏值、最大連出值**的計算方法,博主將開獎位置的遺漏值置為0,返給前端的。下面是這幾個名詞的定義:

**彩票遺漏值**:自上期開出到本期間隔的期數。

**出現總次數**:當前選定的彩票期數區間內該球的出現總次數。

**平均遺漏值**:平均遺漏值計算公式:總期數除以出現的總次數,如果總次數為0,該值為0;如果除不盡將計算結果向下取整。

**最大遺漏值**:歷史開獎以來該球連續不出現的最大值,即為距離上次出現的間隔數的最大值。

**最大連出值**:**博主寫的是選定期數內連續出現的最大值,與右圖不符合**.

四、返回給前端的json資料

五、程式碼塊

import java.math.BigDecimal;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Collections;

import java.util.Comparator;

import java.util.HashMap;

import java.util.LinkedHashMap;

import java.util.LinkedList;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import java.util.Set;

/** * 彩票走勢圖工具類

* @author Administrator * */

public class LotteryTrend {

//所有彩票名稱陣列
public static final String[] titleArray = {"超級大樂透", "七星彩", "排列三", "排列五", "雙色球", "福彩3D", "江西11選5", "11運奪金", "廣東11選5", "上海11選5", "浙江11選5", "七樂彩", "重慶時時彩", "勝負彩", "安徽快三", "湖北快三", "吉林快三", "江蘇快三", "江蘇11選5", "浙江12選5"};

//彩票的id陣列
public static final String[] lotteryidArray = {"19", "18", "2", "13", "16", "1", "9", "8", "10", "24", "27", "17", "3", "71", "32", "33", "34", "35", "28", "22"};
//每種彩票的區域或者數字域
public static final String[][] headArray = {{"紅一區", "紅二區", "紅三區", "後區"}, {"第七位", "第六位", "第五位", "第四位", "第三位", "第二位", "第一位"}, {"百位", "十位", "個位"},
        {"萬位", "千位", "百位", "十位", "個位"}, {"紅一區", "紅二區", "紅三區", "籃球"}, {"百位", "十位", "個位"},
        {"萬位", "千位", "百位", "十位", "個位"}, {"萬位", "千位", "百位", "十位", "個位"}, {"萬位", "千位", "百位", "十位", "個位"},
        {"萬位", "千位", "百位", "十位", "個位"}, {"萬位", "千位", "百位", "十位", "個位"}, {"一區", "二區", "三區"},
        {"萬位", "千位", "百位", "十位", "個位"}, {"3", "1", "0"}, {"百位", "十位", "個位"},
        {"百位", "十位", "個位"}, {"百位", "十位", "個位"}, {"百位", "十位", "個位"},
        {"萬位", "千位", "百位", "十位", "個位"}, {"萬位", "千位", "百位", "十位", "個位"}};

//區域或者數字域的id
public static final String[][] idxArray = {{"area1", "area2", "area3", "back"}, {"num_info7", "num_info6", "num_info5", "num_info4", "num_info3", "num_info2", "num_info1"}, {"num_info3", "num_info2", "num_info1"},
        {"num_info5", "num_info4", "num_info3", "num_info2", "num_info1"}, {"area1", "area2", "area3", "num_info7"}, {"num_info3", "num_info2", "num_info1"},
        {"num_info5", "num_info4", "num_info3", "num_info2", "num_info1"}, {"num_info5", "num_info4", "num_info3", "num_info2", "num_info1"}, {"num_info5",
        "num_info4", "num_info3", "num_info2", "num_info1"}, {"num_info5", "num_info4", "num_info3", "num_info2", "num_info1"}, {"num_info5", "num_info4", "num_info3", "num_info2", "num_info1"},
        {"area1", "area2", "area3"}, {"num_info5", "num_info4", "num_info3", "num_info2", "num_info1"}, {"3", "1", "0"}, {"num_info3", "num_info2", "num_info1"},
        {"num_info3", "num_info2", "num_info1"}, {"num_info3", "num_info2", "num_info1"}, {"num_info3", "num_info2", "num_info1"}, {"num_info5", "num_info4", "num_info3", "num_info2", "num_info1"},
        {"num_info5", "num_info4", "num_info3", "num_info2", "num_info1"}};

//定義每個區域的起始數字
public static final String[][] beginNum = {{"01", "13", "25", "01"}, {"0", "0", "0", "0", "0", "0", "0"}, {"0", "0", "0"},
        {"0", "0", "0", "0", "0"}, {"01", "12", "23", "01"}, {"0", "0", "0"},
        {"1", "1", "1", "1", "1"}, {"1", "1", "1", "1", "1"}, {"1", "1", "1", "1", "1"}, {"1", "1", "1", "1", "1"},
        {"1", "1", "1", "1", "1"}, {"01", "11", "21"}, {"0", "0", "0", "0", "0"}, {"1", "1", "1"}, {"1", "1", "1"},
        {"1", "1", "1"}, {"1", "1", "1"}, {"1", "1", "1"}, {"1", "1", "1", "1", "1"}, {"1", "1", "1", "1", "1"}};
//定義每個區域的長度
public static final int[][] horizontalSpans = {{12, 12, 11, 12}, {10, 10, 10, 10, 10, 10, 10}, {10, 10, 10},
        {10, 10, 10, 10, 10}, {11, 11, 11, 16}, {10, 10, 10},
        {11, 11, 11, 11, 11}, {11, 11, 11, 11, 11}, {11, 11, 11, 11, 11}, {11, 11, 11, 11, 11},
        {11, 11, 11, 11, 11}, {10, 10, 10}, {10, 10, 10}, {14, 14, 14}, {6, 6, 6},
        {6, 6, 6}, {6, 6, 6}, {6, 6, 6}, {11, 11, 11, 11, 11}, {12, 12, 12, 12, 12}};
//是否需要兩位,例如01或者1
public static final String[] isHaveTwoPosition = {"1", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "0"};

//冷熱
public static final String[][] codeAndHotIdxArray = {{"num_info1", "num_info2", "num_info3", "num_info4", "num_info5", "num_info6", "num_info7"},
        {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5", "num_info6", "num_info7"}, {"num_info1", "num_info2", "num_info3"},
        {"num_info3", "num_info2", "num_info1"}, {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5", "num_info6", "num_info7"},
        {"num_info3", "num_info2", "num_info1"}, {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5"}, {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5"},
        {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5"}, {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5"},
        {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5"}, {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5", "num_info6", "num_info7"},
        {"num_info3", "num_info2", "num_info1"}, {}, {"num_info1", "num_info2", "num_info3"}, {"num_info1", "num_info2", "num_info3"}, {"num_info1", "num_info2", "num_info3"},
        {"num_info1", "num_info2", "num_info3"}, {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5"}, {"num_info1", "num_info2", "num_info3", "num_info4", "num_info5"}};

//封裝走勢圖所有的資料

/**
 * list  資料庫查詢到的當前彩種開獎資料集合
 * issueCount  頁面傳來的指定的檢視的總期數
 * totalIssue  當前開獎資料歷史以來的總期數
 */
public static Map<String, Object> trendInfo(List<Map<String, String>> list, String lotteryid, String idx, Integer issueCount, Integer totalIssue) {
    int m = 0, n = 0, horizontalSpan = 0;//m代表當前彩種在彩票id陣列的位置;n代表要展示的區域(如紅一區,後區等)或者數字域(百位,十位,各位等);horizontalSpan水平方向的跨度
    Map<String, Object> map = new LinkedHashMap<String, Object>();//封裝返回資料的集合,包括alldiffs,average_omission,infolist,max_omission,max_output,placenum,result

    //獲取m
    for (int i = 0; i < lotteryidArray.length; i++) {
        if (lotteryidArray[i].equals(lotteryid)) {
            m = i;
            break;
        }
    }
    //System.out.println("當前彩種在彩票id陣列的位置:"+m);
    //獲取n
    for (int i = 0; i < idxArray[m].length; i++) {
        if (idxArray[i].equals(idx)) {
            n = i;
            break;
        }
    }
    //System.out.println("要展示走勢的當前彩票的區域:"+n);

    //獲取水平跨度
    horizontalSpan = horizontalSpans[m][n];

    //封裝開獎資料
    List<Map<String, String>> infolist = new ArrayList<>();
    if (issueCount <= totalIssue) {
        for (int j = 0; j < issueCount; j++) {
            //封裝每一條開獎資料
            String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
            Map<String, String> ma1 = new LinkedHashMap<String, String>();
            //封裝期號
            ma1.put("id", list.get(j).get("id"));

            //封裝id
            ma1.put("lottery_num", list.get(j).get("termNo"));
            //封裝開獎號碼
            for (int i = 0; i < codeAndHotIdxArray[m].length; i++) {
                ma1.put(codeAndHotIdxArray[m][i], sp[i]);
            }
            infolist.add(ma1);
        }
    } else {
        for (int j = 0; j < totalIssue; j++) {
            //封裝每一條開獎資料
            String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
            Map<String, String> ma1 = new LinkedHashMap<String, String>();
            //封裝期號
            ma1.put("id", list.get(j).get("id"));

            //封裝id
            ma1.put("lottery_num", list.get(j).get("termNo"));
            //封裝開獎號碼
            for (int i = 0; i < codeAndHotIdxArray[m].length; i++) {
                ma1.put(codeAndHotIdxArray[m][i], sp[i]);
            }
            infolist.add(ma1);
        }
    }
    map.put("infolist", infolist);
    //轉換資料格式
    List<List<Integer>> convertList = MissingValue.convertAwardData(list);

    //獲得當前彩種的所有遺漏值資料
    int[][] alldiff_totalIssue = MissingValue.getMissingvalue(convertList, Integer.parseInt(beginNum[m][n]), totalIssue, horizontalSpan);
    //獲得當前彩種的指定期的遺漏值資料
    int[][] alldiffs = null;
    if (issueCount <= totalIssue) {
        alldiffs = new int[issueCount][horizontalSpan];
        for (int i = 0; i < alldiffs.length; i++) {
            for (int j = 0; j < horizontalSpan; j++) {
                alldiffs[i][j] = alldiff_totalIssue[i][j];
            }
        }
    } else {
        alldiffs = new int[totalIssue][horizontalSpan];
        for (int i = 0; i < alldiffs.length; i++) {
            for (int j = 0; j < horizontalSpan; j++) {
                alldiffs[i][j] = alldiff_totalIssue[i][j];
            }
        }
    }
    map.put("alldiffs", alldiffs);

    //出現總次數
    List<Integer> placenum = MissingValue.getTotal(alldiffs);

    //平均遺漏值
    List<Integer> average_omission = null;
    if (issueCount <= totalIssue) {
        average_omission = MissingValue.getCoverage(placenum, issueCount);
    } else {
        average_omission = MissingValue.getCoverage(placenum, totalIssue);
    }
    //最大遺漏值
    List<Integer> max_omission = MissingValue.getMax(alldiff_totalIssue);

    //最大連出值
    List<Integer> max_output = MissingValue.getContinuous(alldiffs);
    map.put("max_output", max_output);
    map.put("placenum", placenum);
    map.put("average_omission", average_omission);
    map.put("max_omission", max_omission);
    return map;
}

//封裝冷熱的資料
public static Map<String, Object> saveColoHot(List<Map<String, String>> list, String lotteryid, String idx, Integer issueCount, Integer totalIssue) {
    int m = 0, n = 0;//m代表當前彩種在彩票id陣列的位置,n代表冷熱的區域
    Map<String, Object> map = new LinkedHashMap<String, Object>();//封裝返回資料的集合,包括alldiffs,average_omission,infolist,max_omission,max_output,placenum,result

    //獲取m
    for (int i = 0; i < lotteryidArray.length; i++) {
        if (lotteryidArray[i].equals(lotteryid)) {
            m = i;
            break;
        }
    }

    //獲取n
    for (int i = 0; i < codeAndHotIdxArray[m].length; i++) {
        if (codeAndHotIdxArray[i].equals(idx)) {
            n = i;
            break;
        }
    }
    //獲取開獎資料
    List<List<String>> infolist = new ArrayList<>();
    if (issueCount <= totalIssue) {
        for (int j = 0; j < issueCount; j++) {
            //封裝每一條開獎資料
            String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
            List<String> li = new ArrayList<>();
            //封裝開獎號碼
            for (int i = 0; i < sp.length; i++) {
                li.add(sp[i]);
            }
            infolist.add(li);
        }
    } else {
        for (int j = 0; j < totalIssue; j++) {
            //封裝每一條開獎資料
            String[] sp = list.get(j).get("result").replaceFirst("\\+", ",").split(",");
            List<String> li = new ArrayList<>();
            //封裝開獎號碼
            for (int i = 0; i < sp.length; i++) {
                li.add(sp[i]);
            }
            infolist.add(li);
        }
    }

    List<LinkedHashMap<String, String>> placenum = getColdHot(infolist, idx, n);
    map.put("placenum", placenum);
    map.put("result", "success");
    return map;
}


//獲得冷熱的資料
public static List<LinkedHashMap<String, String>> getColdHot(List<List<String>> infolist, String idx, Integer n) {
    List<LinkedHashMap<String, String>> list = new ArrayList<>();

    //對出現的次數做降序排列
    Map<String, Integer> map = new HashMap<>();
    for (int i = 0; i < infolist.size(); i++) {
        if (map.containsKey(infolist.get(i).get(n))) {
            map.put(infolist.get(i).get(n), map.get(infolist.get(i).get(n)) + 1);
        } else {
            map.put(infolist.get(i).get(n), 1);
        }
    }
    List<Entry<String, Integer>> sortMap = sortMap(map);

    //封裝冷熱圖的資料
    for (Entry<String, Integer> entry : sortMap) {
        String key = entry.getKey();
        Integer value = entry.getValue();
        BigDecimal b1 = new BigDecimal(Double.toString(value * 100));
        BigDecimal b2 = new BigDecimal(Double.toString(infolist.size()));
        double countunm = b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
        LinkedHashMap<String, String> lhm = new LinkedHashMap<>();
        lhm.put(idx, key);
        lhm.put("countid", value + "");
        String countunm1 = String.valueOf(countunm);
        if ((countunm1.split("\\.")[1]).length() == 1) {//此情況代表countunm是整數,小數點後面只有一個0,為滿足資料(資料格式:xx.yy00)封裝要求,要新增三個0
            lhm.put("countunm", countunm1 + "000");
        } else {
            lhm.put("countunm", countunm1 + "00");
        }
        list.add(lhm);
    }

    return list;
}

//對map集合value實現降序排列
public static List<Map.Entry<String, Integer>> sortMap(Map<String, Integer> map) {
    //獲取entrySet
    Set<Map.Entry<String, Integer>> mapEntries = map.entrySet();

    //使用連結串列來對集合進行排序,使用LinkedList,利於插入元素
    List<Map.Entry<String, Integer>> result = new LinkedList<>(mapEntries);
    //自定義比較器來比較連結串列中的元素
    Collections.sort(result, new Comparator<Entry<String, Integer>>() {
        //基於entry的值(Entry.getValue()),來排序連結串列
        @Override
        public int compare(Entry<String, Integer> o1,
                           Entry<String, Integer> o2) {

            return o2.getValue().compareTo(o1.getValue());
        }

    });

    //將排好序的存入到LinkedHashMap(可保持順序)中,需要儲存鍵和值資訊對到新的對映中。
    Map<String, Integer> linkMap = new LinkedHashMap<>();
    for (Entry<String, Integer> newEntry : result) {
        linkMap.put(newEntry.getKey(), newEntry.getValue());
    }
    /*//根據entrySet()方法遍歷linkMap
    for(Map.Entry<String, Integer> mapEntry : linkMap.entrySet()){
        System.out.println("key:"+mapEntry.getKey()+"  value:"+mapEntry.getValue());
    }*/

    return result;
}
}

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @admistrator 計算遺漏值的工具類
 */
public class MissingValue {
    /**
     * 獲取整個區域的遺漏值
     * lis 開獎資料的集合(從資料查詢到的開獎資料集合)
     * row 行數
     * column 列數
     */
    public static int[][] getMissingvalue(List<List<Integer>> lis, Integer beginNum, Integer row, Integer horizontalSpan) {
        int[][] arr = new int[row][horizontalSpan];

        //獲取整個區域的遺漏值
        for (int k = 1; k <= horizontalSpan; k++) {

            //獲取每期開獎資料在當前列的位置
            List<Integer> countList = new ArrayList<Integer>();
            for (int i = 0; i <= lis.size() - 1; i++) {
                for (int j = 0; j < lis.get(i).size(); j++) {
                    if (lis.get(i).get(j) > beginNum + horizontalSpan - 1) {
                        break;
                    }
                    if (lis.get(i).get(j) == k) {
                        countList.add(i);//記錄當前列的開獎號碼的行號
                    }
                }
            }

            if (countList.size() != 0 && countList != null) {
                int[] arrj = getOthers(countList, arr.length);
                for (int j = 0; j < arrj.length; j++) {
                    arr[j][k - 1] = arrj[j];
                }
            } else {
                for (int j = arr.length - 1; j >= 0; j--) {
                    arr[j][k - 1] = arr.length - j;
                }
            }
        }

        return arr;
    }


    //獲取每列的遺漏值資料
    public static int[] getOthers(List<Integer> list, int row) {
        int[] array = new int[row];
        int n = 0;
        while (true) {
            if (list.size() == 1) {
                if (list.get(n) == 0) {//中獎號碼只有一個且在頂部
                    array[n] = 0;
                    for (int i = array.length - 1; i > 0; i--) {
                        array[i] = array.length - i;
                    }
                } else if (list.get(n) == row - 1) {//中獎號碼只有一個且在底部
                    for (int i = list.get(n); i >= 0; i--) {
                        array[i] = list.get(n) - i;
                    }
                } else if (list.get(n) > 0 && list.get(n) < row - 1) {//中獎號碼只有一個且在中間
                    for (int i = array.length - 1; i > list.get(n); i--) {
                        array[i] = array.length - i;
                    }
                    for (int i = list.get(n); i >= 0; i--) {
                        array[i] = list.get(n) - i;
                    }
                }
            } else if (list.size() > 1) {
                if (n == 0) {//第1個開獎號碼
                    if (list.get(n) == 0) {//當前中獎號碼在頂部
                        array[n] = 0;
                    } else if (list.get(n) < row - 1) {//當前號碼在中間
                        for (int i = list.get(n); i >= 0; i--) {
                            array[i] = list.get(n) - i;
                        }
                    }
                } else if (n + 1 < list.size() && n > 0) {//當前為第n+1個開獎號碼,而且不是最後一個,那麼當前號碼一定在中間
                    if (list.get(n) - list.get(n - 1) - 1 != 0) {//開獎號碼有間隔
                        for (int i = list.get(n); i > list.get(n - 1); i--) {
                            array[i] = list.get(n) - i;
                        }
                    } else {//開獎號碼沒有間隔
                        array[list.get(n)] = 0;
                    }
                } else if (n + 1 == list.size() && n > 0) {//當前開獎號碼為這一列的最後一個開獎號碼
                    if (list.get(n) - list.get(n - 1) - 1 > 0) {//開獎號碼有間隔
                        if (list.get(n) == row - 1) {//當前中獎號碼在底部
                            for (int i = list.get(n); i > list.get(n - 1); i--) {
                                array[i] = list.get(n) - i;
                            }
                        } else if (list.get(n) < row - 1) {//當前號碼在中間
                            for (int i = list.get(n); i > list.get(n - 1); i--) {
                                array[i] = list.get(n) - i;
                            }
                            for (int i = array.length - 1; i >= list.get(n) + 1; i--) {
                                array[i] = array.length - i;
                            }
                        }
                    } else if (list.get(n) - list.get(n - 1) - 1 == 0) {//開獎號碼沒有間隔
                        if (list.get(n) == row - 1) {//當前中獎號碼在底部
                            array[list.get(n)] = 0;
                        } else if (list.get(n) < row - 1) {//當前號碼在中間
                            array[list.get(n)] = 0;
                            for (int i = array.length - 1; i > list.get(n); i--) {
                                array[i] = array.length - i;
                            }
                        }
                    }

                    break;
                }

            }

            if (n == list.size() - 1) {
                break;
            }
            n++;
        }
        return array;
    }

    /**
     * 處理開獎資料的方法
     * 實現的功能:將每一期在當前區域的開獎資料獲取出來,並轉換為int 型別
     * lis 開獎資料的集合
     */
    public static List<List<Integer>> convertAwardData(List<Map<String, String>> lis) {
        List<List<Integer>> list = new ArrayList<>();
        for (int i = 0; i < lis.size(); i++) {
            List<Integer> lii = new ArrayList<>();
            String[] sp = lis.get(i).get("result").replaceFirst("\\+", ",").split(",");
            for (int j = 0; j < sp.length; j++) {
                lii.add(Integer.parseInt(sp[j]));
            }
            list.add(lii);
        }
        return list;
    }

    /**
     * 計算每列開獎的總次數(即:出現總次數)
     * <p>
     * arr 遺漏值資料的陣列
     */
    public static List<Integer> getTotal(int[][] arr) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < arr[0].length; i++) {
            int count = 0;
            for (int j = 0; j < arr.length; j++) {
                if (arr[j][i] == 0) {
                    count++;
                }
            }
            list.add(count);
        }
        return list;
    }

    /**
     * 計算平均遺漏值
     * <p>
     * lis 出現總次數集合
     * row  總行數
     */
    public static List<Integer> getCoverage(List<Integer> lis, Integer row) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < lis.size(); i++) {
            if (lis.get(i) != 0) {
                list.add(row / lis.get(i));
            } else {
                list.add(0);
            }
        }
        return list;
    }

    /**
     * 計算最大遺漏值
     * <p>
     * arr 遺漏值的集合
     */
    public static List<Integer> getMax(int[][] arr) {
        List<Integer> ll = new ArrayList<Integer>();
        for (int i = 0; i < arr[0].length; i++) {
            int max = arr[0][i];
            for (int j = 0; j < arr.length; j++) {
                if (arr[j][i] > max)
                    max = arr[j][i];
            }
            ll.add(max);
        }
        return ll;
    }


    /**
     * 計算最大連出值
     * <p>
     * arr 遺漏值的集合
     */
    public static List<Integer> getContinuous(int[][] arr) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < arr[0].length; i++) {
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < arr.length; j++) {
                sb.append(arr[j][i]);
            }
            list.add(max(sb.toString()));
        }
        return list;
    }

    //統計相同字元連續出現的最大子序列的長度
    public static int max(String s) {
        int max = 0, tmp_m = 1;
        for (int i = 1; i < s.length(); i++) {
            if (s.charAt(i) == s.charAt(i - 1)) {
                tmp_m++;
            } else {
                max = max > tmp_m ? max : tmp_m;
                tmp_m = 1;
            }
        }
        max = max > tmp_m ? max : tmp_m;//最後的連續數與最大連續的比較
        return max;
    }

}