劍指offer 36-40

36.兩個(gè)鏈表的第一個(gè)公共結(jié)點(diǎn)

輸入兩個(gè)鏈表茁影,找出它們的第一個(gè)公共結(jié)點(diǎn)薪韩。

拿到這個(gè)題确沸,試想一下捌锭,如果兩個(gè)鏈表的長度一樣,應(yīng)該怎么做罗捎,當(dāng)然就是兩個(gè)鏈表從頭結(jié)點(diǎn)開始同時(shí)往后遍歷观谦,找到第一個(gè)相同的結(jié)點(diǎn)即可。
那么上升到更一般的情況下桨菜,兩個(gè)鏈表長度不相等豁状,應(yīng)該怎么做,單向鏈表是不可逆的倒得,因此我們沒法從后往前找第一個(gè)公共結(jié)點(diǎn)泻红。我們可以仿照兩個(gè)鏈表長度相同到的情況下進(jìn)行求解,怎么讓兩個(gè)鏈表長度相同呢霞掺,就是分別求出兩個(gè)鏈表的長度谊路,然后讓長的那個(gè)鏈表先往后走兩個(gè)鏈表之間的差值的長度即可。
代碼如下

public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if(pHead1==null||pHead2==null){
            return null;
        }
        ListNode cur1 = pHead1;
        ListNode cur2 = pHead2;
        //用兩個(gè)數(shù)字分別記錄兩個(gè)鏈表的長度
        int cnt1 = 0,cnt2 = 0;
        while(cur1!=null){
            cnt1++;
            cur1 = cur1.next;
        }
        while(cur2!=null){
            cnt2++;
            cur2 = cur2.next;
        }
        cur1 = pHead1;
        cur2 = pHead2;
        //如果鏈表1長菩彬,就讓鏈表1走cnt1-cnt2的長度
        //如果鏈表2長缠劝,就讓鏈表2走cnt2-cnt1的長度
        int cnt = 0;
        if(cnt1<cnt2){
            while(cnt<cnt2-cnt1){
                cur2 = cur2.next;
                cnt++;
            }
        }else{
            while(cnt<cnt1-cnt2){
                cur1 = cur1.next;
                cnt++;
            }
        }
        //兩個(gè)鏈表的指針同時(shí)向后走,碰到第一個(gè)相等的結(jié)點(diǎn)就是第一個(gè)公共結(jié)點(diǎn)
        while(cur1!=null&&cur2!=null){
            if(cur1==cur2){
                return cur1;
            }else{
                cur1 = cur1.next;
                cur2 = cur2.next;
            }
        }
        return null;
        
    }
}

37.數(shù)字在排序數(shù)組中出現(xiàn)的次數(shù)

統(tǒng)計(jì)一個(gè)數(shù)字在排序數(shù)組中出現(xiàn)的次數(shù)骗灶。

最簡單直觀的方法當(dāng)然是按順序統(tǒng)計(jì)惨恭,這樣的時(shí)間復(fù)雜度是O(n)
代碼如下

public class Solution {
    //private int cnt = 0;
    public int GetNumberOfK(int [] array , int k) {
        if(array.length<=0){
            return 0;
        }
        int cnt = 0;
        for(int num:array){
            cnt = num==k?cnt+1:cnt;
        }
        return cnt;
    }
}

但是既然題目中已經(jīng)給了排序這個(gè)信息,我們就應(yīng)該利用好排序這個(gè)信息矿卑,即用BinarySearch進(jìn)行尋找第一個(gè)K出現(xiàn)的位置和第一個(gè)大于K的數(shù)出現(xiàn)的位置喉恋。
在使用二分查找的時(shí)候,我們需要明白幾點(diǎn):
1.二分查找的原理就是"逼近"母廷,當(dāng)mid指向的數(shù)大于等于target時(shí)隆豹,證明target在前半段數(shù)組中筏勒;反之target在后半段數(shù)組中,直到低位指針與高位指針重合熬北;
2.如果我們要找的數(shù)不在數(shù)組中嚎京,可能存在兩種情況

