解题-->在线OJ(十六)

1.搜索二维矩阵II

在这里插入图片描述

这个题目的解题思路 和在线OJ(十四)中的第一题 解题思路一样。

class Solution {
      public  static boolean searchMatrix(int[][] matrix, int target) {
        boolean flag=false;
        int i=matrix.length-1;
        int j=0;
        for(;i>=0 && j<matrix[0].length;){
            if(i<0 || j>=matrix[0].length){
                return flag;
            }
            if(matrix[i][j]==target && i>=0 && j<matrix[0].length){
                flag=true;
                break;
            }else if(matrix[i][j]>target && i>=0 && j<matrix[0].length){
                i--;
            }else if(matrix[i][j]<target && i>=0 && j<matrix[0].length){
                j++;
            }
        }
        return flag;
    }
}

2.1打家劫舍I(198)

在这里插入图片描述

class Solution {
   public  static int rob(int[] nums) {
        if(nums.length<=1){
            return nums.length==1?nums[0]:0;
        }
        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        int max=0;
        for(int i=1;i<nums.length;i++){
            if(i==1){
                dp[1]=Math.max(nums[0],nums[1]);
                max= Math.max(max,dp[1]);
                continue;
            }
            dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i]);
            max=Math.max(max,dp[i]);
        }
        return max;
    }
}

2.2打家劫舍II(213)

在这里插入图片描述

打家劫舍I和打家劫舍II的解题思路:
在这里插入图片描述

class Solution {
  public static int rob(int[] nums) {
         if(nums.length<=1){
            return nums.length==1?nums[0]:0;
        }
        //不抢头,不抢尾
        int[] nums1= Arrays.copyOfRange(nums,1,nums.length-1);
        //抢头,不抢尾
        int[] nums2=Arrays.copyOfRange(nums,0,nums.length-1);
        //不抢头,抢尾
        int[] nums3=Arrays.copyOfRange(nums,1,nums.length);
        return Math.max(dp(nums1),Math.max(dp(nums2),dp(nums3)));
    }
    public static int dp(int[] num){
        if(num.length<=1){
            return num.length==1?num[0]:0;
        }
        int max=0;
        int[] dp=new int[num.length];
        dp[0]=num[0];
        for(int i=1;i<num.length;i++){
            if(i==1){
                dp[1]=Math.max(num[0],num[1]);
                max=Math.max(dp[1],max);
                continue;
            }
            dp[i]=Math.max(dp[i-1],dp[i-2]+num[i]);
            max=Math.max(dp[i],max);
        }
        return max;
    }
}

2.3打家劫舍III(337)

在这里插入图片描述

class Solution {
public static int rob(TreeNode root) {
        //res 0:表示 不抢
        //res 1:表示 抢
        int[] res;
        res=best(root);
        return Math.max(res[0],res[1]);
    }
    public static  int[] best(TreeNode root){
        //如果节点为空,就直接返回{0,0}即可
        if(root==null){
            return new int[]{0,0};
        }
        int[] left=best(root.left);
        int[] right=best(root.right);
        //抢当前节点
        int rob=root.val+left[0]+right[0];
        //不抢当前节点
        int not_rob=Math.max(left[0],left[1])+Math.max(right[0],right[1]);
       return new int[]{not_rob,rob};
    }
}

3.前K个高频元素

在这里插入图片描述

class Solution {
  public static int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> hashMap=new HashMap<>();
        for(int x:nums){
            hashMap.put(x,hashMap.getOrDefault(x,0)+1);
        }
        List<Integer> list=hashMap.entrySet().stream().sorted((a,b)->b.getValue()-a.getValue()).map(a ->a.getKey()).collect(Collectors.toList());
        int[] result=new int[k];
        for(int i=0;i<result.length;i++){
            result[i]=list.get(i);
        }
        return result;
    }
}

4.字符串解码

在这里插入图片描述

解题思路:
1.先找到字符串当中第一个左括号对应的下标位置,然后再遍历,找到第一个左括号对应的右括号对应的下标位置。
2.截取这一段内容,在从左括号前一个下标开始往前遍历,找数字。
3.创建一个stringBuilder,首先,截取字符串,从下标0开始,到左括号对应的下标位置。
4.进行字符串拼接,while循环,条件是:数字>0,拼接之前截取的内容(左右括号里面的内容)。
5.然后,字符串再拼接右括号之后的数据。
6.进行递归,递归终止条件是:字符串内没有左括号,就直接返回字符串s即可。

