LeetCode 剑指 Offer 刷题代码 (4)

面试题58 - II. 左旋转字符串

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

面试题58 - I. 翻转单词顺序

    public String reverseWords(String s) {
        s = s.trim();
        char[] arr = s.toCharArray();
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] == ' ' && arr[i - 1] == ' ')
                arr[i - 1] = '|';
        }
        String s1 = "", res ="";
        for(char c:arr)
            s1 += c+"";
        
        String[] split = s1.replace("|","").split(" ");
        for(int i=split.length-1; i>=0; i--)
            res += split[i] + " ";
        return res.trim();
    }

面试题57 - II. 和为s的连续正数序列

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。

序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

    public int[][] findContinuousSequence(int target) {
        ArrayList<int[]> list = new ArrayList<>();

        int i=1,j=2, sum=1+2;
        while(i<=target/2 && j<=target/2+1){
            if(sum>target){
                sum -= i++;
            }else if(sum<target){
                j++;
                sum += j;
            }else{ //==
                int []arr = new int[j-i+1];
                for(int k=i,q=0; k<=j; k++,q++) arr[q] = k;
                list.add(arr);
                sum += ++j;
            }
        }
        int res[][] = new int[list.size()][];
        for(i=0; i<list.size(); i++)
            res[i] = list.get(i);
        return res;
    }

面试题57. 和为s的两个数字

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

    public int[] twoSum(int[] nums, int target) {
        int i = 0, j = nums.length - 1;
        while (i < j - 1) {
            if (nums[i] + nums[j] < target)
                i++;
            else if (nums[i] + nums[j] > target)
                j--;
            else //==
                break;
        }
        return new int[]{nums[i], nums[j]};
    }

面试题56 - I. 数组中数字出现的次数

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

    public int[] singleNumbers(int[] nums) {
        int tmp = 0;
        for (int i = 0; i < nums.length; i++)
            tmp = tmp ^ nums[i];
        int one = tmp & (-tmp);
        
        int res1 = 0, res2 = 0;
        for (int i = 0; i < nums.length; i++)
            if ((nums[i] & one) == one)
                res1 ^= nums[i];
            else
                res2 ^= nums[i];
        return new int[]{res1, res2};
    }

面试题55 - II. 平衡二叉树

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

    public boolean isBalanced(TreeNode root) {
        if(root==null)
            return true;
        if(Math.abs(maxDepth(root.left)-maxDepth(root.right))>1)
            return false;
        return isBalanced(root.left) && isBalanced(root.right);
    }

    public int maxDepth(TreeNode root) {
        if(root==null)
            return 0;
        return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
    }

面试题55 - I. 二叉树的深度

    public int maxDepth(TreeNode root) {
        if(root==null)
            return 0;
        return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
    }

面试题54. 二叉搜索树的第k大节点

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

	//非递归中序遍历
    public int kthLargest(TreeNode root, int k) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode tmp = root;
        int count = 0;
        while(tmp!=null || !stack.empty()){
            while(tmp!=null){
                stack.add(tmp);
                tmp = tmp.right;
            }
            TreeNode node = stack.pop();
            count++;
            if(count==k) return node.val;
            tmp = node.left;
        }
        return -1;
    }

面试题53 - II. 0~n-1中缺失的数字

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

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

面试题53 - I. 在排序数组中查找数字 I

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

    public int search(int[] nums, int target) {
        int res=0, left = 0, right = nums.length-1, mid=0;
        while(left<=right){
            mid = (left+right)/2;
            if(nums[mid]>target) 
                right = mid-1;
            else if(nums[mid]<target)
                left = mid+1;
            else{
                res++;
                break;
            }
        }
        left = mid-1;
        while(left>=0 && nums[left--]==target) res++;
        right = mid+1;
        while(right<nums.length && nums[right++]==target) res++;
        
        return res;
    }

面试题52. 两个链表的第一个公共节点

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        Stack<ListNode> stackA = new Stack<>();
        Stack<ListNode> stackB = new Stack<>();
        ListNode tmpA = headA, tmpB = headB, res = null;

        while(tmpA!=null) {
            stackA.push(tmpA);
            tmpA = tmpA.next;
        }
        while(tmpB!=null) {
            stackB.push(tmpB);
            tmpB = tmpB.next;
        }
        if(stackA.empty() || stackB.empty())
            return null;
        while(!stackA.empty() && !stackB.empty() && stackA.peek()==stackB.peek()){
            res = stackA.pop();
            stackB.pop();
        }
        return res;
    }