1.target夾在數(shù)組中間,例如target=4,array={1,3,5,7,9}业舍;這種情況下試想抖拦,
我們通過逼近的方法可以“知道”4在3的后面,而7,9顯然是大于4的舷暮,所以最后夾在中間的只有5
這里可以延伸為我們在數(shù)組中尋找target時(shí)态罪,如果target不存在,則會(huì)找到第一個(gè)大于target的數(shù)下面;
2.target大于數(shù)組中全部的數(shù)复颈,例如target=6,array={1,2,3,4,5}沥割,
我們最好在寫代碼的時(shí)候就將high定義為array.length耗啦,這樣通過逼近的方法凿菩,最后l和h重疊的時(shí)候就出界了,這樣方便判斷帜讲;

根據(jù)以上可以寫出如下流程的代碼

1.對(duì)target進(jìn)行二分查找衅谷,找到target出現(xiàn)的第一個(gè)位置;
2.對(duì)target+1進(jìn)行二分查找似将,這里的意思是找到第一個(gè)大于等于target+1的元素获黔,類似于放縮發(fā)也就找到了第一個(gè)大于target的元素;
3.對(duì)l進(jìn)行判斷是不是上面提到的兩種不存在的情況玩郊,對(duì)于第一種情況需要判斷array[first]和k是否相等肢执,對(duì)于第二種情況需要判斷first是否出界了,滿足以上兩者之一的译红,都需要判定target不存在數(shù)組中,返回0.

代碼如下

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        if(array.length<=0){
            return 0;
        }
        //對(duì)k進(jìn)行二分查找兴溜,找到k第一次出現(xiàn)的位置
        int first = binarysearch(array,k);
        //對(duì)k+1進(jìn)行二分查找侦厚,找到大于等于K+1的數(shù),即大于K的數(shù)第一次出現(xiàn)的位置拙徽;
        int last = binarysearch(array,k+1);
        //滿足target夾在數(shù)組中某兩個(gè)數(shù)中間或target大于數(shù)組中全部數(shù)情況之一的刨沦,需要返回0
        return (first==array.length||array[first]!=k)?0:last-first;
    }
    //定義簡單二分查找函數(shù)
    private int binarysearch(int [] array,int k){
        int l = 0,h = array.length;
        while(l<h){
            int m = (l+h)/2;
            if(array[m]>=k){
                h = m;
            }else{
                l = m+1;
            }
        }
        return l;
        
    }
}

二叉樹的深度

輸入一棵二叉樹,求該樹的深度膘怕。
從根結(jié)點(diǎn)到葉結(jié)點(diǎn)依次經(jīng)過的結(jié)點(diǎn)(含根想诅、葉結(jié)點(diǎn))形成樹的一條路徑,最長路徑的長度為樹的深度岛心。

這個(gè)題思路倒是簡單来破,就用一個(gè)變量來保存當(dāng)前最大深度,
然后用深度遍歷的方法統(tǒng)計(jì)各條路線的長度忘古,然后與這個(gè)最大深度進(jìn)行比較取大者徘禁,最后輸出最大值。
代碼如下

public class Solution {
    private int depth = 0;
    public int TreeDepth(TreeNode root) {
        if(root==null){
            return 0;
        }
        //這里要注意不要采坑K杩啊K椭臁!
        //我們往下進(jìn)行遞歸的時(shí)候會(huì)使計(jì)數(shù)+1
        //以單個(gè)根節(jié)點(diǎn)為例干旁,左右結(jié)點(diǎn)為空驶沼,但是計(jì)數(shù)+1了,層數(shù)為0+1=1,這才是符合實(shí)際情況到的
        //所以在入口的時(shí)候傳遞的初始層數(shù)應(yīng)該為0
        find_depth(root,0);
        return depth;
    }
    //對(duì)二叉樹進(jìn)行深度遍歷
    public void find_depth(TreeNode root,int cnt){
        //當(dāng)遞歸到結(jié)點(diǎn)為null的時(shí)候争群,將當(dāng)前的cnt與depth進(jìn)行比較取大者
        if(root==null){
            depth = cnt>depth?cnt:depth;
            return;
        }
        //對(duì)左右子樹進(jìn)行遞歸處理
        find_depth(root.left,cnt+1);
        find_depth(root.right,cnt+1);
    }
}

39.平衡二叉樹

