每日五题-(5)

今天没有针对什么专门去做,就是自己剑指还没有刷完的,随便点开五道。

剑指Offer 54.二叉搜索树的第k大节点

在这里插入图片描述

解析过程:

要解此题就得知道什么是二叉搜索树,其满足左孩子 <= 根 <= 右孩子。所以我们要是对其进行中序遍历的话就会有顺序的进行输出,但是此题要求解的是第k大节点,所以也就是倒数第k个,那么就需要进行二叉树的倒序输出了,[右,根,左]。使用递归去遍历的时候需要注意对其k次进行–操作,对第k个元素信息得保存起来,并返回。

代码实现:

class Solution {
    int res,k;
    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        dfs(root);
        return res;
    }
    public void dfs(TreeNode root){
        //如果root为null说明已经到了叶子结点了,返回。
        if(root == null)return;
        //先遍历右子树
        dfs(root.right);
        //访问根结点,记录访问的次数,对k进行--;
        if(--k == 0){
            res = root.val;
            return;
        }
        dfs(root.left);
    }
}

剑指Offer 39.数组中出现次数超过一半的数字

在这里插入图片描述

解析过程:

方式一:HashMap

遍历数组,对所有元素的出现次数进行存储,然后判断次数是否大于数组个数一半,返回。时间复杂度是O(n),空间复杂度也是O(n)。

方式二:排序

题目给定一定存在多数元素,也就是个数大于全部个数一半的数,那么排序之后出现在中间位置上的也就一定是这个数了,懒得写排序过程了,所以就直接Arrays.sort了。

方式三:摩尔投票法

看了大佬的解析,真的很妙!假定众数是x,那么就对其票数加一,如果碰到非众数,就对票数减一,当票数为0时,对将新遍历元素设为众数,再进行判断与计算,那么众数的票数最后一定是>=1的那个。时间复杂度是O(n),空间复杂度是O(1)。

代码实现:

class Solution {
    //方式一:HashMap记录
    //实现复杂度是O(n),空间复杂度也是O(n)
    // Map<Integer,Integer> map;
    // public int majorityElement(int[] nums) {
    //     map = new HashMap<>();
    //     int res = 0;
    //     for(int i = 0;i < nums.length;i++){
    //         map.put(nums[i],map.getOrDefault(nums[i],0)+1);
    //         if(map.get(nums[i])>nums.length/2){
    //             res = nums[i];
    //             break;
    //         }
    //     }
    //     return res;
    // }
    //方式二:排序
    //排序过程懒得写,就Arrays.sort吧,哈哈哈
    // public int majorityElement(int[] nums) {
    //     Arrays.sort(nums);
    //     return nums[nums.length/2];
    // }
    //方式三:摩尔投票法
    //这个方式是看的大佬解析的,真的厉害,就很妙
    public int majorityElement(int[] nums) {
        int x = 0, count = 0;
        for(int num:nums){
            if(count == 0)x = num;
            count += x == num ? 1 : -1;
        }
        return x;
    }
}

这个方法果然有点强!

在这里插入图片描述

剑指Offer28.对称的二叉树

在这里插入图片描述

解析过程:

首先对于根节点来说的话,如果根节点为空,那么这个树我们就可以认为是一个对称的二叉树,如果根节点不为空,那么只需要判断左子树和右子树是否为对称的,然后再去递归判断子树的子树是否为对称的。

当然最后结束条件肯定得到叶子结点了,如果两个都为空,那么说明是对称的,如果只有一个为空或者值不同,说明不对称。

代码实现:

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null)return true;
        return method(root.left,root.right);
    }
    public boolean method(TreeNode l,TreeNode r){
        if(l == null && r == null)return true;
        if(l == null || r == null || l.val != r.val)return false;
        return method(l.left,r.right) && method(l.right ,r.left);
    }
}

剑指Offer30.包含min函数的栈

在这里插入图片描述

解析过程:

这道题真的很简单,我都感觉有点凑数了!

用两个栈来实现对栈中最小值的存放,首先不能单纯的用一个变量来存放最小值,因为栈的特性是先进后出的,如果只是用一个变量来存,那么如果最小值弹出了,此时最小值就需要变化,但是从当下位置往下的所有元素都是随机的,无法找到最小元素(别跟我说遍历)。

所以呢,如果栈为空则最小值栈同样一起压栈,如果不为空,则判断要压栈的元素是不是比当前最小栈中存放的元素还要小,如果是,则压进去。弹栈就是看看当前要栈顶元素是不是最小值栈的栈顶元素即可。

代码实现:

class MinStack {
    Deque<Integer> stack1,stack2;
    /** initialize your data structure here. */
    public MinStack() {
        stack1 = new LinkedList<>();
        stack2 = new LinkedList<>();
    }
    
    public void push(int x) {
        stack1.push(x);
        if(stack2.isEmpty() || stack2.peek() >= x){
            stack2.push(x);
        }
    }
    
    public void pop() {
        if(stack1.pop().equals(stack2.peek())){
            stack2.pop();
        }
    }
    
    public int top() {
        return stack1.peek();
    }
    
    public int min() {
        return stack2.peek();
    }
}

剑指Offer62.圆圈中最后剩下的数字

在这里插入图片描述

解析过程:

这是一道约瑟夫环问题,这个过程还是比较难想,我觉得它不应该列为简单题。。。

我觉得自己也将的不是很明白,大家可以自己去看看解析。。。

class Solution {
    //方式一:递归
    // public int lastRemaining(int n, int m) {
    //     return method(n,m);
    // }
    // public int method(int n,int m){
    //     if(n == 1)return 0;
    //     int x = method(n-1,m);
    //     return (m+x)%n;
    // }
    //方式二:迭代
    public int lastRemaining(int n, int m) {
        int f = 0;
        for(int i = 2;i <= n;i++){
            f = (f+m)%i;
        }
        return f;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值