《剑指Offer》(六):面试中的各项能力(更新中……)

文章目录

    • 剑指 Offer 53 - I. 在排序数组中查找数字 I
    • 剑指 Offer 53 - II. 0~n-1中缺失的数字
    • 剑指 Offer 54. 二叉搜索树的第k大节点
    • 剑指 Offer 55 - I. 二叉树的深度
    • 剑指 Offer 55 - II. 平衡二叉树
    • 剑指 Offer 57. 和为s的两个数字
    • 剑指 Offer 57 - II. 和为s的连续正数序列
    • 剑指 Offer 58 - I. 翻转单词顺序
    • 剑指 Offer 58 - II. 左旋转字符串
    • 剑指 Offer 65. 不用加减乘除做加法

剑指 Offer 53 - I. 在排序数组中查找数字 I

统计一个数字在排序数组中出现的次数。

解题思路: 二分查找

class Solution {
     
    public int search(int[] nums, int target) {
     
        if(nums==null||nums.length==0||target<nums[0]||target>nums[nums.length-1])return 0;
        int left,right;
        int i=0,j=nums.length-1;
        while(i<=j){
     
            int mid=(i+j)/2;
            if(nums[mid]<=target)i=mid+1;
            else j=mid-1;
        }
        right=i;
        if(j >= 0 && nums[j] != target) return 0;
        i=0;j=right-1;
        while(i<=j){
     
            int mid=(i+j)/2;
            if(nums[mid]>=target)j=mid-1;
            else i=mid+1;
        }
        left=i;

        return right-left;
    }
}

剑指 Offer 53 - II. 0~n-1中缺失的数字

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

解题思路:二分法

class Solution {
     
    public int missingNumber(int[] nums) {
     
        if(nums.length==1)return nums[0]==0?1:0;

        int i=0,j=nums.length-1;
        while(i<=j){
     
            int mid=(j+i)/2;
            if(nums[mid]==mid)i=mid+1;
            else j=mid-1;
        }
        return j+1;
    }
}

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

给定一棵二叉搜索树,请找出其中第k大的节点。

解题思路:递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
     
    int k,ans;
    public int kthLargest(TreeNode root, int k) {
     
        this.k=k;
        visit(root);
        return ans;
    }
    public void visit(TreeNode root){
     
        if(root.right!=null)visit(root.right);
        --k;
        if(k==0){
     
            ans=root.val;
            return;
        }
        if(root.left!=null) visit(root.left);
    }
}

剑指 Offer 55 - I. 二叉树的深度

输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。

解题思路:递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
     
    public int maxDepth(TreeNode root) {
     
        if(root==null)return 0;
        return 1+Math.max(maxDepth(root.left),maxDepth(root.right));
    }
}

剑指 Offer 55 - II. 平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

解题思路:递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
     
    public boolean isBalanced(TreeNode root) {
     
        return visit(root)!=-1;
    }
    public int visit(TreeNode root){
     
        if(root==null)return 0;
        int left=visit(root.left);
        if(left==-1)return -1;
        int right=visit(root.right);
        if(right==-1)return -1;
        return (left-right)>=-1&&(left-right)<=1?Math.max(left,right)+1:-1;
    }
}

剑指 Offer 57. 和为s的两个数字

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

解题思路:双指针

class Solution {
     
    public int[] twoSum(int[] nums, int target) {
     
        if(nums.length<=1||target<nums[0]||target>2*nums[nums.length-1])return new int[0];

        int i=0,j=nums.length-1;
        int[] ans=new int[2];
        while(i<j){
     
            if(nums[i]+nums[j]==target){
     
                ans[0]=nums[i];
                ans[1]=nums[j];
                return ans;
            }else if(nums[i]+nums[j]<target){
     
                ++i;
            }else{
     
                --j;
            }
        }
        return ans;
    }
}

剑指 Offer 57 - II. 和为s的连续正数序列

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

解题思路:双指针,滑动窗口

class Solution {
     
    public int[][] findContinuousSequence(int target) {
     
        if(target==1){
     
            int[][] ans=new int[1][1];
            ans[0][0]=1;
            return ans;
        }

        ArrayList<int[]> ans=new ArrayList<int[]>();
        int i=1,j=2,sum=1;
        while(j<=target/2+1){
     
            sum=(i+j)*(j-i+1)/2;
            if(sum<target)++j;
            else if(sum==target){
     
                int[] item=new int[j-i+1];
                for(int k=i;k<=j;++k){
     
                    item[k-i]=k;
                }
                ans.add(item);
                ++i;
            }else{
     
                ++i;
            }
        }
        return ans.toArray(new int[ans.size()][]);
    }
}

剑指 Offer 58 - I. 翻转单词顺序

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。

解题思路:从后往前遍历

class Solution {
     
    public String reverseWords(String s) {
     
        char[] ch=s.trim().toCharArray();
        if(ch.length==0)return "";
        
        int index=ch.length-1;
        StringBuilder ans=new StringBuilder();
        for(int i=index;i>=0;){
     
            // 找到第一个空格
            int j=i;
            while(j>=0&&ch[j]!=' '){
     
                --j;
            }
            ans.append(ch,j+1,i-j);
            ans.append(" ");
            // 跳过多个空格
            while(j>=0&&ch[j]==' '){
     
                --j;
            }
            i=j;
        }
        return ans.toString().trim();
    }
}

剑指 Offer 58 - II. 左旋转字符串

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

class Solution {
     
    public String reverseLeftWords(String s, int n) {
     
        if(s==null||s.length()==0)return s;
        return s.substring(n,s.length())+s.substring(0,n);
    }
}

剑指 Offer 65. 不用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

示例:

输入: a = 1, b = 1
输出: 2

你可能感兴趣的:(算法刷题,算法)