• leetcode刷题 538~


    题目538题

    把二叉搜素树转换为累加树

    给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

    提醒一下,二叉搜索树满足下列约束条件:

    节点的左子树仅包含键 小于 节点键的节点。
    节点的右子树仅包含键 大于 节点键的节点。
    左右子树也必须是二叉搜索树。

    思路

    深度优先遍历

    实现

    class Solution {
        public TreeNode convertBST(TreeNode root) {
            int a = dfs(root,0);
            return root;
        }
    
        private int dfs(TreeNode node, int bigger){
            int right = 0;
            if(node == null){
                return 0;
            }
            
            right = dfs(node.right, bigger);
            if(node.right == null)
                node.val += bigger;
            node.val += right;
            int left = dfs(node.left, node.val);
            if(left != 0){
                return left;
            }
            return node.val;
        }
    }

    题目539题

    最小时间差

    给定一个 24 小时制(小时:分钟 "HH:MM")的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示。

    思路实现

    class Solution {
        public int findMinDifference(List<String> timePoints) {
            if (timePoints.size()>=1440){
                return 0;
            }
            int[] timeList = new int[timePoints.size()];
            for(int index=0; index < timePoints.size(); index++){
                String[] time = timePoints.get(index).split(":");
                int hour = Integer.parseInt(time[0]);
                int minute = Integer.parseInt(time[1]);
                timeList[index] = hour*60 + minute;
            }
            Arrays.sort(timeList);
            int res = 1440;
            for(int index=1; index < timePoints.size(); index++){
                res = Math.min(res, timeList[index]- timeList[index-1]);
                if(res == 0){
                    return 0;
                }
            }
            res = Math.min(res, 1440 - timeList[timeList.length - 1] + timeList[0]);
            return res;
        }
    }

    题目540题

    有序数组中的单一元素

    给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。

    示例 1:

    输入: [1,1,2,3,3,4,4,8,8]
    输出: 2

    思路

    二分法

    实现

    class Solution {
        public int singleNonDuplicate(int[] nums) {
            int left =0, right = nums.length -1;
            int mid=0;
            while(left < right){
                if(nums[left] != nums[left+1]){
                    mid = left;
                    break;
                }else if(nums[right] != nums[right-1]){
                    mid = right;
                    break;
                }else{
                    mid = left + (right-left)/2;
                }
                int halflen = (right - left)/2;
                if(halflen %2==0 && nums[mid]==nums[mid-1]){
                    right = mid - 2;
                }else if(halflen %2==0 && nums[mid]==nums[mid+1]){
                    left = mid + 2;
                }else if(halflen %2==1 && nums[mid]==nums[mid-1]){
                    left = mid + 1;
                }else if(halflen %2==1 && nums[mid]==nums[mid+1]){
                    right = mid - 1;
                }else{
                    break;
                }
            }
            return nums[mid];
        }
    }

    题目541题

    反转字符串II

    给定一个字符串 s 和一个整数 k,你需要对从字符串开头算起的每隔 2k 个字符的前 k 个字符进行反转。

    如果剩余字符少于 k 个,则将剩余字符全部反转。
    如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

    示例:

    输入: s = "abcdefg", k = 2
    输出: "bacdfeg"

    思路实现

    class Solution {
        public String reverseStr(String s, int k) {
            char[] c = s.toCharArray();
            for(int index = 0; index < c.length; index += 2*k){
                int i = index, j = Math.min(index + k - 1, c.length - 1);
                while (i < j) {
                    char tmp = c[i];
                    c[i++] = c[j];
                    c[j--] = tmp;
                }
            }
            return String.valueOf(c);
        }
    }

    题目542题

    01矩阵

    给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。

    两个相邻元素间的距离为 1 。

    示例 1:

    输入:
    [[0,0,0],
    [0,1,0],
    [0,0,0]]

    输出:
    [[0,0,0],
     [0,1,0],
     [0,0,0]]

    思路

    1. 深度优先遍历

    实现

    class Solution {
        private int[][] matrix;
        private int row, col;
        int [][]dirs={{-1,0},{1,0},{0,-1},{0,1}};
        public int[][] updateMatrix(int[][] matrix) {
            this.matrix = matrix;
            row = matrix.length;
            col = matrix[0].length;
            for(int i=0; i < row; i++){
                for(int j=0; j < col; j++ ){
                    if(this.matrix[i][j] ==1 && !hasNeighbors0(i,j)){
                        this.matrix[i][j] = Integer.MAX_VALUE;
                    }
                }
            }
            for(int i=0; i < row; i++){
                for(int j=0; j < col; j++ ){
                    if(this.matrix[i][j] == 1){
                        dfs(i, j);
                    }
                }
            }
    
            return this.matrix;
        }
    
        boolean hasNeighbors0(int x,int y){ 
            for(int[] dir:dirs){
                int new_x=x+dir[0];
                int new_y=y+dir[1];
                if(new_x>=0 && new_x<row && new_y>=0 && new_y<col && matrix[new_x][new_y]==0)
                    return true;
            }
             return false;
        }
    
        private void dfs(int x ,int y){
            for(int[] dir:dirs){
                int new_x=x+dir[0];
                int new_y=y+dir[1];
                if(new_x>=0 && new_x<row && new_y>=0 && new_y<col && matrix[new_x][new_y]>matrix[x][y]+1 ){
                matrix[new_x][new_y] = matrix[x][y]+1;
                dfs(new_x, new_y);
                }
            }
        }
    
    }

    题目543题

    二叉树的直径

    给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

    示例 :
    给定二叉树

    1
    /
    2 3
    /
    4 5
    返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

    思路实现

    class Solution {
        int res = 1;
        public int diameterOfBinaryTree(TreeNode root) {
            calcLen(root);
            return res-1;
        }
    
        private int calcLen(TreeNode node){
            if (node == null){
                return 0;
            }
            int resleft = calcLen(node.left);
            int resright = calcLen(node.right);
            res = Math.max(resleft + resright+ 1, res);
            return Math.max(resleft, resright)+1;
        }
    }

    题目547题

    朋友圈

    班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。

    给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。

    思路

    1.广度优先遍历

    2.Union-Find算法

    实现

    1.
    class Solution {
        public int findCircleNum(int[][] M) {
            int N = M.length;
            int res = 0;
            boolean[] visited = new boolean[N];
            Queue<Integer> queue = new LinkedList<Integer>();
            for(int i=0; i < N; i++){
                if(visited[i] == false){
                    res +=1;
                    queue.offer(i);
                    while(queue.size()!= 0){
                        int j = queue.poll();
                        visited[j] = true;
                        for(int k=0; k <N; k++){
                            if(M[j][k] == 1 && visited[k] == false){
                                queue.offer(k);
                            }
                        }
                    }
                }
            }
            return res;
        }
    }
    2.
    class Solution {
        class UF {
        // 记录连通分量个数
        private int count;
        // 存储若干棵树
        private int[] parent;
        // 记录树的“重量”
        private int[] size;

        public UF(int n) {
            this.count = n;
            parent = new int[n];
            size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
                size[i] = 1;
            }
        }
        
        /* 将 p 和 q 连通 */
        public void union(int p, int q) {
            int rootP = find(p);
            int rootQ = find(q);
            if (rootP == rootQ)
                return;
            
            // 小树接到大树下面,较平衡
            if (size[rootP] > size[rootQ]) {
                parent[rootQ] = rootP;
                size[rootP] += size[rootQ];
            } else {
                parent[rootP] = rootQ;
                size[rootQ] += size[rootP];
            }
            count--;
        }

        /* 判断 p 和 q 是否互相连通 */
        public boolean connected(int p, int q) {
            int rootP = find(p);
            int rootQ = find(q);
            // 处于同一棵树上的节点,相互连通
            return rootP == rootQ;
        }

        /* 返回节点 x 的根节点 */
        private int find(int x) {
            while (parent[x] != x) {
                // 进行路径压缩
                parent[x] = parent[parent[x]];
                x = parent[x];
            }
            return x;
        }
        
        public int count() {
            return count;
        }
    }

            public int findCircleNum(int[][] M) {
            int n = M.length;
            UF uf = new UF(n);
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < i; j++) {
                    if (M[i][j] == 1)
                        uf.union(i, j);
                }
            }
            return uf.count();
        }

    }
     

    题目551题

    学生出勤记录I

    给定一个字符串来代表一个学生的出勤记录,这个记录仅包含以下三个字符:

    'A' : Absent,缺勤
    'L' : Late,迟到
    'P' : Present,到场
    如果一个学生的出勤记录中不超过一个'A'(缺勤)并且不超过两个连续的'L'(迟到),那么这个学生会被奖赏。

    你需要根据这个学生的出勤记录判断他是否会被奖赏。

    思路实现

    class Solution {
        public boolean checkRecord(String s) {
            char[] c = s.toCharArray();
            int a = 0;
            int l = 0;
            for(char i: c){
                if(i == 'A'){
                    a += 1;
                    l = 0;
                }else if(i == 'L'){
                    l += 1;
                }else{
                    l = 0;
                }
                if(a > 1 || l >2){
                    return false;
                }
            }
            return true;
        }
    }

    题目553题

    最优除法

    给定一组正整数,相邻的整数之间将会进行浮点除法操作。例如, [2,3,4] -> 2 / 3 / 4 。

    但是,你可以在任意位置添加任意数目的括号,来改变算数的优先级。你需要找出怎么添加括号,才能得到最大的结果,并且返回相应的字符串格式的表达式。你的表达式不应该含有冗余的括号。

    示例:

    输入: [1000,100,10,2]
    输出: "1000/(100/10/2)"
    解释:
    1000/(100/10/2) = 1000/((100/10)/2) = 200
    但是,以下加粗的括号 "1000/((100/10)/2)" 是冗余的,
    因为他们并不影响操作的优先级,所以你需要返回 "1000/(100/10/2)"。

    思路

    数学降维打击:为了最大化 a/b/c/da/b/c/d 我们首先需要最小化 b/c/d,现在我们的目标变成了最小化表达式 b/c/d。而b/c/d就是最小值。因此对于形如 a/b/c/d/e/f... 的表达式,答案将是 a/(b/c/d/e/f...)

    实现

    class Solution {
        public String optimalDivision(int[] nums) {
            if (nums.length == 1)
                return nums[0] + "";
            if (nums.length == 2)
                return nums[0] + "/" + nums[1];
            StringBuilder res = new StringBuilder(nums[0] + "/(" + nums[1]);
            for (int i = 2; i < nums.length; i++) {
                res.append("/" + nums[i]);
            }
            res.append(")");
            return res.toString();
        }
    }

    题目554题

    砖墙

    你的面前有一堵矩形的、由多行砖块组成的砖墙。 这些砖块高度相同但是宽度不同。你现在要画一条自顶向下的、穿过最少砖块的垂线。

    砖墙由行的列表表示。 每一行都是一个代表从左至右每块砖的宽度的整数列表。

    如果你画的线只是从砖块的边缘经过,就不算穿过这块砖。你需要找出怎样画才能使这条线穿过的砖块数量最少,并且返回穿过的砖块数量。

    你不能沿着墙的两个垂直边缘之一画线,这样显然是没有穿过一块砖的。

    示例:

    输入: [[1,2,2,1],
    [3,1,2],
    [1,3,2],
    [2,4],
    [3,1,2],
    [1,3,1,1]]

    输出: 2

    思路

    哈希表

    实现

    class Solution {
        public int leastBricks(List<List<Integer>> wall) {
            HashMap<Integer, Integer> map = new  HashMap<Integer, Integer>();
            int sum = 0;
            List<Integer> first = wall.get(0);
            for(int num: first){
                sum += num;
            }
            for(List<Integer> level: wall){
                int cur = 0;
                for(int num: level){
                    cur += num;
                    if(cur < sum)
                        map.put(cur,1 + map.getOrDefault(cur,0));
                }
            }
            int max = 0;
            for(int num: map.values()){
                max = Math.max(max, num);
            }
            return wall.size() - max;
        }
    }

    题目556题

    下一个更大元素III

    给定一个32位正整数 n,你需要找到最小的32位整数,其与 n 中存在的位数完全相同,并且其值大于n。如果不存在这样的32位整数,则返回-1。

    示例 1:

    输入: 12
    输出: 21

    思路实现

    class Solution {
        public int nextGreaterElement(int n) {
            int[] t = new int[10];
            int l = t.length;
            int temp = n;
            while (l > 0 && temp > 0) {
                l--;
                t[l] = temp % 10;
                temp /= 10;
            }
            for(int i = t.length-1; i >l; i--){
                if(t[i-1] < t[i]){
                    temp = i-1;
                    int w = i-1;
                    int[] min = new int[t.length-i];
                    int k = 0;
                    for(int j = t.length-1; j>w; j--){
                        if(t[j] <= t[temp] || temp != i-1){
                            min[k] = t[j];
                            k += 1;
                        }else{
                            min[k] = t[temp];
                            k += 1; 
                            temp = j;
                        }
                    }
                    t[w] = t[temp];
                    for(int q = i, s=0; q<t.length; q++,s++){
                        t[q] = min[s];
                    }
                    break;
                }
            }
            int res = 0;
            for(int i: t){
                res = res*10+i;
            }
            return res <= n ? -1 : res;
        }
    
    
    }

    题目539题

    思路实现

    题目539题

    思路实现

    题目539题

    思路实现

    题目539题

    思路实现

    题目539题

    思路实现

    题目539题

    思路实现

    题目539题

    思路实现

    题目539题

    思路实现

    题目539题

    思路实现

  • 相关阅读:
    eclipse如何把多个项目放在一个文件夹下【eclipse中对项目进行分类管理】-图示详解
    hibernate中cache二级缓存问题
    Java处理正则验证手机号-详解
    Java处理手机号中间4位替换成*
    WPF:依赖属性的应用
    WPF:自定义路由事件的实现
    WPF:类型转换器的实现
    MFC中CString转化为char*
    Android4.4 往短信收件箱中插入自定义短信(伪造短信)
    OpenCV imread读取图片,imshow展示图片,出现cv:Exception at memory location异常
  • 原文地址:https://www.cnblogs.com/mgdzy/p/14178007.html
Copyright © 2020-2023  润新知