36、两个链表第一个公共节点
题目描述
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
思路:
对于两个这样的序列:
0-1-2-3-4-5-null
a-b-4-5-null
他们的公共点后的长度必定是相同的。
也就是说4-5-null
这后两个节点是共同的。
那么可以这么推理:
0-1-2-3-4-5-null a-b-4-5-null
和a-b-4-5-null 0-1-2-3-4-5-null
的长度是相同的,且他们的节点都是4-5-null
,且到这个公共节点的最后一个节点的距离相同,都是第九个。
链接:https://www.nowcoder.com/questionTerminal/6ab1d9a29e88450685099d45c9e31e46?answerType=1&f=discussion
来源:牛客网
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) return null;
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
if (p1 != p2 && p1 == null) {
p1 = pHead2;
}
if (p1 != p2 && p2 == null) {
p2 = pHead1;
}
}
return p1;
}
37、统计一个数字在升序数组中出现的次数
题目描述:
统计一个数字在升序数组中出现的次数。
显然是利用二分查找。因为有序,所以目标值target如果有多个,肯定是连在一起。又已知我们可以在有序数组中查找任意一个值,因此我们可以先查找目标范围的下界和上界。
下界定义为:如果存在目标值,则指向第一个目标值,否则,如果不存在, 则指向大于目标值的第一个值。
上界定义为:不管目标值存在与否,都指向大于目标值的第一个值。
package M36TO40;
public class SoluGetNumberOfK {
public int GetNumberOfK(int [] array , int k) {
if (array ==null || array.length==0) return 0;
int lowIndex = lowerBound(array,k);
int upperIndex = upperBound(array,k);
return upperIndex-lowIndex;
}
//这里左边界和右边界,关键是看当等于target时,是l = mid + 1还是r = mid-1
private int upperBound(int[] array,int val){
int l = 0,r = array.length-1,mid;
while (l<=r){
mid = (l+r)/2;
//要找的值比中间值大则,值位于中间点右边,l= mid +1;,直到找到大于val的第一个值
if (array[mid]<=val){
l = mid + 1;
//要找的值比中间值小则,值位于中间点左边,r= mid-1;
}else{
r = mid-1;
}
}
return l;
}
private int lowerBound(int[] array,int val){
int l = 0,r = array.length-1,mid;
while (l<=r){
mid=(l+r)/2;
//与上面的区别是,即使相等也向右找知道找最小的val的值
if (array[mid]<val){
l = mid +1;
}else{
r = mid-1;
}
}
return l;
}
}
38、二叉树的深度
题目描述
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
package M36TO40;
import M16TO20.TreeNode;
import java.util.LinkedList;
import java.util.Queue;
public class SoluTreeDepth {
public int TreeDepth(TreeNode root){
if (root == null) return 0;
//用层次遍历(广度优先遍历)
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int depth = 0;
while (!queue.isEmpty()){
for (int i = 0;i< queue.size();i++){
TreeNode node = queue.poll();
if (node.left !=null) queue.offer(node.left);
if (node.right !=null) queue.offer(node.right);
}
depth++;
}
return depth;
}
}
class Solution {
public int maxDepth(TreeNode root) {
if(root==null) return 0;
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left,right)+1;
}
}
39、平衡二叉树
题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
///二
class Solution {
public boolean isBalanced(TreeNode root) {
if(root==null)
return true;
if(dfs(root)<0){
return false;
}else{
return true;
}
}
public int dfs(TreeNode root){
if(root==null)
return 0;
int left=dfs(root.left);
int right=dfs(root.right);
if(left<-1||right<-1||Math.abs(left-right)>1){
return -2;
}
return Math.max(left,right)+1;
}
}
/
package M36TO40;
import M16TO20.TreeNode;
public class SoluIsBalanced_Solution {
public int depth(TreeNode root){
if (root==null) return 0;
int left = depth(root.left);
if (left==-1) return -1;//如果发现子树不平衡之后就没有必要进行下面的高度的求解了
int right = depth(root.right);
if (right==-1) return -1;//如果发现子树不平衡之后就没有必要进行下面的高度的求解了
//left,right初始化都是0
if (Math.abs(left-right)>1) return -1;
else{
return 1+(left>right ?left:right);
}
}
public boolean IsBalanced_Solution(TreeNode root){
return depth(root) !=-1;
}
}
40、数组中只出现一次的数
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
用的map
package M36TO40;
import java.util.HashMap;
public class SoluFindNumsAppearOnce {
public void FindNumsAppearOnce(int[] array,int num1[],int num2[]) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < array.length; i++) {
if (map.containsKey(array[i])) {
map.put(array[i], 2);
} else {
map.put(array[i], 1);
}
}
int count = 0;
for (int i=0;i<array.length;i++){
if (map.get(array[i])==1){
if (count==0){
num1[0] = array[i];
count++;
}else{
num2[0] = array[i];
}
}
}
}
}
用亦或的:
class Solution {
public int[] singleNumbers(int[] nums) {
//假设a b只出现一次
//先求出 a^b
int mid=nums[0];
for(int i=1;i<nums.length;i++){
mid ^=nums[i];
}
//a^b 找到值的最后一个1
//则 a b两个值的二进制在这一个位置是一定一个是0一个是1
mid -= mid&(mid-1);
int[] res = new int[2];
for(int i=0;i<nums.length;i++){
//数组可以分为两组[a x1 x2 x3...] [b x4 x5 x6...]
//一组中对应二进制为1的位置上的数为0 一组为1,然后组内进行异或运算,这最后分别剩下 a b
if((mid&nums[i])==0){
res[0] ^=nums[i];
}else{
res[1] ^=nums[i];
}
}
if (res[0] > res[1]) {
int temp = res[0];
res[0] = res[1];
res[1] = temp;
}
return res;
}
}