class Solution {
 public static String decodeString(String s) {
        char[] arr=s.toCharArray();
        //寻找第一个 '['
        int left=0;
        int right=0;
        for(int i=0;i<arr.length;i++){
            if(arr[i]=='['){
                left=i;
                break;
            }
        }
        //递归终止条件,字符串中没有左括号
        if(left==0){
            return s;
        }
        //寻找 第一个'['与之对应的 ']'
        Stack<Character> stack=new Stack<>();
        for(int i=left+1;i<arr.length;i++){
            //在寻找']'的过程中,如果遇到'[',将其记录下来,进栈
            if(arr[i]=='['){
                stack.push(arr[i]);
            }
            //如果寻找到了']',但是栈不为空,就说明此时这个']'不是我们要找的,是之前记录下来的'['对应的']'
            //此时,只需要出栈一个'['即可
            else if(arr[i]==']' && !stack.isEmpty()){
                stack.pop();
            }
            //如果符合下面的条件,就说明找到了我们需要的']',将其记录下来
            else if(arr[i]==']' && stack.isEmpty()){
                right=i;
                break;
            }
        }
        //现在左右括号已经找到了,需要将里面的内容提取出来
        //substring:截取字符串,左闭右开
        String temp=s.substring(left+1,right);
        //定义一个StringBuilder,用于字符串的拼接
        StringBuilder stringBuilder=new StringBuilder();
        //现在需要算左括号之前的数字具体是多少
        int numLeft=left-1;
        int numRight=left-1;
        //从 left-1的位置开始往前看,看数字有几位
        while(numLeft>=0) {
            if (numLeft >= 0 && arr[numLeft] >= '0' && arr[numLeft] <= '9') {
                numLeft--;
            } else {
                break;
            }
        }
        //上面已经找到了数字位是从numLeft+1开始,截至到right
        //substring是左闭右开,所以,截取字符串的位置是(numLeft+1,numRight+1);
        int num=Integer.parseInt(s.substring(numLeft+1,numRight+1));
        //在循环拼接括号内的内容之前,需要先给stringBuilder拼接数字之前的数据
        stringBuilder.append(s.substring(0,numLeft+1));
        //给stringBuilder拼接括号内的内容
        while (num>0){
            stringBuilder.append(temp);
            num--;
        }
        //现在需要给stringBuilder拼接右括号之后的内容
        stringBuilder.append(s.substring(right+1));
        //进行递归
        return decodeString(stringBuilder.toString());
    }
}

5.表示数值的字符串

在这里插入图片描述

解题思路:
本题有几个条件:
1.点之前不能出现点或者e;
2.e之前不能出现e并且必须出现数字;
3.+/-的位置必须是0下标或者是+/-的位置之前是e。

class Solution {
public static boolean isNumber(String s) {
        boolean seeNum=false;
        boolean seePoint=false;
        boolean seeE=false;
        s=s.trim();
         s=s.toLowerCase();
        for(int i=0;i<s.length();i++){
            char ret=s.charAt(i);
            if(ret>='0' && ret<='9'){
               //说明当前已经出现了数字
                seeNum=true;
            }
            //1.点之前不能出现点或者e
            //当前为 点 的情况下,需要判断 seePoint 和 seeE 是否为true,如果为true,就说明点之前出现了点或者e,就直接返回false
            else if(ret=='.'){
                if(seePoint || seeE){
                    return false;
                }
                //这个记录当前字符为点,所以,将seePoint=true;
                seePoint=true;
            }
            // 2.e之前不能出现e并且必须出现数字
            //如果当前字符为'e'
            else if(ret=='e'){
                //如果e之前没有数字或者是已经出现了e,就直接返回false
                if(seeE || !seeNum){
                    return false;
                }
                //说明当前已经出现过数字
                seeE=true;
                seeNum=false;       //如果是12e,seeNum=false,返回seeNum即可
            }
            //3.+/-出现在0位置和e位置之后
            else if(ret=='+' || ret=='-'){
                if(i!=0 && s.charAt(i-1)!='e'){
                    return false;
                }
            }else{
                return false;
            }
        }
        return seeNum;
    }
}

6.树的子结构

在这里插入图片描述

解题思路:
1.判断 A的根节点 和 B的根节点 值是否一样;
2.如果节点值一样,递归,看A的左子树和B的左子树,A的右子树和B的右子树 节点值是否一致,递归终止条件:如果两个节点值不一样,返回false;一直递归,如果A的子树为空并且B的子树不为空,直接返回false;如果B的子树为空,直接返回true;
3.如果节点值不一样,递归,看A的左子树和B的根节点 的值是否一致;看A的右子树和B的根节点的值是否一致。

