力扣310.最小高度树(拓扑排序,无向图),力扣.加油站力扣.矩阵置零力扣.二叉树中的最大路径和

目录

力扣310.最小高度树(拓扑排序,无向图)

力扣.加油站

力扣.矩阵置零​​​

力扣.二叉树中的最大路径和


力扣310.最小高度树(拓扑排序,无向图)

当他是最小高度树时候,树根必定是中心节点,且中心节点一定一两个,且中心节点在最长路径之间,不是找树,而是找中心节点,左右子树都为空的,不要去考虑

相当于是先整一圈,把周围的叶子节点都处理了,然后再处理其他叶子节点,在处理,直到剩下最后一两个

那么这个无向图,换句话就需要把东西插入,每个都算一个入度,换句话说,在边上的节点,会先被排除

复制代码
class Solution {
  public List<Integer> findMinHeightTrees(int n, int[][] map) {
    ArrayList <Integer>res=new ArrayList<>();
    if(n==1) {
       res.add(0);
       return res;
    }
        Map<Integer,ArrayList<Integer>> edges=new HashMap<>();
        //统计每个顶点的入度
        int []in=new int[n];
        //建图
        for(int i=0;i<map.length;i++){
            //找到的是b->a的边
            int a=map[i][0];
            int b=map[i][1];
            //节点和邻居们
            if(!edges.containsKey(b)){
                edges.put(b,new ArrayList<>());
            }
            if(!edges.containsKey(a)){
                edges.put(a,new ArrayList<>());
            }
            edges.get(b).add(a);
            edges.get(a).add(b);
            //b指向a,所以a的入度++。
            in[a]++;
            in[b]++;
        }
//拓扑排序
        LinkedList<Integer>q=new LinkedList<>();   //此时此刻,叶子节点们都数量
        //有向图:(1)先把入度为0的点,加入到队列中
        //无向图:(2)连接到就只有一条线,所以加入队列
        for(int i=0;i<n;i++){
            //说明你的入度为1,那么没人指向你,就自己一个
            if(in[i]==1) q.add(i);

        }
        //2.bfs
        while(!q.isEmpty()){
//其实这个res的清空,就是一个处理,其实实际就是最后一块有用。前面那些个其实没啥大用,其实可以考虑,只剩下最后一轮的时候,
            res.clear();
            int sz=q.size();
            while(sz!=0){
                int leaf=q.poll();
                res.add(leaf);
                ArrayList<Integer>neighbors=edges.get(leaf);//某个叶子节点都邻居们
                for(int neighbor:neighbors){
                    in[neighbor]--;
                    //他的边为1,就说明他是作为叶子节点,所以我们需要把叶子节点出去,然后新的叶子节点进行添加。
                    if(in[neighbor]==1){
                        q.add(neighbor);
                    };
                }
                sz--;
            }
        }
        return res;
}
}

力扣.加油站

这个题看起来简单,但是测试数据有一个很恶心,牛魔来20个0,真想开小米su7床死出数据的

优化的想法是这么

我们观察一下,他的gas和cos,首先考虑是不是gas最后一定要是大于等于cost的,那么我们再考虑,我们不管从哪里出发,是不是都是要走一圈,那么再思索,假如看第一个示例,前面几个 -2 -2 -2,3,3这个就是gas-cos,那么我们看路途中会不会出现是不是就是相当于分开两半,从最小位置的下一个位置(这个示例,最低的亏损是-6,那么从-6的后一个出发,就相当于可以最晚走到亏损最少的点,假如此时还不行,那么就肯定不行了)

复制代码
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cos) {
        int n=gas.length;
        int ret=0;
        int minret=0;
        int minIndex=0;
        for(int i=0;i<n;i++){
            //此时获得到的汽油要求比消耗到i+1的汽油多
            //ret表示当前油多少汽油
            ret+=gas[i]-cos[i];
            //在能够到达下一个的时候,才算是你成功
            if(ret<minret){
                minret=ret; 
                minIndex=i+1;
            }  
  }
          return ret>=0?minIndex:-1;
    
 }
}

力扣.矩阵置零

复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
        boolean row0_flag = false;
        boolean col0_flag = false;
    //为什么要特殊处理第一行和第一列,因为他们在中间和在第一行,第一列是不同的
        // 第一行是否有零
        for (int j = 0; j < col; j++) {
            if (matrix[0][j] == 0) {
                row0_flag = true;
                break;
            }
        }
        // 第一列是否有零
        for (int i = 0; i < row; i++) {
            if (matrix[i][0] == 0) {
                col0_flag = true;
                break;
            }
        }
   //原因:我们的原理是标记每个点的左边开头的点,和上面开头的点,我们扫描时候是扫描,就是不在左边和上面的点,所以从1,1,开始改变
   //那么假如我们最左边一列和最上面一列也有0咋整,这个老铁自己进行一个处理,先统计这些个在边上的,然后最后 再去改变这些在边上的

        //相当于标记每个0这个点的,行的起始点和列的起始点
        // 把第一行第一列作为标志位
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (matrix[i][j] == 0) {
                    matrix[i][0] = matrix[0][j] = 0;
                }
            }
        }
        // 找到先前开头的0的节点,把标记的0的行和列都给他置为0就好
        for (int i = 1; i < row; i++) {
            for (int j = 1; j < col; j++) {
                if (matrix[i][0] == 0 || matrix[0][j] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }
        if (row0_flag) {
            for (int j = 0; j < col; j++) {
                matrix[0][j] = 0;
            }
        }
        if (col0_flag) {
            for (int i = 0; i < row; i++) {
                matrix[i][0] = 0;
            }
        } 
    }
}

力扣.二叉树中的最大路径和

思路:这个蛮不好想的,拿下面图做示例,可以看到,假如我们在-10,我们可以选择要么是9,要么是20+15或者20+7,相当于他是一条直线(只允许一个根这样)​​​​​​​,那么我们统计就相当于统计左右节点最大能给的值,就是本身的节点+左右节点中最大的节点12

复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int maxSum=-100;
    
    public int maxPathSum(TreeNode root) {
       dfs(root);
       return  maxSum;
    }
      public int dfs(TreeNode root) {
        if(root==null)return 0;
        int count=0;
        count+=root.val;
        int left =Math.max(dfs(root.left),0);
        int right=Math.max(dfs(root.right),0);
        count+=left+right;
        maxSum=Math.max(maxSum,count);
        return root.val+Math.max(left,right);
    }

}
相关推荐
L_cl1 分钟前
【Python 算法零基础 4.排序 ① 选择排序】
数据结构·算法·排序算法
山北雨夜漫步1 小时前
机器学习 Day18 Support Vector Machine ——最优美的机器学习算法
人工智能·算法·机器学习
拼好饭和她皆失1 小时前
算法加训之最短路 上(dijkstra算法)
算法
瓦力wow3 小时前
c语言 写一个五子棋
c语言·c++·算法
X-future4263 小时前
院校机试刷题第六天:1134矩阵翻转、1052学生成绩管理、1409对称矩阵
线性代数·算法·矩阵
Codeking__4 小时前
前缀和——中心数组下标
数据结构·算法
爱喝热水的呀哈喽4 小时前
非线性1无修
算法
花火QWQ4 小时前
图论模板(部分)
c语言·数据结构·c++·算法·图论
Pacify_The_North5 小时前
【进程控制二】进程替换和bash解释器
linux·c语言·开发语言·算法·ubuntu·centos·bash