輸入一棵二叉樹回怜,判斷該二叉樹是否是平衡二叉樹。

這個(gè)題的思路還是判斷左右子樹的高度差是否小于1祭阀,我們可以采用這樣的方式鹉戚,即初始化一個(gè)布爾變量為true,全局中只要出現(xiàn)一個(gè)位置不滿足平衡二叉樹的條件鲜戒,就會(huì)使這個(gè)變量被賦值為false,如果全局都滿足平衡二叉樹抹凳,最后的輸出也就是true;同時(shí)遏餐,在計(jì)算樹的深度的時(shí)候要學(xué)會(huì)通過遞歸返回值,具體步驟如下

1.初始化一個(gè)全局布爾變量boolean res = true赢底;
2.構(gòu)建一個(gè)整型返回值的函數(shù)用來計(jì)算樹的高度失都,注意這個(gè)函數(shù)既承擔(dān)了在遞歸中不斷計(jì)算樹的深度的任務(wù),又承擔(dān)著判斷各子樹是否為平衡二叉樹幸冻,當(dāng)然只要判定一次不為平衡二叉樹粹庞,其它也就無所謂了。

有了這個(gè)思路洽损,代碼如下

public class Solution {
    //初始化一個(gè)全局布爾變量
    private boolean res = true;
    public boolean IsBalanced_Solution(TreeNode root) {
        //height函數(shù)無需返回值庞溜,因?yàn)橹恍枰诋?dāng)中判定res是否會(huì)變成false即可
        height(root);
        return res;
    }
    private int height(TreeNode root){
        //如果結(jié)點(diǎn)為空則返回0,這既是對(duì)根節(jié)點(diǎn)的判定碑定,也是一個(gè)遞歸計(jì)算深度的初始值
        if(root==null){
            return 0;
        }
        //對(duì)左右子樹進(jìn)行遞歸
        int left = height(root.left);
        int right = height(root.right);
        if(Math.abs(left-right)>1){
            res = false;
        }
        //這里承擔(dān)著一層層往上遞歸樹的深度的任務(wù)
        //可以這樣看流码,root的深度是多少?是1加上左子樹的深度和右子樹的深度中的大者
        //那么左子樹深度left和右子樹深度right是多少呢延刘?
        //就是又要用到這個(gè)height函數(shù)來求解了漫试,left = height(root.left);right=height(root.right);
        //當(dāng)遞歸到葉子結(jié)點(diǎn)的時(shí)候,可以看到左右都為null碘赖,即葉子結(jié)點(diǎn)的深度為1驾荣,這也是一層層往上遞歸的
        return 1+Math.max(left,right);
    }
}

40.數(shù)組中只出現(xiàn)一次的數(shù)字

一個(gè)整型數(shù)組里除了兩個(gè)數(shù)字之外,其他的數(shù)字都出現(xiàn)了兩次普泡。請(qǐng)寫程序找出這兩個(gè)只出現(xiàn)一次的數(shù)字播掷。

之前做的簡單難度的是找出一個(gè)只出現(xiàn)一次的數(shù)字,這次要找兩個(gè)劫哼,要學(xué)會(huì)將復(fù)雜問題拆分成簡單的子問題來求解叮趴,如果我們能根據(jù)某些特征將這些數(shù)字分成兩組,第一組只包含第一個(gè)數(shù)权烧,第二組只包含第二個(gè)數(shù)眯亦,然后再用只出現(xiàn)一次的一個(gè)數(shù)這個(gè)思路來求解不就行了嗎?
假設(shè)這兩個(gè)只出現(xiàn)一次的數(shù)為a,b我們對(duì)數(shù)組中所有的數(shù)求異或般码,最后得到的結(jié)果就是a^b妻率,異或異或顧明思意這個(gè)結(jié)果肯定會(huì)包含1,因?yàn)閍,b肯定是不相等板祝,我們找到第一個(gè)為1的位宫静,例如00100這個(gè)數(shù),整個(gè)數(shù)組就被劃分成兩個(gè)部分了,1.該位為1孤里;2該位不為1伏伯;
該位為1的數(shù)與上00100肯定不為0,該位為0的數(shù)與上00100肯定為0
按照這個(gè)思路,流程如下