class Solution {
  public boolean isSubStructure(TreeNode A, TreeNode B) {
        //约定空树不是任意一个树的子结构
        if(A==null || B==null){
            return false;
        }
        //1.判断A节点的值和B节点值是否一致;
        //2.递归,看 A的左子树和B的根节点 的值是否一致
        //3.递归,看 A的右子树和B的根节点 的值是否一致
        return isSub(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B);
    }
    public boolean isSub(TreeNode A,TreeNode B){
        //说明B的结构已经遍历完了,就直接返回true
        if(B==null){
            return true;
        }
        //这里A结构已经遍历完了,但是B结构还没有遍历,说明这里不符合
        if(A==null){
            return false;
        }
        //如果两个节点值不一样的话,就不匹配
        if(A.val!=B.val){
            return false;
        }
        //走到这里,就说明A结构中的点和B结构中的点 值一样,相匹配
        return isSub(A.left,B.left) && isSub(A.right,B.right);
    }
}

7.栈的压入、弹出序列

在这里插入图片描述

解题思路:
1.遍历pushed,将元素入栈的过程中,需要判断栈顶元素和弹出序列的元素是否一样,如果一样,直接将元素出栈。
2.当元素全部进栈后,如果,栈此时不为空,则,继续将元素出栈,判断出栈的元素和弹出序列元素是否一样,如果不一样,直接返回false,如果一样,出栈。
3.最后判断弹出序列下标j是否等于弹出序列的长度。

class Solution {
  public static boolean validateStackSequences(int[] pushed, int[] popped) {
        Stack<Integer> stack=new Stack<>();
        int j=0;
        for(int i=0;i<pushed.length;i++){
            stack.push(pushed[i]);
            //如果栈不为空 并且 栈顶元素等于弹出队列元素,将元素出栈
             while(!stack.isEmpty() &&stack.peek()==popped[j]){
                stack.pop();
                j++;
            }
        }
        while(!stack.isEmpty()){
            int ret=stack.pop();
            if(ret==popped[j]){
                j++;
            }else{
                return false;
            }
        }
        return j==popped.length;
    }
}

8.二叉搜索树的后序遍历序列

在这里插入图片描述

解题思路:
判断这个数组是否满足某个二叉搜索树的后序遍历。
二叉搜索树的特点:左<根<右
后序遍历结果是:左右根,所以,后序遍历数组结果,最后一个节点值可以区分出哪些节点是该节点的左子树,哪些节点是该节点的右子树。
1.定义一个链表,将数组元素全部加入到链表当中;
2.拿到链表的最后一个值,将链表拆分左链表和右链表,再递归,再拿到最后一个值,再将链表拆分成左链表和右链表,直到链表长度<=1的时候,返回true.
3.递归返回false的情况是:控制链表下标的i不等于链表长度-1===》出现这种情况是因为:后序遍历错误。

class Solution {
     public static boolean verifyPostorder(int[] postorder) {
        List<Integer> list=new ArrayList<>();
        for(int x:postorder){
            list.add(x);
        }
        return  afterJudge(list);
    }
    //二叉搜索树的特点是:左<中<右
    //后续遍历的特点是 左右中,最后一个节点的值大于一部分连续节点,小于一部分连续节点,所以,由此,可以判断出哪些节点是根节点的左子树,哪些节点是根节点的右子树
    //在遍历的过程当中,如果出现了大于最后一个节点值的一系列节点不是连续,则这个后续遍历就是错误的
    public static boolean afterJudge(List<Integer> list){
        if(list.size()<=1){
            return true;
        }
        //记录链表的总长度
        int index=list.size();
        //获取 链表最后的值,也就是二叉搜索树的根节点的值
        int ret=list.get(index-1);
        int i=0;
        //主要目的:记录左节点的值
        List<Integer> left=new ArrayList<>();
        //主要目的:记录右节点的值
        List<Integer> right=new ArrayList<>();
        while(list.get(i)<ret){
            left.add(list.get(i++));
        }
        while(list.get(i)>ret){
            right.add(list.get(i++));
        }
        if(i!=list.size()-1){
            return false;
        }
        return afterJudge(left) && afterJudge(right);
    }
}

9.二叉树中和为某一值的路径

在这里插入图片描述

解题思路:
回溯法。

class Solution {
   List<List<Integer>> result=new ArrayList<>();
    public  List<List<Integer>> pathSum(TreeNode root, int target) {
        findSum(root,target,new ArrayList<>());
        return result;
    }
    public void findSum(TreeNode root,int target,List<Integer> list){
        if(root==null){
            return;
        }
        list.add(root.val);
        target=target-root.val;
        //target==0 并且 当前节点为叶子节点===》说明list当中的数据之和 等于 target,这是一组正确的结果,将这一组结果加入到result链表当中
     if(target==0 && root.left==null && root.right==null){
            result.add(new ArrayList<>(list));
        } else {
            findSum(root.left, target, list);
            findSum(root.right, target, list);
        }
        list.remove(list.size()-1);
    }
}

10.1+2+3+…+n

在这里插入图片描述

class Solution {
    public int sumNums(int n) {
           boolean flag=(n>0) && (n=n+sumNums(n-1))>0;
           return n;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值