【Double Week】No.21

C_01 上升下降字符串

给你一个字符串 s ,请你根据下面的算法重新构造字符串:

  • 从 s 中选出 最小 的字符,将它 接在 结果字符串的后面。
  • 从 s 剩余字符中选出 最小 的字符,且该字符比上一个添加的字符大,将它 接- 在 结果字符串后面。
  • 重复步骤 2 ,直到你没法从 s 中选择字符。
  • 从 s 中选出 最大 的字符,将它 接在 结果字符串的后面。
  • 从 s 剩余字符中选出 最大 的字符,且该字符比上一个添加的字符小,将它 接在 结果字符串后面。
  • 重复步骤 5 ,直到你没法从 s 中选择字符。
  • 重复步骤 1 到 6 ,直到 s 中所有字符都已经被选过。

在任何一步中,如果最小或者最大字符不止一个 ,你可以选择其中任意一个,并将其添加到结果字符串。

请你返回将 s 中字符重新排序后的 结果字符串 。

输入:s = "aaaabbbbcccc"
输出:"abccbaabccba"
解释:第一轮的步骤 123 后,结果字符串为 result = "abc"
第一轮的步骤 456 后,结果字符串为 result = "abccba"
第一轮结束,现在 s = "aabbcc" ,我们再次回到步骤 1
第二轮的步骤 123 后,结果字符串为 result = "abccbaabc"
第二轮的步骤 456 后,结果字符串为 result = "abccbaabccba"

方法一:前后遍历法

题目中要求我们第一次选完字符串 s 中的最小不重复字符,然后第二轮选择第一轮中选剩下的并且从大开始选。

用 map 记录字符串 s 中每个字符的出现次数,当 sb 的长度不够 n 时,我们一直遍历,然后从小到大选即从区间 [0,25] 区间中选一轮,然后又从区间 [25, 0] 又选一轮,这样可以保证排序的要求。

public String sortString(String s) {

  StringBuilder sb = new StringBuilder();
  char[] S = s.toCharArray();
  int N = S.length, i = 0;
  int[] map = new int[26];
  for (int j = 0; j < N; j++) {
    map[S[j]-'a']++;
  }
  
  while (i < N) {
    for (int j = 0; j < 26; j++)
    if (map[j]-- > 0) {
      sb.append((char) (j + 'a'));
      i++;
    }
    for (int j = 25; j >= 0; j--)
    if (map[j]-- > 0) {
      sb.append((char)(j + 'a'));
      i++;
    }
  }
  return sb.toString();
}

复杂度分析

  • 时间复杂度: O ( n ) O(n)
  • 空间复杂度: O ( n ) O(n)

B_02 每个元音包含偶数次的最长子字符串(没做)

给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:每个元音字母,即 'a','e','i','o','u' ,在子字符串中都恰好出现了偶数次。

输入:s = "eleetminicoworoep"
输出:13
解释:最长子字符串是 "leetminicowor" ,它包含 e,i,o 各 2 个,以及 0 个 a,u 。

方法一:


复杂度分析

  • 时间复杂度: O ( ) O()
  • 空间复杂度: O ( ) O()

B_03 二叉树中的最长交错路径

给你一棵以 root 为根的二叉树,二叉树中的交错路径定义如下:

  • 选择二叉树中 任意 节点和一个方向(左或者右)。
  • 如果前进方向为右,那么移动到当前节点的的右子节点,否则移动到它的左子节点。
  • 改变前进方向:左变右或者右变左。
  • 重复第二步和第三步,直到你在树中无法继续移动。

交错路径的长度定义为:访问过的节点数目 - 1(单个节点的路径长度为 0 )。

请你返回给定树中最长 交错路径 的长度。

输入:root = [1,null,1,1,1,null,null,1,1,null,1,null,null,null,1,null,1]
输出:3
解释:蓝色节点为树中最长交错路径(右 ->-> 右)。

方法一:dfs

我们需要一个变量记录当前结点是从什么方向走过来的,

  • 上次是从左边走过来,
    • 我们又要走左边,那么我们将交错路径的长度 depth 重新置为 1。
    • 如果我们走右边,只需把交错路径的深度 depth +1。
  • 上次是从右边走过来,
    • 我们又要走右边,那么我们将交错路径的长度 depth 重新置为 1。
    • 如果我们走左边,只需把交错路径的深度 depth +1、
int max = 0;
final static boolean toLeft = true;
final static boolean toRight = false;
public int longestZigZag(TreeNode root) {
  dfs(root, toLeft, 0);
  return res;
}
private void dfs(TreeNode root, boolean pre, int depth) {

  if (root == null)
    return;
  if (pre == toLeft) {
    dfs(root.left, toLeft, 1);
    dfs(root.right, toRight, depth + 1);
  } else {
    dfs(root.right, toRight, 1);
    dfs(root.left, toLeft, depth + 1);
  }
  max = Math.max(max, depth);
}

复杂度分析

  • 时间复杂度: O ( n ) O(n)
  • 空间复杂度: O ( n ) O(n)

A_04 Maximum Sum BST in Binary Tree

给你一棵以 root 为根的 二叉树 ,请你返回 任意 二叉搜索子树的最大键值和。

二叉搜索树的定义如下:

  • 任意节点的左子树中的键值都 小于 此节点的键值。
  • 任意节点的右子树中的键值都 大于 此节点的键值。
  • 任意节点的左子树和右子树都是二叉搜索树。

示例 1:

输入:root = [1,4,3,2,4,2,5,null,null,null,null,null,null,4,6]
输出:20
解释:键值为 3 的子树是和最大的二叉搜索树。

方法一:模板代码

第一次写的时候,因为没有注意到构造函数的参数,导致在前几一个 if,else 中返回了一些 0 作为参数,也直接导致了后面的计算出错。

class Solution {
    int max = 0;
    public int maxSumBST(TreeNode root) {
        dfs(root);
        return max;
    }
    private ResultNode dfs(TreeNode root) {
        if (root == null)  
            return new ResultNode(true);
            
        ResultNode left =  dfs(root.left);
        ResultNode right = dfs(root.right);
        
        if (left.isBST == false || right.isBST == false) {
            return new ResultNode(false);
        }
        ResultNode rt = new ResultNode();
        if (root.val > left.max_val && root.val < right.min_val) {
            rt.isBST = true;
            rt.sum = root.val + left.sum + right.sum;
            max = Math.max(rt.sum, max);
            rt.min_val = Math.min(root.val, left.min_val);  
            rt.max_val = Math.max(root.val, right.max_val);
        } else {
            rt.isBST = false;
        }
        return rt;
    }
    class ResultNode {
        //二叉搜索树
        public boolean isBST = false;
        public int sum;
        public long min_val = Long.MAX_VALUE;
        public long max_val = Long.MIN_VALUE;
        public ResultNode(boolean _isBST, long _min_num, long _max_num) {
            isBST = _isBST;
            min_val = _min_num;
            max_val = _max_num;
        }
        public ResultNode(boolean _isBST, long _min_num, long _max_num, int _sum) {
            isBST = _isBST;
            sum = _sum;
            min_val = _min_num;
            max_val = _max_num;
        }
        public ResultNode(boolean _isBST) {
            isBST = _isBST;
        }
        public ResultNode() {}
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n)
  • 空间复杂度: O ( n ) O(n)

发布了461 篇原创文章 · 获赞 102 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/104725476