1.求出這兩個(gè)數(shù)相異或的結(jié)果
2.求出這個(gè)結(jié)果中第一位為1的這個(gè)數(shù)
3.根據(jù)這個(gè)判定條件捌袜,分別不同條件下的數(shù)不斷求異或運(yùn)算说搅,得到最終的兩個(gè)數(shù)

代碼如下

//num1,num2分別為長度為1的數(shù)組。傳出參數(shù)
//將num1[0],num2[0]設(shè)置為返回結(jié)果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        int diff = 0;
        for(int num:array){
            diff ^= num;
        }
        //找到第一個(gè)不為1的數(shù)
        //負(fù)數(shù)的二進(jìn)制是取反加1
        //以diff=10100為例虏等,-diff = 01011+1=01100
        //10100&01100=00100弄唧,正好就是我要求的
        diff &= -diff;
        for(int num:array){
            //這里就是分為了兩個(gè)元素區(qū),第一個(gè)為在該位上為0霍衫,則與diff后全部為0,我們異或所有的這些數(shù)即可
            //相反得到到的就是另外一個(gè)數(shù)
            if((num&diff)==0){
                num1[0] ^=num;
            }else{
                num2[0] ^=num;
            }
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末候引,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子敦跌,更是在濱河造成了極大的恐慌澄干,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件峰髓,死亡現(xiàn)場離奇詭異傻寂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)携兵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搂誉,“玉大人徐紧,你說我怎么就攤上這事√堪茫” “怎么了并级?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長侮腹。 經(jīng)常有香客問我嘲碧,道長,這世上最難降的妖魔是什么父阻? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任愈涩,我火速辦了婚禮,結(jié)果婚禮上加矛,老公的妹妹穿的比我還像新娘履婉。我一直安慰自己,他們只是感情好斟览,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布毁腿。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪已烤。 梳的紋絲不亂的頭發(fā)上鸠窗,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音胯究,去河邊找鬼稍计。 笑死,一個(gè)胖子當(dāng)著我的面吹牛唐片,可吹牛的內(nèi)容都是我干的丙猬。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼费韭,長吁一口氣:“原來是場噩夢啊……” “哼茧球!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起星持,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤抢埋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后督暂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揪垄,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年逻翁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饥努。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡八回,死狀恐怖酷愧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缠诅,我是刑警寧澤溶浴,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站管引,受9級(jí)特大地震影響士败,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜褥伴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一谅将、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧噩翠,春花似錦戏自、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽志衣。三九已至,卻和暖如春猛们,著一層夾襖步出監(jiān)牢的瞬間念脯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國打工弯淘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绿店,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓庐橙,卻偏偏與公主長得像假勿,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子态鳖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 基本概念 鏈表的含義: 鏈表是一種用于存儲(chǔ)數(shù)據(jù)集合的數(shù)據(jù)結(jié)構(gòu)转培,具有以下屬性 相鄰元素之間通過指針相連 最后一個(gè)元素...
    古劍誅仙閱讀 1,010評(píng)論 0 3
  • 1. 找出數(shù)組中重復(fù)的數(shù)字 題目:在一個(gè)長度為n的數(shù)組里的所有數(shù)字都在0到n-1的范圍內(nèi)。數(shù)組中某些數(shù)字是重復(fù)的浆竭,...
    BookThief閱讀 1,777評(píng)論 0 2
  • 鏈表 記錄《劍指offer》中所有關(guān)于鏈表的題目浸须,以及LeetCode中的相似題目 相關(guān)題目列表 題目 鏈表是面試...
    wenmingxing閱讀 1,172評(píng)論 0 11
  • 大學(xué)的時(shí)候不好好學(xué)習(xí),老師在講臺(tái)上講課邦泄,自己在以為老師看不到的座位看小說删窒,現(xiàn)在用到了老師講的知識(shí),只能自己看書查資...
    和玨貓閱讀 1,447評(píng)論 1 3
  • 轉(zhuǎn)載請(qǐng)注明出處:http://www.reibang.com/p/c65d9d753c31 在上一篇博客《數(shù)據(jù)結(jié)構(gòu)...
    Alent閱讀 3,516評(píng)論 4 74