11.给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。不得使用库函数,不需要考虑大数问题
思路:不能用==比较两个浮点数是否相等,因为有误差。考虑输入值的多种情况。
代码实现:
public double Power(double base, int exponent) {
double res = 0;
if (equal(base,0)) {
return 0;
}
if (exponent == 0) {
return 1.0;
}
if (exponent > 0) {
res = mutiply(base,exponent);
}else {
res = mutiply(1/base,-exponent);
}
return res;
}
public double mutiply(double base, int e) {
double sum = 1;
for (int i = 0; i < e; i++) {
sum = sum * base;
}
return sum;
}
public boolean equal(double a, double b) {
if (a - b < 0.000001 && a - b > -0.000001) {
return true;
}
return false;
}
12.打印1到最大的n位数
思路:考虑大数问题,使用字符串或数组表示。
代码实现:
public void printToMaxOfNDigits(int n) {
int[] array=new int[n];
if(n <= 0)
return;
printArray(array, 0);
}
private void printArray(int[] array,int n) {
for(int i = 0; i < 10; i++) {
if(n != array.length) {
array[n] = i;
printArray(array, n+1);
} else {
boolean isFirstNo0 = false;
for(int j = 0; j < array.length; j++) {
if(array[j] != 0) {
System.out.print(array[j]);
if(!isFirstNo0)
isFirstNo0 = true;
} else {
if(isFirstNo0)
System.out.print(array[j]);
}
}
System.out.println();
return ;
}
}
}
13.O(1)时间删除链表节点
思路:将要删除节点的下一个节点的值赋给要删除的节点,然后指向下下一个节点
代码实现:
public void deleteNode(ListNode head, ListNode deListNode) {
if (deListNode == null || head == null)
return;
if (head == deListNode) {
head = null;
} else {
// 若删除节点是末尾节点,往后移一个
if (deListNode.nextNode == null) {
ListNode pointListNode = head;
while (pointListNode.nextNode.nextNode != null) {
pointListNode = pointListNode.nextNode;
}
pointListNode.nextNode = null;
} else {
deListNode.data = deListNode.nextNode.data;
deListNode.nextNode = deListNode.nextNode.nextNode;
}
}
}
14.输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变
思路:每次只和前面一个数交换位置。或者利用辅助数组
代码实现:
// 解法一:移动偶数位置,时间复杂度 O(n²),空间复杂度 O(1)
public void reOrderArray(int[] array) {
if (array == null || array.length == 0) {
return ;
}
for (int i = 1; i < array.length; i++) {
int j = i - 1;
if (array[i] % 2 != 0) {
while (j >= 0) {
if (array[j] % 2 != 0) {
break;
}
if (array[j] % 2 == 0) {
int t = array[j + 1];
array[j + 1] = array[j];
array[j] = t;
j--;
}
}
}
}
}
// 解法二:双指针法,时间复杂度 O(n),空间复杂度 O(1)
public void reOrderArray(int[] array) {
if (array == null || array.length == 0) {
return;
}
int left = 0;
int right = array.length - 1;
while (left < right) {
while (left < right && array[left] % 2 != 0) {
left++;
}
while (left < right && array[right] % 2 == 0) {
right--;
}
if (left < right) {
int tmp = array[left];
array[left] = array[right];
array[right] = tmp;
}
}
}
15.输入一个链表,输出该链表中倒数第k个结点。
扩展题:找中间节点,使用两个指针,一个走一步,一个走两步。找到中间节点
思路:定义一快一慢两个指针,快指针走K步,然后慢指针开始走,快指针到尾时,慢指针就找到了倒数第K个节点。
代码实现:
public ListNode FindKthToTail(ListNode head,int k) {
if (head == null || k <= 0) {
return null;
}
ListNode fast = head;
ListNode slow = head;
while(k-- > 1) {
if (fast.next != null)
fast = fast.next;
else
return null;
}
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
16.输入一个链表,反转链表后,输出链表的所有元素。
扩展题:输出反转后链表的头节点,定义三个指针反向输出。
思路:定义两个指针,反向输出
代码实现:
public ListNode ReverseList(ListNode head) {
if (head == null) {
return null;
}
ListNode temp = null;
while(head != null) {
ListNode p = head.next;
head.next = temp;
temp = head;
head = p;
}
return temp;
}
17.输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
思路:递归与非递归求解,小数放在前面。
代码实现:
public ListNode Merge(ListNode list1,ListNode list2) {
if (list1 == null) {
return list2;
}
if (list2 == null) {
return list1;
}
ListNode newHead = null;
if (list1.val <= list2.val) {
newHead = list1;
newHead.next = Merge(list1.next,list2);
}else {
newHead = list2;
newHead.next = Merge(list1,list2.next);
}
return newHead;
}
18.输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:若根节点相等,利用递归比较他们的子树是否相等,若根节点不相等,则利用递归分别在左右子树中查找。
代码实现:
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
boolean result = false;
if (root2 != null && root1 != null) {
if(root1.val == root2.val){
result = doesTree1HaveTree2(root1,root2);
}
if (!result)
return HasSubtree(root1.left,root2) || HasSubtree(root1.right,root2);
}
return result;
}
public boolean doesTree1HaveTree2(TreeNode node1, TreeNode node2) {
if (node2 == null) {
return true;
}
if (node1 == null) {
return false;
}
if (node1.val != node2.val) {
return false;
}
return doesTree1HaveTree2(node1.left,node2.left) &&
doesTree1HaveTree2(node1.right,node2.right);
}
19.操作给定的二叉树,将其变换为源二叉树的镜像。
思路:使用递归或非递归方式交换每个节点的左右子树位置。
代码实现:
public void Mirror(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
while (root != null || !stack.isEmpty()) {
while (root != null) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
stack.push(root);
root = root.left;
}
if (!stack.isEmpty()) {
root = stack.pop();
root = root.right;
}
}
}
20.输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
思路:终止行号大于起始行号,终止列号大于起始列号,
代码实现:
public ArrayList<Integer> printMatrix(int[][] matrix) {
ArrayList<Integer> list = new ArrayList<>();
if(matrix == null)
return list;
int start = 0;
while(matrix[0].length > start*2 && matrix.length > start*2) {
printOneCircle(matrix,start,list);
start++;
}
return list;
}
private void printOneCircle(int[][] matrix,int start,ArrayList<Integer> list) {
int endX = matrix[0].length - 1 - start; // 列
int endY = matrix.length - 1 - start; // 行
// 从左往右
for (int i = start; i <= endX; i++)
list.add(matrix[start][i]);
// 从上往下
if (start < endY) {
for (int i = start + 1; i <= endY; i++)
list.add(matrix[i][endX]);
}
// 从右往左(判断是否会重复打印)
if (start < endX && start < endY) {
for (int i = endX - 1; i >= start; i--)
list.add(matrix[endY][i]);
}
// 从下往上(判断是否会重复打印)
if (start < endX && start < endY - 1) {
for (int i = endY - 1; i >= start + 1; i--)
list.add(matrix[i][start]);
}
}
未完待续。。。。。