剑指offer:0~n-1中缺失的数字、二叉搜索树的最大k个节点、二叉树的深度、平衡二叉树、数组中数字出现的次数、和为s的两个数字、和为s的连续正数序列、翻转单词顺序、左旋字符串、滑动窗口的最大值

0~n-1中缺失的数字

题目

在这里插入图片描述

题解

    public int missingNumber(int[] nums) {
        for(int i=0;i<nums.length;i++){
            if(nums[i]!=i){
                return i;
            }
        }
        return nums.length;
    }

二叉搜索树的第k大节点

题目

在这里插入图片描述

题解

思路:由于二叉搜索树中序遍历得到的序列升序的,因此中序遍历的逆序得到的序列就是降序的,通过右-中-左的方式遍历二叉搜索树,得到的第k个节点就是第k大的
代码:

    private int count=0;
    private int res=0;

    public int kthLargest(TreeNode root, int k) {

        inorder(root,k);
        return res;
    }
    public void   inorder(TreeNode root,int k){
        if(root==null) return;
        inorder(root.right,k);
        count++;
        if(count==k) res=root.val;

        inorder(root.left,k);

    }

二叉树的深度

题目

在这里插入图片描述

题解

代码:

public int maxDepth(TreeNode root) {
       if(root==null) return 0;
       int leftH=maxDepth(root.left);
       int rightH=maxDepth(root.right);
       return leftH>rightH?leftH+1:rightH+1;
    }

平衡二叉树

题目

在这里插入图片描述

题解

代码:

    public boolean isBalanced(TreeNode root) {

      return getDepth(root)>=0;
    }

    public int getDepth(TreeNode root){
        if(root==null) return 0;
        int leftH=getDepth(root.left);
        int rightH=getDepth(root.right);
        if(leftH>=0 && rightH>=0 && Math.abs(leftH-rightH)<=1){
            return leftH>rightH?leftH+1:rightH+1;
        }else {
            return -1;
        }
    }

数组中数字出现的次数(一)

题目

在这里插入图片描述

题解

public int[] singleNumbers(int[] nums) {
       
       int[] ans=new int[2];
       int ret=0;
       for(int num:nums){
           ret^=num;
       }
       int offset=0;
       while((ret&1)==0){
           ret>>=1;
           offset++;
       }
      for(int num:nums){
          if(((num>>offset) & 1) ==0){
              ans[0]^=num;
          }else {
              ans[1]^=num;
          }
      }
      return ans;
    }

数组中数字出现的次数

题目

在这里插入图片描述

题解

思路:我们需要统计所有数字在某一位置的和能不能被3整除,如果不能被3整除,说明那个只出现一次的数字的二进制在那个位置是1……把32位全部统计完为止
代码:

 public int singleNumber(int[] nums) {
       int ret=0;
       for(int i=0;i<32;i++){
           int oneCount=0;
           //统计第i位中1的个数
           for(int j=0;j<nums.length;j++){
               oneCount+=(nums[j]>>i) & 1;
           }
           if(oneCount%3==1){
               ret |= 1<<i;
           }
       }
       return ret;
    }

和为s的两个数字

题目

在这里插入图片描述

题解

代码:

    public int[] twoSum(int[] nums, int target) {
       
       int left=0;
       int right=nums.length-1;
       while(left<right){
           if(nums[left]+nums[right]==target){
               return new int[]{nums[left],nums[right]};
           }else if(nums[left]+nums[right]<target){
               left++;
           }else {
               right--;
           }
       }
       return new int[]{-1,-1};
    }

和为s的连续正数序列

题目

在这里插入图片描述

题解

思路:滑动窗口+双指针,定义l,r分别指向窗口的左右边界,s保存窗口中所有数的和
初始值:l为1,r为2,s为3
比较s与target

  • 当s==target时,将窗口中的序列加入到结果集
  • 当s < target,r++,扩大窗口,同时更新元素和s
  • 当s > target,l++,缩小窗口,同时更新元素和s

当l>=r时,跳出循环,因为题目要求序列最少包含两个元素
代码:

 public int[][] findContinuousSequence(int target) {
       
       List<int[]> ret=new ArrayList<>();
       int l=1;
       int r=2;
       int s=3;
       while(l<r){
           if(s==target){ //将当前窗口中的序列加入到结果集
               int[] tmp=new int[r-l+1];
               for(int i=l;i<=r;i++){
                  tmp[i-l]=i;
               }
               ret.add(tmp);
           }
           if(s<target){ //如果窗口中所有数的序列和小于target,r向后移动一位,扩大窗口,同时s+=r
                r++;
                s+=r;
           }else { //如果窗口中所有数组成的序列和大于等于target,l向后移动一位,缩小窗口,同时s-=r
               s-=l;
               l++;
           }
       }
       return ret.toArray(new int[0][]);
    }

翻转单词顺序

题目

在这里插入图片描述

题解

    public String reverseWords(String str) {

     String[] ss=str.trim().split(" ");
     StringBuffer sb=new StringBuffer();
     for(int i=ss.length-1;i>=0;i--){
         if(ss[i].equals("")) continue;
         sb.append(ss[i]+" ");
     }     
     return sb.toString().trim();
    }

左旋字符串

题目

在这里插入图片描述

题解

   public String reverseLeftWords(String s, int n) {
      return s.substring(n)+s.substring(0,n);
    }

滑动窗口的最大值

题目

在这里插入图片描述

题解

代码:

 private Deque<Integer> queue=new LinkedList<>();
    
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n=nums.length;
        int[] ret=new int[n-k+1];
        for(int i=0;i<k;i++){
          while(!queue.isEmpty() && nums[i]>=nums[queue.peekLast()]){
              queue.pollLast();
          }
          queue.offerLast(i);
        }
          ret[0]=nums[queue.peekFirst()];
          for(int i=k;i<n;i++){
              while(!queue.isEmpty() && nums[i]>=nums[queue.peekLast()]){
              queue.pollLast();
          }
          queue.offerLast(i);
             while(queue.peekFirst()<=i-k){
                 queue.pollFirst();
             }
             ret[i-k+1]=nums[queue.peekFirst()];
             
          }
            return ret;
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值