剑指offer之36-40题解
目录
36. 两个链表的第一个公共结点
(一)题目描述
输入两个链表,找出它们的第一个公共结点。
(二)思路
- 设A的长度为a+c,B的长度为b+c,其中c为尾部公共部分的长度,可知a+c+b = b+c+a.
- 当访问链表A的指针访问到链表尾部时,令它从链表B的头部重新开始访问链表B;同样的,当访问链表B的指针访问到链表尾部时,令它从链表A的头部重新开始访问链表A。这样就能控制访问A和B两个链表的指针同时访问到交点。
(三)代码实现
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode l1 = pHead1, l2 = pHead2;
while (l1 != l2) {
l1 = (l1 == null) ? pHead2 : l1.next;
l2 = (l2 == null) ? pHead1 : l2.next;
}
return l1;
}
}
37. 数字在排序数组中出现的次数
(一)题目描述
统计一个数字在排序数组中出现的次数。
(二)思路
(三)代码实现
代码实现一:
public class Solution {
public int GetNumberOfK(int[] array, int k) {
int first = binarySearch(array, k);
int last = binarySearch(array, k + 1);
return (first == array.length || array[first] != k) ? 0 : last - first;
}
private int binarySearch(int[] array, int k) {
int l = 0, h = array.length;
while (l < h) {
int m = l + (h - l) / 2;
if (array[m] >= k)
h = m;
else
l = m + 1;
}
return l;
}
}
代码实现二
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int count = 0;
for (int i = 0; i < array.length; i++) {
if (array[i]==k){
count++;
}
}
return count;
}
}
38. 二叉树的深度
(一)题目描述
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
(二)思路
- 递归遍历即可。
(三)代码实现
public class Solution {
public int TreeDepth(TreeNode root) {
return root == null ? 0 : 1 + Math.max(TreeDepth(root.left), TreeDepth(root.right));
}
}
39. 平衡二叉树
(一)题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
(二)思路
- 利用递归求出左子树和右子树的最高,如果相减的绝对值大于1,那么不是平衡二叉树,否则是平衡二叉树。
(三)代码实现
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
if (root == null)
return true;
int left = height(root.left);
int right = height(root.right);
if (Math.abs(left - right) > 1)
return false;
return true;
}
private int height(TreeNode root) {
return root == null ? 0 : 1 + Math.max(height(root.left), height(root.right));
}
}
40. 数组中只出现一次的数字
(一)题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
(二)思路
-
除了有两个数字只出现了一次,其他数字都出现了两次。异或运算中,任何一个数字和自己本身异或都是0,任何一个数字和0异或都是本身。
-
两个不相等的元素在位级表示上必定会有一位存在不同,将数组所有元素异或得到的结果为不存在重复的两个元素异或的结果。
-
diff &= -diff得到出diff最右侧不为0的位,也就是不存在重复的两个元素在位级上最右侧的那一位,利用这一位就可以将两个元素区分开来。
-
例如:数组元素为2,4,3,6,3,2,5,5,异或的结果为0010,也就是倒数第二位为1,也就是倒数第二位为标记位来进行拆分,那么第一个子数组就为{2,3,6,3,2},他们的倒数第二位为1,第二个子数组为{4,5,5}倒数第二位为0,对这两个子数组分别再异或,最终找到6和4。
(三)代码实现
public class Solution {
public void FindNumsAppearOnce(int[] array, int num1[], int num2[]) {
int diff = 0;
for (int num : array)
diff ^= num;
diff &= -diff;
for (int num : array) {
if ((num & diff) == 0)
num1[0] ^= num;
else
num2[0] ^= num;
}
}
}