《剑指offer第二版》三

1. 旋转数组的最小数字

(1)题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1

(2)题目分析

遇到排序数组的查找问题,最优解一般都是二分法,这个题要分三种情况考虑,如果中间数字大于最右边的数字,那么最小值就在右数组,如果中间数字小于最右边的数字,那么最小值就在左数组,如果中间数字等于最右边的数字,则最小值即有可能存在于左数组,也有可能存在于右数组,这时候只需要让最右边的指针往左移动一位,这时候最小值肯定还在数组中。

(3)代码

package swordOffer.day3;

/**
 * @author chengzhengda
 * @version 1.0
 * @date 2020-03-22 17:45
 * @desc
 */
public class t11 {
    public int minArray(int[] numbers) {
        int i = 0;
        int j = numbers.length - 1;
        while (i < j) {
            int mid = (i + j) / 2;
            if (numbers[mid] > numbers[j]) {
                i = mid + 1;
            } else if (numbers[mid] < numbers[j]) {
                j = mid;
            } else {
                j--;
            }
        }
        return numbers[i];
    }
    public static void main(String[] args) {
        int[] nums = {1, 1, 1, 0, 1};
        t11 tt = new t11();
        System.out.println(tt.minArray(nums));
    }
}

2. 二进制中1的个数

(1)题目描述

请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。

(2)题目分析

数字1的二进制只有第一个是1,将数字与1按位与,如果等于1,那么说明该数字的第一位是1,然后对数字进行移位,直至数字等于0,便统计完了该数字二进制中所有的1。

(3)代码

package swordOffer.day3;

/**
 * @author chengzhengda
 * @version 1.0
 * @date 2020-03-23 11:30
 * @desc 二进制中1的个数
 */
public class t12 {

    public static int hammingWeight(int n) {
        int res = 0;
        while (n != 0) {
            res += n & 1;
            n >>>= 1;
        }
        return res;
    }

    public static void main(String[] args) {
        System.out.println(hammingWeight(9));
    }
}

3. 数值的整数次方

(1)题目描述

实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
示例 1:
输入: 2.00000, 10
输出: 1024.00000

(2)题目分析

这个题最直观的方法,是将负的幂转化为正的幂, 然后循环求乘法,但是如果幂的数字太大,会导致循环的次数过多,消耗太多的时间,因此这里需要引入快速幂的算法来解决,
当n为偶数时,x^n = x ^ (n/2) * x ^ (n/2),
当n为奇数时,x ^n = x ^ ((n-1)/2 ) * x ^ ((n-1)/2) * x
但是 由于n为奇数,n/2 = (n-1)/2,所以x ^ n = x ^ (n/2) * x( n/2 ) * x;
通过快速幂算法,可以将O(N)的时间复杂度降为O(logN)。

(3)代码

package swordOffer.day3;

/**
 * @author chengzhengda
 * @version 1.0
 * @date 2020-03-23 14:28
 * @desc
 */
public class t13 {
    public static double myPow(double x, int n) {
        if (x == 0) {
            return 0;
        }
        long a = n;
        double res = 1.0;

        if (a < 0) {
            x = 1.0 / x;
            a = -a;
        }

        while (a > 0) {
            if ((a & 1) == 1) {
                res *= x;
            }
            x *= x;
            a >>= 1;
        }
        return res;
    }

    public static void main(String[] args) {
        System.out.println(myPow(2.0, -2));
    }
}

4. 打印从1到最大的n位数

(1)题目描述

输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例 1:
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]

(2)题目分析

这个题没啥好说的,小学生都会做,,,

(3)代码

package swordOffer.day3;

/**
 * @author chengzhengda
 * @version 1.0
 * @date 2020-03-23 14:49
 * @desc
 */
public class t14 {

    public static void main(String[] args) {
        int res[] = printNumbers(3);
        for (int i : res) {
            System.out.println(i);
        }
    }

    public static int[] printNumbers(int n) {
        double num = Math.pow(10, n);
        int[] res = new int[(int) num - 1];
        for (int i = 1; i < num; i++) {
            res[i - 1] = i;
        }
        return res;
    }
}

5. 删除链表的节点

(1)题目描述

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意:此题对比原题有改动
示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

(2)题目分析

本题比较容易,需要注意的点是,需要创建一个虚拟的头结点,因为原链表的第一个节点也是可能被删除的。

(3)代码

package swordOffer.day3;

import charpter2.ListNode;

/**
 * @author chengzhengda
 * @version 1.0
 * @date 2020-03-23 14:57
 * @desc
 */
public class t15 {
    public static ListNode deleteNode(ListNode head, int val) {
        ListNode temp = new ListNode(0);
        temp.next = head;
        ListNode res = temp;
        while (temp.next != null) {
            if (temp.next.val == val) {
                temp.next = temp.next.next;
                break;
            }
            temp = temp.next;
        }
        return res.next;
    }

    public static void main(String[] args) {
        ListNode listNode1 = new ListNode(1);
        ListNode listNode2 = new ListNode(2);
        ListNode listNode3 = new ListNode(3);
        ListNode listNode4 = new ListNode(4);
        listNode1.next = listNode2;
        listNode2.next = listNode3;
        listNode3.next = listNode4;

        ListNode res = deleteNode(listNode1, 1);
        while (res != null) {
            System.out.println(res.val);
            res = res.next;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值