1. 程式人生 > 其它 >LeetCode93. 復原 IP 地址

LeetCode93. 復原 IP 地址

LeetCode93. 復原 IP 地址

題目描述

/**
     * 
     * 給定一個只包含數字的字串,用以表示一個 IP 地址,
     * 返回所有可能從 s 獲得的 有效 IP 地址 。你可以按任何順序返回答案。
     * <p>
     * 有效 IP 地址 正好由四個整數(每個整數位於 0 到 255 之間組成,且不能含有前導 0),
     * 整數之間用 '.' 分隔。
     * <p>
     * 例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,
     * 但是 "0.011.255.245"、"192.168.1.312" 和 "[email protected]" 是 無效 IP 地址。
     *
     */

思路分析

  1. 復原IP地址,即給定一個數字字串,按照IP地址規則將其復原為多個滿足條件的IP地址
  2. 很容易想到遞迴 + 回溯的方法
  3. 定義一個大小為4 的全域性陣列,用於儲存IP地址的每一段,因此還需要一個索引記錄是那一段
  4. 使用深度優先的方式,即遍歷字串,選擇一個滿足條件的數字字串作為IP地址的第一段,等條件不滿足或找到滿足的後再回溯尋找第一個滿足的其他字串,然後從未選擇的字串開始,依次再選擇第二段,第二段仍然有很多選擇,先選擇一個,等條件不滿足或找到滿足的後再回溯,直至選擇到最後一段
  5. 不斷的遞迴 + 回溯,直到找到所有滿足的或者篩選掉所有不滿足的
  6. 遞迴結束的條件為儲存每一段的陣列中都儲存了滿足格式的字串,並且字串全部遍歷結束,說明找到滿足IP遞迴規則的,則結束
  7. 或者陣列已滿,但是字串還沒有遍歷完,說明不滿足
  8. 還要考慮字串的某一位為零的情況,則直接將零作為單獨的一段即可
  9. 其他正常情況遞迴+回溯即可
  10. 原始碼見下

原始碼及分析

//表示總共將字串分為4段
    static final int SEG_COUNT = 4;
    //建立集合儲存結果
    List<String> list = new ArrayList<>();
    //建立陣列儲存每一段的元素
    int[] segments = new int[SEG_COUNT];

    public List<String> restoreIpAddresses(String s) {
        dfs(s,0,0);
        return list;
    }

    /**
     * 從字串s的start位置開始尋找下一段的元素
     *
     * @param s     字串
     * @param seg   表示第幾段
     * @param start 下一段開始位置索引
     */
    public void dfs(String s, int seg, int start) {
        //如果找到了四段ip並且遍歷完了字串,那麼就是一種答案
        if (seg == SEG_COUNT){
            if (start == s.length()){
                //走到這一步說明segments陣列中已經存在一個滿足要求的答案,將其拼接轉成字串即可
                StringBuffer ipAddress = new StringBuffer();
                for (int i = 0; i < SEG_COUNT; i++) {
                    //拼接字串
                    ipAddress.append(segments[i]);
                    //拼接 .
                    if (i != SEG_COUNT - 1){
                        ipAddress.append('.');
                    }
                }
                //將拼接後的結果新增到集合中
                list.add(ipAddress.toString());
            }
            //找到一個後繼續回溯
            return;
        }
        //如果還沒找到4段IP就已經遍歷完了字串,那麼提前回溯
        if (start == s.length()){
            return;
        }
        //由於前導不能為零,如果遇到零,只能將0作為這一段的ip
        if (s.charAt(start) == '0') {
            segments[seg] = 0;
            dfs(s, seg + 1, start + 1);
        }
        //正常情況下,列舉每一種可能性並遞迴
        //定義變數儲存每一段的結果
        int address = 0;
        //從start開始遍歷,直到遍歷完字串
        for (int i = start; i < s.length(); i++) {
            //先將每一段的字元轉為數字
            address = address * 10 + (s.charAt(i) - '0');
            //判斷當前段的地址是否滿足條件,如果滿足,則遞迴判斷下一段,否則結束
            if (address > 0 && address <= 255) {
                segments[seg] = address;
                dfs(s, seg + 1, i + 1);
            }else {
                break;
            }
        }
    }