zoukankan      html  css  js  c++  java
  • leetcode刷题 557~

    题目557

    反转字符串中的单词III

    给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

    思路实现

    class Solution {
        public String reverseWords(String s) {
            String[] buff = s.split(" ");
            StringBuffer result = new StringBuffer();
            for(String string: buff){
                String reverse = new StringBuffer(string).reverse().toString();
                result.append(reverse+" ");
            }
            return result.toString().substring(0, s.length());
        }
    }

    题目558

    四叉树交集

    二进制矩阵中的所有元素不是 0 就是 1 。

    给你两个四叉树,quadTree1 和 quadTree2。其中 quadTree1 表示一个 n * n 二进制矩阵,而 quadTree2 表示另一个 n * n 二进制矩阵。

    请你返回一个表示 n * n 二进制矩阵的四叉树,它是 quadTree1 和 quadTree2 所表示的两个二进制矩阵进行 按位逻辑或运算 的结果。

    注意,当 isLeaf 为 False 时,你可以把 True 或者 False 赋值给节点,两种值都会被判题机制 接受 。

    四叉树数据结构中,每个内部节点只有四个子节点。此外,每个节点都有两个属性:

    val:储存叶子结点所代表的区域的值。1 对应 True,0 对应 False;
    isLeaf: 当这个节点是一个叶子结点时为 True,如果它有 4 个子节点则为 False 。

    思路

    递归

    实现

    class Solution {
        public Node intersect(Node quadTree1, Node quadTree2) {
            if(quadTree1.isLeaf){
                if(quadTree1.val == true){
                    return quadTree1;
                }
                else{
                    return quadTree2;
                }
            }else if(quadTree2.isLeaf){
                if(quadTree2.val == true){
                    return quadTree2;
                }else{
                    return quadTree1;
                }
            }
            Node topLeft = intersect(quadTree1.topLeft, quadTree2.topLeft);
            Node topRight = intersect(quadTree1.topRight, quadTree2.topRight);
            Node bottomLeft = intersect(quadTree1.bottomLeft, quadTree2.bottomLeft);
            Node bottomRight = intersect(quadTree1.bottomRight, quadTree2.bottomRight);
            if(topLeft.isLeaf && topRight.isLeaf && bottomLeft.isLeaf && bottomRight.isLeaf &&topLeft.val && topRight.val && bottomLeft.val && bottomRight.val){
                return new Node(true, true, null, null, null, null);
            }
            return new Node(false, false,topLeft, topRight, bottomLeft, bottomRight);
        }
    }

    题目559

    N叉树的最大深度

    给定一个 N 叉树,找到其最大深度。

    最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。

    思路实现

    class Solution {
        private int maxLevel = 0;
        public int maxDepth(Node root) {
            if(root == null){
                return maxLevel;
            }
            dfs(root, 0);
            return maxLevel;
        }
    
        private void dfs(Node node, int level){
            int curLevel = level +1;
            if(node.children.isEmpty()){
                maxLevel = Math.max(maxLevel, curLevel);
            }else{
                for(Node next: node.children){
                    dfs(next, curLevel);
                }
            }
        }
    }

    题目560

    和为k的子数组

    给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。

    示例 1 :

    输入:nums = [1,1,1], k = 2
    输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。

    思路

    前缀树:

    维护一个表,这个表的key是从0到index的和,value是key出现的次数。

    实现

    class Solution {
        public int subarraySum(int[] nums, int k) {
            HashMap<Integer, Integer> map = new HashMap<>();
            int sum = 0;
            int res = 0;
            map.put(0,1);
            for (int index = 0; index < nums.length; index++ ){
                sum += nums[index];
                int temp = sum - k;
                if(map.containsKey(temp)){
                    res += map.get(temp);
                }
                map.put(sum, map.getOrDefault(sum, 0)+1);
            }
            return res;
        }
    }

    题目561

    数组拆分I

    给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。

    返回该 最大总和 。

    思路

    排序

    实现

    class Solution {
        public int arrayPairSum(int[] nums) {
            Arrays.sort(nums);
            int res=0;
            for(int index=0; index < nums.length; index+=2){
                res += nums[index];
            }
            return res;
        }
    }

    题目563

    二叉树的坡度

    给定一个二叉树,计算 整个树 的坡度 。

    一个树的 节点的坡度 定义即为,该节点左子树的节点之和和右子树节点之和的 差的绝对值 。如果没有左子树的话,左子树的节点之和为 0 ;没有右子树的话也是一样。空结点的坡度是 0 。

    整个树 的坡度就是其所有节点的坡度之和。

    思路实现

    class Solution {
        private int res = 0;
        public int findTilt(TreeNode root) {
            int num = dfs(root);
            return res;
        }
    
        private int dfs(TreeNode node){
            if(node == null){
                return 0;
            }
            int left = dfs(node.left);
            int right = dfs(node.right);
            res += Math.abs(left-right);
            return node.val+left+right;
        }
    }

    题目565

    数组嵌套

    索引从0开始长度为N的数组A,包含0到N - 1的所有整数。找到最大的集合S并返回其大小,其中 S[i] = {A[i], A[A[i]], A[A[A[i]]], ... }且遵守以下的规则。

    假设选择索引为i的元素A[i]为S的第一个元素,S的下一个元素应该是A[A[i]],之后是A[A[A[i]]]... 以此类推,不断添加直到S出现重复的元素。

    思路

    深度优先遍历

    实现

    class Solution {
        private int[] nums;
        boolean[] visited;
        public int arrayNesting(int[] nums) {
            this.nums = nums;
            visited = new boolean[nums.length];
            int res = 0;
            for(int i=0; i<nums.length; i++){
                if(!visited[i]){
                    res = Math.max(dfs(i), res);
                }
            }
            return res;
        }
    
        public int dfs(int begin){
            visited[begin] = true;
            int nextIndex = nums[begin];
            int num =0;
            if(!visited[nextIndex]){
                num = dfs(nextIndex);
            }
            return 1+num;
        }
    }

    题目566

    重塑矩阵

    在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。

    给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。

    重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。

    如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

    思路实现

    class Solution {
        public int[][] matrixReshape(int[][] nums, int r, int c) {
            int m = nums.length;
            int n = nums[0].length;
            int count = m*n;
            if(r*c != count){
                return nums;
            }
            int[][] res = new int[r][c];
            for(int i=0; i<count; i++){
                res[i/c][i%c] = nums[i/n][i%n];
            }
            return res;
        }
    }

    题目567

    字符串的排列

    给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。

    换句话说,第一个字符串的排列之一是第二个字符串的子串。

    示例1:

    输入: s1 = "ab" s2 = "eidbaooo"
    输出: True
    解释: s2 包含 s1 的排列之一 ("ba").

    思路

    用字典和滑动窗口

    实现

    class Solution {
        public boolean checkInclusion(String s1, String s2) {
            if(s1.length() > s2.length()){
                return false;
            }
            char[] chars1 = s1.toCharArray();
            char[] chars2 = s2.toCharArray();
            int windows = s1.length();
            int[] s1map = new int[26];
            int[] s2map = new int[26];
            for (int i = 0; i < windows; i++) {
                s1map[chars1[i] - 'a']++;
                s2map[chars2[i] - 'a']++;
            }
            int res = 0;
            for(int i=0; i<26; i++){
                if(s1map[i] == s2map[i]){
                    res += 1 ;
                }
            }
            for(int i = windows ; i < s2.length(); i++){
                if(res==26){
                    return true;
                }
                int r = chars2[i] - 'a', l = chars2[i-windows]-'a';
                s2map[r] += 1;
                if (s2map[r] == s1map[r])
                    res += 1;
                else if(s2map[r] == s1map[r]+1)
                    res -= 1;
                s2map[l] -= 1;
                if (s2map[l] == s1map[l])
                    res += 1;
                else if(s2map[l] == s1map[l]-1)
                    res -= 1;
            }
            return res == 26;
        }
    }

    题目572

    另一个树的子树

    给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。

    思路

    深度优先遍历

    准备答案还使用了KMP和哈希表

    实现

    class Solution {
        public boolean isSubtree(TreeNode s, TreeNode t) {
            if(s == null){
                return false;
            }
            return equals(s, t)||isSubtree(s.left, t) || isSubtree(s.right, t);
        }
    
        private boolean equals(TreeNode s, TreeNode t){
            if(s == null && t == null){
                return true;
            }
            if(s != null && t != null && s.val == t.val){
                return equals(s.left, t.left) && equals(s.right, t.right);
            }
            return false;
        }
    
    }

    题目575

    分糖果

    给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。

    思路实现

    class Solution {
        public int distributeCandies(int[] candyType) {
            HashSet < Integer > set = new HashSet < > ();
            for (int candy: candyType) {
                set.add(candy);
            }
            return Math.min(set.size(), candyType.length / 2);
        }
    }

    题目576

    出界的路径数

    给定一个 m × n 的网格和一个球。球的起始坐标为 (i,j) ,你可以将球移到相邻的单元格内,或者往上、下、左、右四个方向上移动使球穿过网格边界。但是,你最多可以移动 N 次。找出可以将球移出边界的路径数量。答案可能非常大,返回 结果 mod 10**9 + 7 的值。

    思路

    1.深度优先遍历,但是会超时

    2.动态规划

    dp[i][j][k]:表示从(i,j)出发第k步出界的路径总数,等价于从外界出发第k步走到(i,j)的路径总数

    状态转移方程

    dp[i][j][k] = dp[i-1][j][k-1]+dp[i+1][j][k-1] + dp[i][j-1][k-1]+dp[i][j+1][k-1]

    结果
    Sum=dp[i][j][k]

    实现

    1.
    class Solution {
        private int m;
        private int n;
        int[][] move = new int[][]{{-1,0},{1,0},{0,-1},{0,1}};
        public int findPaths(int m, int n, int N, int i, int j) {
            this.m = m;
            this.n = n;
            int res = dfs(i,j,N);
            return res;
        }
    
        public int dfs(int i, int j ,int round){
            int res = 0;
            if (i < 0 || i == m || j < 0 || j ==n ){
                return 1;
            }
            if (round > 0){
                for(int in=0; in<4; in++){
                    int x = i + move[in][0];
                    int y = j + move[in][1];
                    res += dfs(x,y, round-1) % (10**9+7);
                }
            }
            return res;
        }
    }
    2.class Solution {
        private int m;
        private int n;
        int[][] move = new int[][]{{-1,0},{1,0},{0,-1},{0,1}};
        public int findPaths(int m, int n, int N, int x, int y) {
           long[][][] dp = new long [m+2][n+2][N+1];
           int mod = 1000000007;
           for(int i =0 ; i < m+2; i++){
               dp[i][0][0] = 1;
               dp[i][n+1][0] = 1;
            }
           for(int j=0; j < n+2; j++){
               dp[0][j][0] = 1;
               dp[m+1][j][0] = 1;
            }
            for(int k = 1; k<=N; k++){
                for(int i = 1; i < m+1; i++){
                    for(int j=1; j< n+1; j++){
                        dp[i][j][k] = (dp[i-1][j][k-1]+dp[i+1][j][k-1]+dp[i][j-1][k-1]+dp[i][j+1][k-1])%(mod);
                    }
                }
            }
            long res =0;
            for(int k=0; k<=N; k++){
                res = (res + dp[x+1][y+1][k]) % mod;
            }
            return (int)res;
        }
    }

    题目581

    最短无序连续子数组

    给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。

    你找到的子数组应是最短的,请输出它的长度。

    示例 1:

    输入: [2, 6, 4, 8, 10, 9, 15]
    输出: 5
    解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。

    思路

    从左到右循环,记录最大值为 max,若 nums[i] < max, 则表明位置 i 需要调整, 循环结束,记录需要调整的最大位置 i 为 high;

    同理,从右到左循环,记录最小值为 min, 若 nums[i] > min, 则表明位置 i 需要调整,循环结束,记录需要调整的最小位置 i 为 low.

    实现

    class Solution {
        public int findUnsortedSubarray(int[] nums) {
            int max = nums[0];
            int high = 0;
            for(int i = 0; i < nums.length; i ++){
                if(nums[i] < max){
                    high = i;
                }
                else{
                    max = nums[i];
                }
            }
            int min = nums[nums.length-1];
            int low = nums.length -1;
            for(int i = nums.length-1; i>=0; i--){
                if(nums[i] > min){
                    low = i;
                }
                else{
                    min = nums[i];
                }
            }
            return (low - high +1) == nums.length ? 0 : high - low +1;
    
        }
    }

     

  • 相关阅读:
    【转】#pragma pack(push,1)与#pragma pack(1)的区别
    emwin 之变量定义位置
    【转】C语言字符串与数字相互转换
    【转】用emWin进度条控件做个表盘控件,效果不错
    emwin 之消息 WM_INIT_DIALOG
    emwin 之使用键盘数据发送函数的注意事项
    emwin 解决在A窗口上新建B窗口后‘只激活’B窗口问题
    【转】数学与编程——求余、取模运算及其性质
    hdu4831 Scenic Popularity(线段树)
    2014年百度之星程序设计大赛
  • 原文地址:https://www.cnblogs.com/mgdzy/p/14230860.html
Copyright © 2011-2022 走看看