LeetCode93復原IP地址

復原IP地址>>>

在這裏插入圖片描述
在這裏插入圖片描述

package BDyNamicProgramming;

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

/**
 * @Author Zhou  jian
 * @Date 2020 ${month}  2020/4/26 0026  17:34
 * 復原IP地址
 */
public class Problem93 {


    /**
     * 回溯+剪枝
     * @param s
     * @return
     * 回溯算法事實上就是在一個樹形問題上做深度優先遍歷,因此首先需要把問題轉換成樹形問題
     * 這裏請及大家一定要拿起紙盒筆,模擬一下如何通過制定的字符串s生成IP地址的過程,把樹形圖畫出來
     * 在畫樹形圖的過程中,一定會發現有些樹枝是沒有必要的,把沒有必要的枝葉剪去的操作就是兼職

     這個問題思想不難,但是細節比較繁瑣,什麼時候遞歸終止,如何手動截取字符串,再轉換成int類型
     還有如何在中間節點發現可以兼職,這些
     */
    /**
     * 本題可以使用回溯和遞歸的思想復原ip地址:
     *
     *      1、首先創建ans來接受復原後的所有ip地址,然後通過創建 回溯方法進行篩選,最終返回ans
     *
     *      2、創建回溯方法體需要傳入四各參數進行把控:
     *              1、給定的數字字符串s
     *              2、回溯過程中遍歷到的位置pos,
     *              3、當前確定好的ip段的數量
     *              4、收集結果的ans
     *
     *      3、考慮方法體出口:如果確定好4個段並且遍歷完整個s,就將cur之間的端以.分隔開發來放入ans
     *
     *      4、接下來對s進行篩選,其中注意每段的長度最大爲3,拆箱int後的長度不超過,其實位置不能爲0
     *
     * @param s
     * @return
     */
    public List<String> restoreIpAddresses(String s) {

        List<String> ans = new ArrayList<>();
        if (s == null || s.length() == 0) {
            return ans;
        }
        // 回溯
        back(s, 0, new ArrayList<>(), ans);


        return ans;
    }

    // 中間兩個參數解釋:pos-當前遍歷到 s 字符串中的位置,cur-當前存放已經確定好的 ip 段的數量

    /**
     *
     * @param s
     * @param pos  當前遍歷到 s 字符串中的位置
     * @param cur cur-當前存放已經確定好的 ip 段的數量
     * @param ans  最終的結果
     */
    private void back(String s, int pos, List<String> cur,  List<String> ans) {
        //遞歸結束條件
        //當前遍歷的cur中的個數爲4
        if (cur.size() == 4) {

            // 如果此時 pos 也剛好遍歷完整個 s
            if (pos == s.length()) {
                // join 用法:例如 [[255],[255],[111],[35]] -> 255.255.111.35
                ans.add(String.join(".", cur));
            }


            return;
        }

        // ip 地址每段最多有三個數字
        for (int i = 1; i <= 3; i++) {

            // 如果當前位置距離 s 末尾小於 3 就不用再分段了,直接跳出循環即可。
            if (pos + i > s.length()) {
                break;
            }

            // 將 s 的子串開始分段:pos 到pos i
            String segment = s.substring(pos, pos + i);


            // 剪枝條件:段的起始位置不能爲 0,
            // 段拆箱成 int 類型的長度不能大於 255
            if ((segment.startsWith("0") && segment.length() > 1)|| (i == 3 && Integer.parseInt(segment) > 255)) {
                continue;
            }


            // 符合要求就加入到 cur 數組中
            cur.add(segment);

            // 繼續遞歸遍歷下一個位置
            back(s, pos + i, cur, ans);

            // 回退到上一個元素,即回溯
            cur.remove(cur.size() - 1);
        }
    }






}




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