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;
}
}
}