剑指offer面试题笔记11~20题(Java实现)
一、面试题11:数值的整数次方(P90)
题目:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,不需要考虑大数问题。
解题思路:
二、面试题12:打印1到最大的n位数(P94)
题目:输入数字n,按顺序打印出从1到最大的n为十进制数。比如输入3,则打印出1,2,3一直到999。
解题思路:
三、面试题13:在O(1)时间删除链表结点(P99)
题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数的定义如下:
struct ListNode { int m_nValue; ListNode* m_pNext }; void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted);
解题思路:获取待删除结点的下一个结点,将下一个结点的内容复制到需要删除的结点上覆盖原有的内容,再把下一个结点删除。若待删除结点是链表最后一个节点则需要从头到尾遍历。若链表中只有一个结点,删除结点后,还需要把链表的头结点设置为null。
public class T13 { public static void deleteNode (ListNode head, ListNode toDelete) { if (head == null || toDelete == null) return; if (toDelete.next != null) { ListNode next = toDelete.next; toDelete.value = next.value; toDelete.next = next.next; next = null; } else if (head == toDelete) { head = null; toDelete = null; } else { ListNode node = head; while (node.next != toDelete) { node = node.next; } node.next = null; toDelete = null; } } }
四、面试题14:调整数组顺序使奇数位于偶数前面(P102)
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
解题思路:定义两个指针,一个从前往后,一个从后往前,前面指针若指向的是奇数,则向后移动,直到遇到偶数为止;后面指针若指向偶数,则向前移动,直到遇到奇数为止。当后面指针最终到前面指针之前时,终止。
public class T14 { public static void reorderOddEven (int[] num, int length) { if (num == null || length == 0) return; int begin = 0; int end = length - 1; while (begin < end) { while (num[begin] % 2 == 1) begin ++; while (num[end] % 2 == 0) end --; if (begin < end) { int temp = num[begin]; num[begin] = num[end]; num[end] = temp; } } } }
五、面试题15:链表中倒数第K个结点(P107)
题目:输入一个链表,输出该链表中倒数第K个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第一个结点。
链表结点定义如下:
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
}
解题思路:定义两个指针,第一个指针从链表的头指针开始遍历向前走k-1,第二个指针保持不动;从第k步开始,第二个指针也开始从链表头指针开始遍历。由于两个指针距离保持在k-1,当第一个指针到达链表尾结点时,第二个指针正好是倒数第k个结点。
public class T15 { public static ListNode findKthToTail (ListNode node, int k) { ListNode ahead = node; ListNode behind = null; for (int i = 0; i < k - 1; i ++) ahead = ahead.next; behind = node; while (ahead.next != null) { ahead = ahead.next; behind = behind.next; } return behind; } }
六、面试题16:反转链表(P112)
题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。链表结点定义如下:
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
}
解题思路:
七、面试题17:合并两个排序的链表(P114)
题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
}
解题思路:两个链表两个指针,链表值小的结点为头结点。指针后移,递归。
public static ListNode merge (ListNode head1, ListNode head2) { if (head1 == null) return head2; if (head2 == null) return head1; ListNode mergeHead = null; if (head1.value < head2.value) { mergeHead = head1; mergeHead.next = merge (head1.next, head2); } else { mergeHead = head2; mergeHead.next = merge (head1, head2.next); } return mergeHead; }
八、面试题18:树的子结构(P117)
题目:输入两棵二叉树A和B,判断B是不是A的子结构。二叉树结点定义如下:
struct BinaryTreeNode { int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight; }
解题思路:第一步在树A中查找与根结点的值一样的结点,实际上就是树的遍历。第二部是判断树A中以R为根结点的子树是不是和树B具有相同的结构。递归的终止条件是我们到达了树A或者树B的叶结点。
public static boolean hasSubTree (BinaryTreeNode root1, BinaryTreeNode root2) { boolean result = false; if (root1 != null && root2 != null) { if (root1.value == root2.value) result = doesTree1HaveTree2 (root1, root2); if (!result) result = hasSubTree (root1.left, root2); if (!result) result = hasSubTree (root1.right, root2); } return result; } public static boolean doesTree1HaveTree2 (BinaryTreeNode root1, BinaryTreeNode root2) { if (root2 == null) return true; if (root1 == null) return false; return doesTree1HaveTree2 (root2.left, root2.left) && doesTree1HaveTree2 (root1.right, root2.right); }
九、面试题19:二叉树的镜像(P125)
题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。
二叉树结点的定义如下:
struct BinaryTreeNode { int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight; }
解题思路:先前序遍历这棵树的每个结点,如果遍历到的结点有子结点,就交换它的两个子结点。当交换完所有非叶子节点的左右子结点之后,就得到了树的镜像。
public static void mirrorRecursively (BinaryTreeNode node) { if (node == null || node.left == null || node.right == null) return; BinaryTreeNode temp = node.left; node.left = node.right; node.right = temp; if (node.left != null) mirrorRecursively(node.left); if (node.right != null) mirrorRecursively(node.right); }
十、面试题20:顺时针打印矩阵(P127)
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵:
| 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
解题思路:
浙公网安备 33010602011771号