CodeTop100 Day33

128、字典序第k小的数

class Solution {
    public int findKthNumber(int n, int k) {
        /*
         leetcode评论区郭郭解析
        本质是一个10叉树的先序遍历,找到按照先序遍历的第k个节点
        为什么是先序遍历?这个由字典序的性质决定:[1,10,100,1000,1001]
        假设相同位数的数字在10叉树的同一层上,那么就是先序遍历就是字典序排列
        从cur=1开始进行遍历,先计算的以cur为根的且<=n的节点个数nodes
            若nodes<=k,说明以cur开头的合格节点数不够,cur应该向右走:cur++
            若nodes>k,说明以cur开头的合格节点数足够,cur应该向下走:cur*=10
        */
        // 首先遍历以1开头大的数字
        // 由于cur可能会很大,因此int可能计算过程中会溢出,用long类型
        long cur = 1;
        // 因为1遍历了,因此k--
        k--;
        // 当且仅当k>0(还未遍历到第k个的时候)循环
        while(k > 0) {
            // 获取以cur开头的子节点合格(<=n)数目nodes
            int nodes = getNodes(n, cur);
            // 若nodes<=k的话说明把这nodes个节点分完都还没到k
            if(nodes <= k) {
                // cur向右走
                cur++;
                // 抵消掉nodes个节点
                k -= nodes;
            }else {
                // 若nodes>k的话说明把nodes个节点够分
                // cur往下走
                cur *= 10;
                // 将cur计算进k
                k--;
            }
        }
        // 最后cur会停留在第k小的数上
        return (int)cur;
    }

    /*
    计算[1,n]内以cur为根(开头)的节点个数
    */
    private int getNodes(int n, long cur) {
        // next表示cur右边的数,此时cur=10,next=11
        long next = cur + 1;
        // 统计合格的节点个数
        long totalNodes = 0;
        // 当cur<=n时可以进入循环
        while(cur <= n) {
            // 这里是最关键的一步:当n不在cur层时,该层有效节点数目为next - cur(全部都要了)
            // 当n在cur层时,该层有效节点数目为n - cur + 1(要一部分)
            // 统一起来就是取最小值
            totalNodes += Math.min(n - cur + 1, next - cur);
            // cur与next均向下计算
            cur *= 10;
            next *= 10;
        }
        return (int)totalNodes;
    }
}

129、删除二叉搜索树中的节点

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        //若该节点没有子节点就直接删除,若有子节点则调整该节点
        if(root==null){return null;}
       if(root.val==key){
        if(root.left==null) return root.right;
        if(root.right==null)return root.left;
        TreeNode t=root.left;
        while(t.right!=null) t=t.right;
        t.right=root.right;
        return root.left;
       }else if(root.val<key)root.right=deleteNode(root.right,key);
       else root.left=deleteNode(root.left,key);
       return root;
    }



}

130、验证回文串

class Solution {
    public boolean isPalindrome(String s) {
        s=s.toLowerCase();
        int left=0;
        int right=s.length()-1;
        while(left<right){
            while(left<right&&!Character.isLetterOrDigit(s.charAt(left))){
                left++;
            }
            while(left<right&&!Character.isLetterOrDigit(s.charAt(right))){
                right--;
            }

            if(left<right){
                if(s.charAt(left)!=s.charAt(right)){
                    return false;
                }
                left++;
                right--;
            }
            
        }
        return true;
    }
}

131、解码方法

class Solution {
    public int numDecodings(String s) {
        //每次选一位或者两位
        //f[i]=f[i-1]+f[i-2];
        int n=s.length();
        s=" "+s;
        char[] cs=s.toCharArray();
        int[] f=new int[n+1];
        f[0]=1;
        for(int i=1;i<=n;i++){
            int a=cs[i]-'0',b=(cs[i-1]-'0')*10+(cs[i]-'0');
            if(1<=a&&a<=9)f[i]=f[i-1];
            if(10<=b&&b<=26)f[i]=f[i]+f[i-2];
        }
        return f[n];
    }
}

132、子结构判断

class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        return (A != null && B != null) && (recur(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B));
    }
    boolean recur(TreeNode A, TreeNode B) {
        if(B == null) return true;
        if(A == null || A.val != B.val) return false;
        return recur(A.left, B.left) && recur(A.right, B.right);
    }
}

先序遍历树 A 中的每个节点 node ;(对应函数 isSubStructure(A, B))
判断树 A 中以 node 为根节点的子树是否包含树 B 。(对应函数 recur(A, B))

133、跳跃训练

public class Solution {
    public int trainWays(int n) {
        if (n == 0 || n == 1) {
            return 1;
        }
        int[] dp = new int[n + 1];
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= n; i++) {
            dp[i] = (dp[i - 2] + dp[i - 1]) % 1000_000_007;
        }
        return dp[n];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值