刷题找工作第8篇

什么是平衡二叉树
答:有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树

位运算与绝对值
-1的二进制码
题目1:
平衡二叉树

public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
        
        return dfs(root)!=-1;
    }
    
    int dfs(TreeNode root)
    {
        if(root==null) return 0;
        
        int left=dfs(root.left);
        if(left==-1) return -1;
        int right = dfs(root.right);
        if(right==-1) return -1;
        
        return Math.abs(left-right)>1 ? -1: Math.max(left,right)+1;
        
        
        
    }
}

下面这种代码可以对比一下,没有进行减枝的

链接:https://www.nowcoder.com/questionTerminal/8b3b95850edb4115918ecebdf1b4d222?f=discussion
来源:牛客网

public classSolution {
    public boolean IsBalanced_Solution(TreeNode root) {
        if(root == null) {
            return true;
        }
        return Math.abs(maxDepth(root.left) - maxDepth(root.right)) <= 1 &&
            IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
    }
      
    private int maxDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
    }
}

题目二
只出现一次的数

题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

普通方法:使用HashMap 两次遍历,返回结果
普通法二: 排序一遍,使用栈,peek一下相同的就pop,不同的就push ,最终栈里只有两个值,
拿出来就是要的那个数
异或方法

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果

public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        
        int aOrb = 0;
        num1[0]=num2[0]=0;
        for(int i:array) aOrb^=i;
        
        int i=0;
        for(;i<31;++i)
        {
            if((aOrb&(1<<i))!=0) break;
        }
               
        int flag = 1<<i;
        for(int j:array) {
            if((j&flag)==0)
            {
                num1[0]^=j;
            }else{
                num2[0]^=j;
            }
        }

    }
}

这个题我解释一下,一个数和数组里的所有数异或,由于数组里只有两个数的不一样的,因此这个数的值等于 num1[0]^num2[0],思考一下,异或两次得到0哦0与任何数异或都等于那个数,自己画个图想一下
num1[0]与num2[0]不一样,那么异或之后的二进制数一定有个值为1,(举个例子,i等于j,i^j==0;)(如果i!=j ,那么 i异或j一定不等于0),也就是说,相同异或为0,不同异或为1只要找到不同,就能区分开个两个数,用两个桶分别装起来
因此,利用二进制数1的位置不同,可以区分 Num1和Num2

题目三
和为S的连续正数
时间复杂度不知怎么分析,估计不会是 O(N^2), 因为是等差数列 N ∗ ( N + 1 ) / 2 = s u m N*(N+1)/2=sum N(N+1)/2=sum , 所以 N< 2 ∗ s u m \sqrt{2*sum} 2sum

import java.util.ArrayList;
import java.util.Collections;
public class Solution {
    int sum;
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
       this.sum = sum;
        ArrayList<ArrayList<Integer>> ans = new ArrayList();
        //等差数列: N*(A中) = sum, 关键是求 (A中),求中间那个数
        //注意到 N*(N+1)= 2* sum ,因此N是有个上界的,
        if(sum<=1) 
        {
            return ans;
        }
        int bound = (int)Math.sqrt(sum<<1);
        for(int i=1;i<bound;++i)
        {
            int mid = sum/i;
            if((i&1)==1)
            {
               ArrayList p =  getOdd(mid,false);
               if(!p.isEmpty()) ans.add(p);
            }else{
                ArrayList p =  getOdd(mid,true);
               if(!p.isEmpty()) ans.add(p);
            }
        }
        Collections.sort(ans,(ArrayList<Integer> a,ArrayList<Integer> b)->{return a.get(0).compareTo(b.get(0));});
        return ans;

    }
    public ArrayList<Integer> getOdd(int mid,boolean even)
    {
        ArrayList<Integer> res = new ArrayList();
        if(mid==sum)
        {
            
            return res;
        }
        int l = mid-1,r = mid+1;
        if(even) ++l;
        int sq = l+r+mid;
        if(even) sq-=mid;
        while(sq<=sum)
        {
            if(sq==sum)
            {
                for(int i=l;i<=r&&(i>0);++i)
                {
                    if(i==0) continue;
                    res.add(i);
                }
                return res;
            }
            
            l--;r++;
            sq+=(l+r);  
        }
        return res;   
    }

}

我看了一下,有一种双指针的写法,维护一个滑动窗口,窗口内的和小于sum,r++,窗口内的和大于sum,那么l++, 等于的话登记一下信息,再 l++(因为r++的话一定是大于sum的)
我也写一下

import java.util.ArrayList;
import java.util.Collections;
public class Solution {
    int sum;
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
       
        ArrayList<ArrayList<Integer>> ans = new ArrayList();
        //等差数列: N*(A中) = sum, 关键是求 (A中),求中间那个数
        //注意到 N*(N+1)= 2* sum ,因此N是有个上界的
        if(sum<=1) return ans;
        int l=1,r=2;
        while(l<r)
        {
            //在内部使用等差数列的公式计算
            int res = (r-l+1)*(l+r)>>>1;
            if(res<sum) r++;
            else if(res==sum)
            {
                ArrayList<Integer> arr = new ArrayList();
                for(int i=l;i<=r;++i)
                {
                    arr.add(i);
                }
                ans.add(arr);
                l++;
            }
            
            else{
                l++;
            }
  
        }
        return ans;
 
    }

}

题目四
和为S的数字
题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] arr,int sum) {
        // i+j=sum, 求 min(i*j),也就是i==j的时候, i*j最大, 如果ij相差越远就越小
        int l=0,r=arr.length-1;

        while(l<r)
        {
            
            int res = arr[l]+arr[r];
            if(res>sum) 
            {
                r--;
            }
            else if(res==sum)
            {
                ArrayList<Integer> p = new ArrayList<Integer>();
                p.add(arr[l]);
                p.add(arr[r]);
                return p;
                
            }else
            {
                 l++;
            }
            
        }
        
        
        return new ArrayList<Integer>();
    }
}

题目五
左旋转字符串
题目描述
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它

public class Solution {
    public String LeftRotateString(String str,int n) {
        int len = str.length();
        if(len<n) return "";
        
        String ans = (str+str).substring(n,len+n);
        return ans;
        
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值