Leetcode上的dfs問題

下面的題目是我刷的Leetcode上關(guān)于深度優(yōu)先搜索的題目,因?yàn)轭}還沒刷完,所以這篇文章會(huì)將不時(shí)地進(jìn)行續(xù)更

package cn.infobuy.gouqi.demo;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
 * DFS 深度優(yōu)先搜索
 * @author Administrator
 *
 */
public class DepthFirstSearchSolution {
    class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) {
            val = x;
        }   
    }
    class ListNode {
        int val;
        ListNode next;
        ListNode(int x) { val = x; }
    }
    /**
     * 在每個(gè)樹行中找最大值
     * @param root
     * @return
     */
    public List<Integer> largestValues(TreeNode root) {
//      Queue<TreeNode> queue = new LinkedList<TreeNode>();
//      while(root!=null){
//          
//      }
        return null;
    }
     public int sumNumbers(TreeNode root) {
         if(root==null){
             return 0;
         }
         return sumNumbers(root,0);
     }
    private int sumNumbers(TreeNode root,int prefixNumber) {
        // 葉子節(jié)點(diǎn)
        if(root.left==null&&root.right==null){
            return prefixNumber*10+root.val;
        }
        int sumNumber=0;
        if(root.left!=null){
            sumNumber+=sumNumbers(root.left,prefixNumber*10+root.val);
        }
        if(root.right!=null){
            sumNumber+=sumNumbers(root.right,prefixNumber*10+root.val);
        }
        return sumNumber;
    }

    /**
     * 判斷是否為相同的樹
     * 給定兩個(gè)二叉樹,編寫一個(gè)函數(shù)來檢驗(yàn)它們是否相同南片。如果兩個(gè)樹在結(jié)構(gòu)上相同变姨,并且節(jié)點(diǎn)具有相同的值纽匙,則認(rèn)為它們是相同的丽惭。
     * 通過深度優(yōu)先遍歷
     * @param p
     * @param q
     * @return
     */
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p==null|q==null){
            if(p==q){
                return true;
            }else{
                return false;
            }
        }
        return p.val==q.val&&isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
    }
    /**
     * 判斷是否為對稱二叉樹
     * @param root
     * @return
     */
    public boolean isSymmetric(TreeNode root) {
        if(root==null){
            return true;
        }
        return isSymmetric(root.left,root.right);
    }
    private boolean isSymmetric(TreeNode left,TreeNode right){
        if(left==null||right==null){
            if(left==null&&right==null){
                return true;
            }else{
                return false;
            }
        }
        return (left.val==right.val)&&isSymmetric(left.left,right.right)&&isSymmetric(left.right,right.left);
    }
    /**
     * 找出二叉樹的深度
     * @param root
     * @return
     */
    public int maxDepth(TreeNode root) {
        if(root==null){
            return 0;
        }
        return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
    }
    /**
     * 驗(yàn)證是否為二叉搜索樹 BST
     * @param root
     * @return
     */
    public boolean isValidBST(TreeNode root) {
        return isValidBST(root,Long.MIN_VALUE,Long.MAX_VALUE);
    }
    public boolean isValidBST(TreeNode root,long min,long max) {
        if(root==null) {
            return true;
        }
        return isValidBST(root.left,min,root.val)&&isValidBST(root.right,root.val,max)&&root.val>min&&root.val<max;
    }
    /**
     * 驗(yàn)證是否是平衡二叉樹
     * 平衡二叉樹的特征:一個(gè)二叉樹每個(gè)節(jié)點(diǎn) 的左右兩個(gè)子樹的高度差的絕對值不超過1
     * @param root
     * @return
     */
    public boolean isBalanced(TreeNode root) {
        if(root==null) {
            return true;
        }
        return isBalanced(root.left)&&isBalanced(root.right)&&(Math.abs(maxDepth(root.left)-maxDepth(root.right))<=1);
    }
    /**
     * 找出二叉樹的最小深度
     * @param root
     * @return
     */
    public int minDepth(TreeNode root) {
        if(root==null) {
            return 0;
        }
        if(root.left==null&&root.right==null) {
            return 1;
        }
        if(root.left==null) {
            return minDepth(root.right)+1;
        }
        if(root.right==null) {
            return minDepth(root.left)+1;
        }
        return Math.min(minDepth(root.left),minDepth(root.right))+1;
    }
    /**
     * 路徑總和
     * 給定一個(gè)二叉樹和一個(gè)目標(biāo)和击奶,判斷該樹中是否存在根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑,這條路徑上所有節(jié)點(diǎn)值相加等于目標(biāo)和
     * @param root
     * @param sum
     * @return
     */
    public boolean hasPathSum(TreeNode root, int sum) {
        if(root==null) {
            return false;
        }
        if(root.left==null&&root.right==null) {
            return root.val==sum;
        }
        return hasPathSum(root.left,sum-root.val)||hasPathSum(root.right,sum-root.val);
    }
    /**
     * 路徑總和 II
     * 給定一個(gè)二叉樹和一個(gè)目標(biāo)和责掏,找到所有從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)路徑總和等于給定目標(biāo)和的路徑
     * @param root
     * @param sum
     * @return
     */
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        if(root==null) {
            return new ArrayList<List<Integer>>(0);
        }
        // 葉子節(jié)點(diǎn)
        if(root.left==null&&root.right==null) {
            if(sum==root.val) {
                List<List<Integer>> iList = new ArrayList<List<Integer>>(0);
                List<Integer> list = new LinkedList<Integer>();
                list.add(root.val);
                iList.add(list);
                return iList;
            }else {
                return new ArrayList<List<Integer>>(0);
            }
        }
        // 子節(jié)點(diǎn)
        List<List<Integer>> mainList=new ArrayList<List<Integer>>(0);
        if(root.left!=null){
            List<List<Integer>> leftList = pathSum(root.left,sum-root.val);
            if(leftList.size()>0) {
                for(int i=0;i<leftList.size();i++) {
                    LinkedList<Integer> list = (LinkedList<Integer>) leftList.get(i);
                    list.addFirst(root.val);
                }
                mainList=leftList;
            }
        }
        if(root.right!=null){
            List<List<Integer>> rightList = pathSum(root.right,sum-root.val);
            if(rightList.size()>0) {
                for(int i=0;i<rightList.size();i++) {
                    LinkedList<Integer> list = (LinkedList<Integer>) rightList.get(i);
                    list.addFirst(root.val);
                }
                mainList.addAll(rightList);
            }
        }
        return mainList;
    }
    /**
     * 返回二叉樹的所有路徑
     * 給定一個(gè)二叉樹柜砾,返回所有從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑。
     * @param root
     * @return
     */
    public List<String> binaryTreePaths(TreeNode root) {
        if(root==null) {
            return new ArrayList<String>(0);
        }
        // 葉子節(jié)點(diǎn)
        if(root.left==null&&root.right==null) {
            List<String> list = new ArrayList<String>(1);
            list.add(root.val+"");
            return list;
        }
        // 路徑
        List<String> paths = new ArrayList<String>();
        if(root.left!=null) {
            List<String> partPaths = binaryTreePaths(root.left);
            for(int i = 0;i<partPaths.size();i++) {
                paths.add(root.val+"->"+partPaths.get(i));
            }
        }
        if(root.right!=null) {
            List<String> partPaths = binaryTreePaths(root.right);
            for(int i = 0;i<partPaths.size();i++) {
                paths.add(root.val+"->"+partPaths.get(i));
            }
        }
        return paths;
    }
    /**
     * 被圍繞的區(qū)域
     * 給定一個(gè)二維的矩陣换衬,包含 'X' 和 'O'(字母 O)痰驱。找到所有被 'X' 圍繞的區(qū)域,并將這些區(qū)域里所有的 'O' 用 'X' 填充瞳浦。
     * @param board
     */
    public void solve(char[][] board) {
        int len = board.length;
        if(len<=0) {
            return;
        }
        for(int x=0;x<board.length;x++) {
            for(int y=0;y<board[x].length;y++) {
                if(board[x][y]=='O') {
                    //如果左上相連的區(qū)域包含'O'
                    boolean flag = edgeDonotHaveOBTWClear(board,x,y,x,y);
                    for(int i=0;i<board.length;i++) {
                        for(int j=0;j<board[i].length;j++) {
                            if(board[i][j]=='-') {
                                board[i][j]=flag?'X':'O';
                            }
                        }
                    }
                }
                
            }
        }
    }
    /**
     * 是否邊界全部為'X' // 如果全部為'X' 則做下清理
     * false 表示邊界為'O'
     * true 表示邊界為'X'
     * @param board
     * @param x
     * @param y
     * @return
     */
    private boolean edgeDonotHaveOBTWClear(char[][] board,int x,int y,int boundX,int boundY) {
        if(x==0||y==0||x==board.length-1||y==board[0].length-1) {
            if(board[x][y]=='X') {
                return true;
            }else {
                return false;
            }
        }
        // 碰壁返回
        if(board[x][y]=='X') {
            return true;
        }
        if(x<boundX&&y<boundY) {
            if(board[x][y]=='X') {
                return true;
            }else {
                return false;
            }
        }
        // 避免重復(fù)入棧操作
        if(board[x][y]=='-') {
            return true;
        }
        // 表示這個(gè)節(jié)點(diǎn)第一次入棧操作
        board[x][y]='-';
        /**
         * 不管有多少棧担映,一共加起來最多只有(n-x乘y) 個(gè)幀才對
         */
        boolean reachEdgeDonotHaveO =  
                edgeDonotHaveOBTWClear(board,x+1,y,boundX,boundY)
                &&edgeDonotHaveOBTWClear(board,x-1,y,boundX,boundY)
                &&edgeDonotHaveOBTWClear(board,x,y-1,boundX,boundY)
                &&edgeDonotHaveOBTWClear(board,x,y+1,boundX,boundY);
        if(reachEdgeDonotHaveO) {
            board[x][y]='X';
        }
        return reachEdgeDonotHaveO;
    }
    /**
     * 求島嶼的個(gè)數(shù)
     * 給定一個(gè)由 '1'(陸地)和 '0'(水)組成的的二維網(wǎng)格,計(jì)算島嶼的數(shù)量叫潦。
     * 一個(gè)島被水包圍另萤,并且它是通過水平方向或垂直方向上相鄰的陸地連接而成的。你可以假設(shè)網(wǎng)格的四個(gè)邊均被水包圍诅挑。
     * @param grid
     * @return
     */
    public int numIslands(char[][] grid) {
        int length = grid.length;
        if(length==0) {
            return 0;
        }
        int counter  = 0;
        /**
         * 坐標(biāo)(x,y)
         */
        for(int x=0;x<length;x++) {
            for(int y=0;y<grid[0].length;y++) {
                if(grid[x][y]=='1') {
                    counter++;
                    clearNearByIslands(grid,x,y);
                };
            }
        }
        return counter;
    }
    /**
     * 清除附近的島嶼四敞,防止重復(fù)計(jì)算
     * @param grid
     * @param x
     * @param y
     */
    private void clearNearByIslands(char[][] grid,int x,int y) {
        if(x<0||y<0||x>=grid.length||y>=grid[0].length) {
            return;
        }
        // 這里一個(gè)節(jié)點(diǎn)不會(huì)重復(fù)生成一個(gè)棧,
        // 如果之前滿足條件能入棧的話拔妥,在入棧之后這個(gè)滿足條件就會(huì)改變忿危,之后就不會(huì)再重復(fù)入棧
        if(grid[x][y]=='1') {
            grid[x][y]='0';
            clearNearByIslands(grid,x-1,y);
            clearNearByIslands(grid,x+1,y);
            clearNearByIslands(grid,x,y-1);
            clearNearByIslands(grid,x,y+1);
        }
    }
    /**
     * 低效做法:
     * 有序鏈表轉(zhuǎn)換二叉搜索樹
     * 1)把鏈表轉(zhuǎn)換成數(shù)組
     * 2)遞歸插入數(shù)組的中間元素
     * @param head
     * @return
     */
    public TreeNode sortedListToBST(ListNode head) {
        if(head==null) {
            return null;
        }
        // 將鏈表轉(zhuǎn)換為數(shù)組
        List<Integer> list = new ArrayList<Integer>();
        while(head!=null) {
            list.add(head.val);
            head=head.next;
        }
        // 遞歸在BST中插入數(shù)組元素
        return halfInsertNode(list,0,list.size()-1);
    }
    /**
     * 遞歸插入數(shù)組的中間元素
     * @param root
     * @param list
     * @param lgt
     * @param rgt
     */
    private TreeNode halfInsertNode(List<Integer> list,int lgt,int rgt) {
        if(lgt>rgt) {
            return null;
        }
        int mid = (lgt+rgt)/2;
        TreeNode node = new TreeNode(list.get(mid));
        node.left = halfInsertNode(list,lgt,mid-1);
        node.right = halfInsertNode(list,mid+1,rgt);
        return node;
    }
    public TreeNode sortedArrayToBST(int[] nums) {
        if(nums==null) {
            return null;
        }
        return halfInsertNode(nums,0,nums.length-1);
    }
    private TreeNode halfInsertNode(int[] list,int lgt,int rgt) {
        if(lgt>rgt) {
            return null;
        }
        int mid = (lgt+rgt)/2;
        TreeNode node = new TreeNode(list[mid]);
        node.left = halfInsertNode(list,lgt,mid-1);
        node.right = halfInsertNode(list,mid+1,rgt);
        return node;
    }
    /**
     * 其實(shí)鏈表ListNode可以直接轉(zhuǎn)為BST
     * @param head
     * @param end
     * @return
     */
    public TreeNode sortedList(ListNode head, ListNode end){
        if (head == end){
            return null;
        }
        ListNode slow = head;
        ListNode fast = head;
        while (fast != end && fast.next != end){
            // fast以兩倍的速度跑到末尾
            // 此時(shí)slow所在的節(jié)點(diǎn)剛好位于中間
            fast = fast.next.next;
            slow = slow.next;
        }
        TreeNode root = new TreeNode(slow.val);
        root.left = sortedList(head,slow);
        root.right = sortedList(slow.next,end);
        return root;
   }
    /**
     * 二叉樹展開為鏈表
     * @param root
     */
    public void flatten(TreeNode root) {
        
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市没龙,隨后出現(xiàn)的幾起案子铺厨,更是在濱河造成了極大的恐慌,老刑警劉巖硬纤,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件解滓,死亡現(xiàn)場離奇詭異,居然都是意外死亡筝家,警方通過查閱死者的電腦和手機(jī)洼裤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來溪王,“玉大人腮鞍,你說我怎么就攤上這事∮猓” “怎么了移国?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長道伟。 經(jīng)常有香客問我迹缀,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任祝懂,我火速辦了婚禮票摇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嫂易。我一直安慰自己兄朋,他們只是感情好掐禁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布怜械。 她就那樣靜靜地躺著,像睡著了一般傅事。 火紅的嫁衣襯著肌膚如雪缕允。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天蹭越,我揣著相機(jī)與錄音障本,去河邊找鬼。 笑死响鹃,一個(gè)胖子當(dāng)著我的面吹牛驾霜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播买置,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼粪糙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了忿项?” 一聲冷哼從身側(cè)響起蓉冈,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎轩触,沒想到半個(gè)月后寞酿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡脱柱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年伐弹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榨为。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掸茅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出柠逞,到底是詐尸還是另有隱情昧狮,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布板壮,位于F島的核電站逗鸣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撒璧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一透葛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卿樱,春花似錦僚害、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹄胰,卻和暖如春岳遥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背裕寨。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工浩蓉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宾袜。 一個(gè)月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓捻艳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親庆猫。 傳聞我的和親對象是個(gè)殘疾皇子认轨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355