文章目錄
-
- 36、兩個連結清單第一個公共節點
- 37、統計一個數字在升序數組中出現的次數
- 38、二叉樹的深度
- 39、平衡二叉樹
- 40、數組中隻出現一次的數
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;
}
}
39、平衡二叉樹
題目描述
輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。
在這裡,我們隻需要考慮其平衡性,不需要考慮其是不是排序二叉樹
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;
}
}
///二
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;
}
}
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;
}
}