leetcode 684.354,133,207,121,63,64,jz46,120,357

684 冗余连接

 

   不得不说并查集真的是一种很巧妙的思维了。。。

int[] visit;

    public int[] findRedundantConnection(int[][] edges) {
        visit = new int[edges.length+1];
        for (int i = 0; i < visit.length; i++) {
            visit[i] = i;
        }
        for (int i = 0; i < edges.length; i++) {
            if (!connectd(edges[i][0],edges[i][1])){
                union(edges[i][0],edges[i][1]);
            }else {
                return edges[i];
            }
        }

        return null;
    }
    public void union(int p,int q){
        int s = visit[p],t = visit[q];
        if (s != t){
            for (int i = 0; i < visit.length; i++) {
                if (visit[i] == s){
                    visit[i] = t;
                }
            }
        }
    }
    public boolean connectd(int p,int q){
        return visit[p] == visit[q];
    }

   然后由于union的复杂度是On,这儿还可以进行优化,quik union。具体的就是相当的亲戚只保留一个根节点 即p = visit[p],其他的都指向自己的父节点即可

  public void union(int p,int q){
        int proot = find(p);
        int qroot = find(q);
        if (proot == qroot){
            return;
        }
        visit[proot] = qroot;
    }

    public int find(int p){
        while (p != visit[p]){
            p = visit[p];
        }
        return p;
    }
    public boolean connectd(int p,int q){
        return find(p) == find(q);
    }

  然后这儿如果整个列表都是亲戚,而且顺序极端的情况下会形成一个链表。所以还能继续优化  具体的优化可以查看这边博客 传送门→https://www.cnblogs.com/ggnbnb/p/12586205.html

 

 

 

354 俄罗斯套娃的问题   记住相等是不行的

 

   其实就是个最长递增子序列的问题,这题还有个贪心+二分的解法。。有兴趣的可以去了解下

    public int maxEnvelopes(int[][] envelopes) {
 Arrays.sort(envelopes, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1]-o2[1];
            }
        });
       int[] dp = new int[envelopes.length];
       dp[0] = 1;
        int max = 1;
        for (int i = 1; i < envelopes.length; i++) {
            dp[i] = 1;
            int[] cu = envelopes[i];
            for (int j = 0; j < i; j++) {
                if (cu[0]>envelopes[j][0] && cu[1]>envelopes[j][1]){
                    dp[i] = Math.max(dp[i],dp[j]+1);
                }

            }
            max = Math.max(max,dp[i]);

        }
        return max;
    }

   

133 克隆图

 

   这题我做的和官解一样。。但不知道为何打败人数很少。。

Map<Integer,Node> nodeMap;

    public Node cloneGraph(Node node) {
        if (node == null){
            return null;
        }
        nodeMap = new HashMap<>();
        return dfs(node);
    }

    public Node dfs(Node node){
        Node cu = new Node(node.val);
        nodeMap.put(node.val,cu);
        List<Node> cns = cu.neighbors;
        List<Node> ns =  node.neighbors;
        for (Node n : ns) {
            if (nodeMap.containsKey(n.val)){
                cns.add(nodeMap.get(n.val));
            }else {
                cns.add(dfs(n));
            }

        }
        return cu;

    }


     static class Node {
        public int val;
        public List<Node> neighbors;
        public Node() {
            val = 0;
            neighbors = new ArrayList<Node>();
        }
        public Node(int _val) {
            val = _val;
            neighbors = new ArrayList<Node>();
        }
        public Node(int _val, ArrayList<Node> _neighbors) {
            val = _val;
            neighbors = _neighbors;
        }
    }

 

207 这是之前做过的一个题,当时用的dfs,现在才知道还可以用拓扑排序

 

 

public static boolean canFinish(int numCourses, int[][] prerequisites) {
        Map<Integer, List<Integer>> map = new HashMap<>();
        int[] arr = new int[numCourses];
        for (int[] ar : prerequisites) {
            int x1 =ar[0],x2 = ar[1];
            arr[x2]+=1;
            List<Integer> forws = map.get(x1);
            if (forws == null){
                forws = new ArrayList<>();
                map.put(x1,forws);
            }
            forws.add(ar[1]);


        }
        //计算入度
        while (!map.isEmpty()){
            int size = map.size();
            Set<Integer> set = map.keySet();
            Iterator<Integer> iterator = set.iterator();
            boolean circle = true;
            while (iterator.hasNext()){
                Integer value = iterator.next();
                if (arr[value] == 0){
                    circle = false;
                    List<Integer> childs = map.get(value);
                    for (Integer child : childs) {
                        if (arr[child]>0){
                            arr[child]--;
                        }
                    }
                    iterator.remove();
                }
            }
            if (circle){
                return false;
            }

        }
        return true;


    }

 

53 最大子序和

 

 

 

    public static int maxSubArray(int[] nums) {
        if (nums.length <1){
            return 0;
        }

        int pre = nums[0];
        int max = pre;
        for (int i = 1; i < nums.length; i++) {
            pre = Math.max(nums[i],pre+nums[i]);
            max = Math.max(pre,max);
        }
        return max;
    }

 

