36.两个链表的第一个公共节点
题目描述
输入两个链表,找出它们的第一个公共结点。
思路:
我们的做法通常是找出两个链表的长度,然后让长的先走两个链表的长度差,然后再一起走(因为两个链表用公共的),可是我们真的需要知道长度吗?
看看另一种浪漫的解法:
走你来时走过的路,那么我们会在交叉路口突然的相遇.
package com.matajie;
/**
* 36.两个链表的第一个公共节点
* 题目描述
* 输入两个链表,找出它们的第一个公共结点。
*
* 我的程序才不会有bug!
* author:年仅18岁的天才少年程序员丶mata杰
**/
public class FindFirstCommonNode {
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while (p1 != p2){
p1 = (p1 == null) ? pHead2 : p1.next;
p2 = (p2 == null) ? pHead1 : p2.next;
}
return p1;
}
}
解释:
如果两个链表长度一样,并且公共点位置一样,那么会在第一个公共点位置退出,如果不一样,那么会在第二个公共点位置退出.如果没有公共点,那么最后一定同时等于null退出.
如图, m != n时,两者第二次到达公共点时走过的距离是m+s+n和n+s+m,所以第二次一定会相遇,如果没有公共点,那么最后在len1+len2位置一定会相遇,就是null.
37.数字在排序数组中出现的次数.
题目描述
统计一个数字在排序数组中出现的次数。
思路:看见有序,就用二分!
package com.matajie;
/**
* 37.数字在排序数组中出现的次数
* 题目描述
* 统计一个数字在排序数组中出现的次数。
*
* 我的程序才不会有bug!
* author:年仅18岁的天才少年程序员丶mata杰
**/
public class GetNumberOfK {
public int GetNumberOfK(int [] array , int k) {
int length = array.length;
if(length == 0) return 0;
int firstK = getFirstK(array,k,0,length-1);
int lastK = getLastK(array,k,0,length-1);
if(firstK != -1 && lastK != -1){
return lastK-firstK+1;
}
return 0;
}
private int getFirstK(int[] array,int k ,int start,int end){
if(start>end){
return -1;
}
int mid = (start+end)>>1;
if(array[mid]>k){
return getFirstK(array,k,start,mid-1);
}else if(array[mid] < k){
return getFirstK(array,k,mid+1,end);
}else if(mid-1 >= 0 && array[mid-1] == k){
return getFirstK(array,k,start,mid-1);
}else {
return mid;
}
}
private int getLastK(int[] array,int k,int start,int end){
int length = array.length;
int mid = (start+end)>>1;
while (start<=end){
if(array[mid] > k){
end = mid-1;
}else if(array[mid]<k){
start = mid+1;
}else if(mid+1 < length && array[mid+1] == k){
start = mid+1;
}else {
return mid;
}
mid = (start+end)>>1;
}
return -1;
}
}
38.二叉树的深度
题目描述
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
package com.matajie;
/**
* 38.二叉树的深度
* 题目描述
* 输入一棵二叉树,求该树的深度。
* 从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
*
* 我的程序才不会有bug!
* author:年仅18岁的天才少年程序员丶mata杰
**/
public class TreeDepth {
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
public int TreeDepth(TreeNode root) {
if(root == null) return 0;//空节点返回0
return Math.max(1+TreeDepth(root.left),1+TreeDepth(root.right));//原树的深度由左右子树中深度较深的加1
}
}
39.平衡二叉树
题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
思路
如果遍历每个节点,借助一个获取数深度的递归函数,根据该节点的左右左右子树高度差判断是否平衡,然后递归的对左右子树进行判断的话,这种方法在判断上层节点的时候会多次重复遍历下层节点,增加不必要的开销.
可以改为从下往上遍历,如果子树是平衡二叉树,则返回子树的高度,如果发现子树不是平衡二叉树,则直接听之便利,这样至多只对每个节点访问一次.
package com.matajie;
/**
* 39.平衡二叉树
*
*
* 我的程序才不会有bug!
* author:年仅18岁的天才少年程序员丶mata杰
**/
public class IsBalanced_Solution {
public boolean IsBalanced_Solution(TreeNode root) {
return getDepth(root) != -1;
}
private int getDepth(TreeNode root){
if(root == null) return 0;
int left = getDepth(root.left);
if(left == -1)return -1;
int right = getDepth(root.right);
if(right == -1)return -1;
return Math.abs(left-right)>1?-1:1+Math.max(left,right);
}
}
40.数组中只出现一次的数字
题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
思路:
a^ b^ a = b,所以问题就变成了把一个包含两个出现一次数字的数组array拆分成两个出现一次数组array1和array2的问题,怎么分呢?假设数组为a,a,b,b,c,c,d,e,依次异或,最后的结果是d^ e,那么d ^ e的第n位为1,也就意味着d和e的第n位肯定不同,所以可按照这个条件拆分数组d和e肯定会被分开.
package com.matajie;
/**
* 40.数组中只出现一次的数字
* 题目描述
* 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
*
* 我的程序才不会有bug!
* author:年仅18岁的天才少年程序员丶mata杰
**/
public class FindNumsAppearOnce {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array == null || array.length <2) return;
int temp = 0;
for(int i = 0;i<array.length;i++)
temp ^= array[i];
int indexOf1 = findFirstBitls(temp);
for(int i = 0;i<array.length;i++)
if(isBit(array[i],indexOf1)){
num1[0]^=array[i];
}else {
num2[0]^=array[i];
}
}
public int findFirstBitls(int num){
int indexBit = 0;
while (((num&1)==0)&&(indexBit)<8*4){
num = num>>1;
++indexBit;
}
return indexBit;
}
public boolean isBit(int num,int indexBit){
num = num>>indexBit;
return (num & 1 )== 1;
}
}
扩展:
数组中只有一个数出现一次,其他书都出现了2次,找出这个数字?
package com.matajie;
/**
* 数组中只有一个数出现一次,其他书都出现了2次,找出这个数字?
*
* 我的程序才不会有bug!
* author:年仅18岁的天才少年程序员丶mata杰
**/
public class Find1From2 {
public int find1From2(int[] a){
int len = a.length;
int res = 0;
for(int i = 0;i<a.length;i++){
res ^= a[i];
}
return res;
}
}
数组中只有一个数出现一次,其他数字都出现了3次,找出这个数字?
package com.matajie;
/**
* 数组中只有一个数出现一次,其他数字都出现了3次,找出这个数字?
*
* 我的程序才不会有bug!
* author:年仅18岁的天才少年程序员丶mata杰
**/
public class Find1From3 {
public int find1From3(int[] a){
int[] bits = new int[32];
int len = a.length;
for(int i = 0;i<len;i++){
for(int j = 0;j<len;j++){
bits[j] = bits[j]+((a[i]>>>j)&1);
}
}
int res = 0;
for(int i = 0;i<32;i++){
if(bits[i] % 3 !=0){
res |= 1<<i;
}
}
return res;
}
}