面试题51. 数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

	private int res = 0;
    public int reversePairs(int[] nums) {
        mergeSort(nums,0,nums.length-1,new int[nums.length]);
        return res;
    }

    private void mergeSort(int[] nums, int s, int e, int[] tmp) {
        if(s>=e)
            return;
        int mid = (s+e)/2;
        mergeSort(nums, s, mid, tmp);
        mergeSort(nums, mid+1, e, tmp);
        merge(nums,s,mid,e,tmp);
    }

    private void merge(int[] nums, int s, int mid, int e, int[] tmp) {
        int i=s,j=mid+1,k=s;
        while(i<=mid && j<=e){
            if(nums[i]<=nums[j])
                tmp[k++] = nums[i++];
            else{
                tmp[k++] = nums[j++];
                res += mid-i+1;
            }
        }
        while(i<=mid)
            tmp[k++] = nums[i++];
            
        while (j<=e)
            tmp[k++] = nums[j++];

        for(i=s; i<=e; i++)
            nums[i] = tmp[i];
    }

面试题50. 第一个只出现一次的字符

在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。

    public char firstUniqChar(String s) {
        LinkedHashMap<Character, Integer> map = new LinkedHashMap<>();
        for(int i=0; i<s.length(); i++){
            char c = s.charAt(i);
            if(map.containsKey(c))
                map.put(c,map.get(c)+1);
            else
                map.put(c,1);
        }
        for(char c : map.keySet())
            if(map.get(c)==1)
                return c;
        return ' ';
    }

面试题49. 丑数

我们把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

    public int nthUglyNumber(int n) {
        int p2=0,p3=0,p5=0,index=0;
        int []arr = new int[n];
        arr[index++] = 1;
        while(index<n){
            int tmp = Math.min(arr[p2]*2,Math.min(arr[p3]*3,arr[p5]*5));
            if(tmp==arr[p2]*2) p2++;
            if(tmp==arr[p3]*3) p3++;
            if(tmp==arr[p5]*5) p5++;
            arr[index++] = tmp;
        }
        return arr[n-1];
    }

面试题48. 最长不含重复字符的子字符串

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

    public int lengthOfLongestSubstring(String s) {
        HashMap<Character, Integer> map = new HashMap<>();
        int max = 0;
        for(int head=0,tail=0; tail<s.length(); tail++){
            if(map.containsKey(s.charAt(tail))){
                head = Math.max(map.get(s.charAt(tail))+1,head);
            }
            map.put(s.charAt(tail),tail);
            max = Math.max(tail-head+1,max);
        }
        return max;
    }

面试题47. 礼物的最大价值

在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

	//动态规划 f(i, j) = max{f(i - 1, j), f(i, j - 1)} + grid[i][j]
    public int maxValue(int[][] grid) {

        for(int i=0; i<grid.length; i++){
            for(int j=0; j<grid[0].length; j++){
                int max = -1;
                if(i==0&&j==0) continue;
                if(i-1>=0) max = grid[i-1][j];
                if(j-1>=0) max = max>grid[i][j-1]?max:grid[i][j-1];
                grid[i][j] += max;
            }
        }
        return grid[grid.length-1][grid[0].length-1];
    }
	//超时
    private int res = 0;
    private int n,m;
    public int maxValue(int[][] grid) {
        if(grid==null || grid.length==0)
            return 0;
        n = grid.length; m=grid[0].length;
        dfs(grid,0,0,0);
        return res;
    }

    private void dfs(int[][] arr, int x, int y, int sum) {
        if(x==n-1 && y==m-1){
            sum += arr[x][y];
            res = res>sum?res:sum;
            return;
        }
        if(x+1<n)
            dfs(arr,x+1,y,sum+arr[x][y]);
        if(y+1<m)
        dfs(arr,x,y+1,sum+arr[x][y]);
    }

面试题46. 把数字翻译成字符串

给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

    public int translateNum(int num) {
        if(num<=9)
            return 1;
        if(num%100<=9 || num%100>=26)
            return translateNum(num/10);
        return translateNum(num/10)+translateNum(num/100);
    }

面试题45. 把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

    public String minNumber(int[] nums) {
        return Arrays.stream(nums).mapToObj(num->num+"")
                .sorted((i,j)->(i+j).compareTo(j+i))
                .collect(Collectors.joining());
    }

面试题44. 数字序列中某一位的数字

数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。

     public int findNthDigit(int n) {
        if(n<10)
            return n;
        long k=1,sum=n,s= (long) (Math.pow(10,k-1)*9);
        while(sum>s){
            sum -= s;
            k++;
            s = (long) (Math.pow(10,k-1)*9)*k;
        }
        String res = (int)(Math.pow(10,k-1)+(sum-1)/k) +"";
        int mod = (int)((sum-1) % k);
        return res.charAt(mod)-'0';
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值