70  爬楼梯   一次一步 或者两步  N步一共有多少种方法

 

 

 

    public static int climbStairs(int n) {
        if (n <= 3){
            return n;
        }
        int[] dp = new int[n+1];
        dp[1] = 1;dp[2] = 2;dp[3] = 3;
        for (int i = 4; i <=n ; i++) {
            dp[i] = dp[i-2]+dp[i-1];
        }
        return dp[n];

    }

 

121 买卖股票的最佳时机

 

 

    public static int maxProfit(int[] prices) {
        int k = prices[0];
        int max = 0;
        for (int i = 1; i < prices.length; i++) {
            int c = prices[i];
            if (c > k){
                max = Math.max(max, c- k);
            }else {
                k = c;
            }

        }
        return max;
    }

 

63 不同路径

 

 

public static int uniquePathsWithObstacles(int[][] obstacleGrid) {
        if (obstacleGrid[0][0] == 1){
            return 0;
        }
        int m = obstacleGrid.length,n = obstacleGrid[0].length;
        int[][] dp = new int[m][n];
        boolean t1 = true,t2 = true;
        for (int i = 0; i < m; i++) {
            if (obstacleGrid[i][0] == 1){
                t1 = false;
            }
            if (t1){
                dp[i][0] = 1  ;
            }
            if (i == 0){
                for (int j = 1; j < n; j++) {
                    if (obstacleGrid[0][j] == 1){
                        t2 = false;
                    }
                    if (t2){
                        dp[0][j] = 1;
                    }

                }
            }

        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j] != 1){
                    dp[i][j] = dp[i-1][j]+dp[i][j-1];
                }
            }
        }
        return dp[m-1][n-1];
        
    }

 

64 最小路径和

 

 

    public static int minPathSum(int[][] grid) {
        int m = grid.length,n = grid[0].length;
        int[][] dp = new int[m][n];
        boolean t1 = true,t2 = true;
        dp[0][0] = grid[0][0];
        for (int i = 1; i < m; i++) {
            dp[i][0] = dp[i-1][0]+grid[i][0];
        }
        for (int i = 1; i < n; i++) {
            dp[0][i] = dp[0][i-1]+grid[0][i];
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j];
            }
        }
        return dp[m-1][n-1];
        
    }

 

数字翻译成字符串

 

   思路是如果当前字符和前一个字符可以组成一个有效数字,那么出现的情况就等于前一个加上前前一个字符的情况。否则就等于前一个字符的情况

    public static int translateNum(int num) {
        String value = String.valueOf(num);
        int[] dp = new int[value.length()];

        dp[0] = 1;
        if (value.length()<=1){
            return dp[0];
        }
        int pre = value.charAt(0)-48;
        dp[1] = pre*10+value.charAt(1)-48 >25?1:2;
        if (value.length()<=2){
            return dp[1];
        }
        pre = dp[1];
        for (int i = 2; i < value.length(); i++) {
            if (pre == 0 || pre*10+value.charAt(i)-48 > 25){
                dp[i] = dp[i-1];
            }else {
                dp[i] = dp[i-1]+dp[i-2];
            }
            pre = value.charAt(i)-48;
        }
        return dp[value.length()-1];
    }

 

120 三角形的最小路径和

 

 

public static int minimumTotal1(List<List<Integer>> triangle) {
        if (triangle.size() == 1){
            return triangle.get(0).get(0);
        }
        int[][] dp = new int[triangle.size()][triangle.size()];
        dp[0][0] = triangle.get(0).get(0);
        int min = Integer.MAX_VALUE;
        for (int i = 1; i < triangle.size(); i++) {
            List<Integer> integers = triangle.get(i);
            for (int j = 0; j < integers.size(); j++) {
                if (j == 0){
                    dp[i][j] = dp[i-1][j] +integers.get(j);
                }else if (j == integers.size()-1){
                    dp[i][j] = dp[i-1][j-1] +integers.get(j);
                }
                else {
                    dp[i][j] = Math.min(dp[i-1][j],dp[i-1][j-1])+integers.get(j);
                }
                if (i == triangle.size()-1){
                    min = Math.min(min,dp[i][j]);
                }
            }
        }
        return min;
    }

 

357 计算各个位数不同的数的数字个数

 

 

   解析直接看如下,摘自题解,就是一个组合的知识吧

 

 

 

    public static int countNumbersWithUniqueDigits(int n) {
        int[] dp = new int[n+1];
        dp[0] = 0;
        if (n == 0 ){
            return dp[0];
        }
        dp[1] = 10;
        if (n == 1){
            return dp[1];
        }
        dp[2] = 91;
        if (n == 2){
            return dp[2];
        }
        int s = 81;
        for (int i = 3; i <= n; i++) {
            s *= 11-i;
            dp[i] = dp[i-1]+s;
        }
        return dp[n];
    }

 

posted @ 2021-03-11 10:29  雨落寒沙  阅读(81)  评论(0编辑  收藏  举报