日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面试准备系列01----面试中的链表题目汇总

發(fā)布時間:2025/3/13 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试准备系列01----面试中的链表题目汇总 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?面試準備系列01----面試中的鏈表題目匯總

? ? ?九月份立即就要校招了,感覺時間非常是捉急啊~~~~白天要實習(xí),就僅僅能晚上熬夜來準備基礎(chǔ)知識和寫博客了。此篇博文是面試準備系列的第一篇,隨后會持續(xù)更新02,03......下面是常見的關(guān)于鏈表的面試題目,題目差點兒都來自LeetCode 或者 劍橋offer,也借鑒了不少網(wǎng)上的答案,感謝感謝~~

1.鏈表長度
2.得到鏈表倒數(shù)第k個節(jié)點的值?3.刪除鏈表的倒數(shù)第k個節(jié)點
4.求單鏈表的中間節(jié)點
5.推斷鏈表是否有環(huán)
6.找出有環(huán)鏈表的環(huán)的入口
7.推斷兩個單鏈表是否相交
8.找出兩個相交鏈表的第一個交點

9.從尾到頭打印單鏈表

10.逆置單鏈表

11.合并兩個有序鏈表,使合并后的鏈表依舊有序

12.在o(1)的時間復(fù)雜度刪除單鏈表中指定的某一節(jié)點

package com.sheepmu;import java.util.Stack;/*** 1.鏈表長度* 2.得到鏈表倒數(shù)第k個節(jié)點的值* 3.刪除鏈表的倒數(shù)第k個節(jié)點* 4.求單鏈表的中間節(jié)點* 5.推斷鏈表是否有環(huán)* 6.找出有環(huán)鏈表的環(huán)的入口* 7.推斷兩個單鏈表是否相交* 8.找出兩個相交鏈表的第一個交點* 9.從尾到頭打印單鏈表* 10.逆置單鏈表 * 11.合并兩個有序鏈表,使合并后的鏈表依舊有序 * 12.在o(1)的時間復(fù)雜度刪除單鏈表中指定的某一節(jié)點*13.在指定節(jié)點前插入一個節(jié)點*14.無序鏈表刪除反復(fù)元素* @author sheepmu*/ class ListNode { int value;ListNode next;public ListNode(int value){this.value=value;this.next=null;} }public class List {public static void main(String[] args){ListNode n1=new ListNode(1);ListNode n2=new ListNode(2);ListNode n3=new ListNode(3);ListNode n4=new ListNode(4);ListNode n5=new ListNode(5);ListNode n6=new ListNode(6);n1.next=n2;n2.next=n3;n3.next=n4;n4.next=n5;n5.next=n6;System.out.println("鏈表長度---->"+getLenRec(n1));System.out.println("鏈表倒數(shù)第三個節(jié)點的值---->"+getLastK(n1,3));System.out.println("刪除鏈表倒數(shù)第3個節(jié)點---->"+moveLastK(n1,3));//此時鏈表已經(jīng)是 1,2,3,5,6 System.out.println("刪除倒數(shù)第k個后的鏈表長度---->"+getLenRec(n1));System.out.println("鏈表中間節(jié)點的值---->"+getMid(n1));System.out.println("鏈表是否有環(huán)---->"+isHaveC(n1));System.out.println("鏈表環(huán)的入口---->"+getFirstC(n1));System.out.println("從尾到頭打印單鏈表---->");reversePrintListStack(n1);System.out.println("逆置單鏈表后的頭節(jié)點--->"+reverseList(n1).value);}//1.鏈表長度public static int getLen(ListNode head){if(head==null) return 0;int len=1;while(head.next!=null){len++;head=head.next;}return len;}//1.鏈表長度 -----遞歸------public static int getLenRec(ListNode head){if(head==null) return 0;return getLenRec(head.next)+1;}//2.得到鏈表倒數(shù)第k個節(jié)點的值/*** 思路:由于倒數(shù)第k個和最后一個相距k-1個節(jié)點,故採用前后指針,第一個先走k-1步,即走到第k個,鏈表我習(xí)慣從1開始計算,然后兩個指針在同一時候走,當前指針p走到末尾時,后指針q的位置剛好是倒數(shù)第k個節(jié)點。 */public static int getLastK(ListNode head,int k){if(head==null||k<=0)return -1;ListNode p=head;ListNode q=head;while(--k>0)//讓p先走k-1步,即p走到第k個節(jié)點,從1開始計數(shù)哈~{p=p.next;if(p.next==null)break; //防止輸入的倒數(shù)k值特別大的異常情況}if(p.next==null)//說明輸入的k超出鏈表長度范圍or等于鏈表長度,即刪除第一個。一定要特別注意這些特別情況,代碼的魯棒性~~{return head.value;}else{while(p.next!=null){p=p.next;q=q.next;}return q.value;}}//3.刪除鏈表的倒數(shù)第k個節(jié)點/*** 思路:和上面相比就是要刪除倒數(shù)第k個,那么就須要記錄后指針的前一節(jié)點,由于刪除鏈表的本質(zhì)就是它的前一節(jié)點指向它的后一節(jié)點*/public static ListNode moveLastK(ListNode head,int k){if(head==null||k<=0)return null;ListNode p=head;ListNode q=head;while(--k>0)//讓p先走k-1步,即p走到第k個節(jié)點,從1開始計數(shù)哈~{p=p.next;if(p.next==null)break; //防止輸入的倒數(shù)k值特別大的異常情況}if(p.next==null)//說明輸入的k超出鏈表長度范圍or等于鏈表長度,即刪除第一個。{return head.next;}else{ListNode pre=q;//用于記錄刪除節(jié)點的前一節(jié)點while(p.next!=null){pre=q;p=p.next;q=q.next;}pre.next=q.next;return head;} }//4.求單鏈表的中間節(jié)點/*** 前后指針,一個每次走2步一個每次走1步,若鏈表長度為奇數(shù)返回中間值,為偶數(shù)返回中間2者的前一者*/public static int getMid(ListNode head){if(head==null||head.next==null)//0個節(jié)點和1個節(jié)點時return -1;if(head.next.next==null)//兩個節(jié)點時return head.value;ListNode p=head;ListNode q=head;while(p.next!=null&&p.next.next!=null)//若僅僅有 一個節(jié)點 和 兩個節(jié)點 時while條件不滿足{p=p.next.next;q=q.next;}return q.value;}//5.推斷鏈表是否有環(huán)/*** 思路:前后指針,一個每次走兩步一個每次走一步,若兩指針相遇了則說明鏈表有環(huán)*/public static boolean isHaveC(ListNode head){if(head==null||head.next==null||head.next.next==null) //僅僅有兩個節(jié)點時也無環(huán)吧?return false;ListNode p=head;ListNode q=head;while(p.next!=null&&p.next.next!=null){p=p.next.next;q=q.next;if(p==q)return true; }return false;}//6.找出有環(huán)鏈表的環(huán)的入口/*** 思路:若有環(huán)肯定會在環(huán)中相遇第一次相遇的位置到環(huán)開始的位置的距離(按環(huán)的方向)與頭節(jié)點到環(huán)的開始的距離相等。故當相遇時,讓節(jié)點q置于頭節(jié)點,讓后兩個節(jié)點同一時候走,再次相遇處就是環(huán)開始的位置。*/public static ListNode getFirstC(ListNode head){if(head==null||head.next==null||head.next.next==null)return null;ListNode p=head;ListNode q=head;while(p.next!=null&&p.next.next!=null){p=p.next.next;q=q.next;if(p==q)break; //pq相遇后break }if(p.next==null||p.next.next==null)//無環(huán)return null;q=head;//把q置于頭節(jié)點while(p!=q){p=p.next;q=q.next;}return q; }//7.推斷兩個單鏈表是否相交/*** 思路:若兩鏈表相交,則兩鏈表的尾節(jié)點肯定是同一節(jié)點*/public boolean isXJ(ListNode head1,ListNode head2){if(head1==null||head2==null)return false;ListNode tail1=head1;while(tail1.next!=null)//不包括僅僅有一個節(jié)點的情況 ,所以上面須要考慮僅僅有一個節(jié)點的情況,可是此時雖僅僅有一個節(jié)點都不進入入while,就return時比較就能夠了 {tail1=tail1.next;//得到head1的尾巴}ListNode tail2=head2;while(tail2.next!=null) {tail2=tail2.next;}return tail1==tail2;}//8.找出兩個相交鏈表的第一個交點/*** 思路:先讓長的鏈表的指針先走長度差的距離,然后兩個指針一起走,相遇的地方便是交點的開始處。*/public static ListNode getFirstJD(ListNode head1,ListNode head2){if(head1==null||head2==null)return null;ListNode tail1=head1;int len1=1;while(tail1.next!=null) {len1++;tail1=tail1.next;}ListNode tail2=head2;int len2=1;while(tail2.next!=null) {len2++;tail2=tail2.next;}ListNode n1=head1;ListNode n2=head2;if(len1>len2){int k=len1-len2;while(k-->0)//這樣寫更精妙~~~~n1=n1.next; }else{int k=len2-len1;while(k-->0)n2=n2.next;}while(n1!=n2){n1=n1.next;n2=n2.next;}return n1;}//9.從尾到頭打印單鏈表/*** 思路:逆序的問題首先想到棧,先進后出,要么用Stack,要么讓系統(tǒng)使用棧,即遞歸~~*/public static void reversePrintListStack(ListNode head) { if(head==null)return;Stack<ListNode> stack = new Stack<ListNode>(); ListNode cur = head; while (cur != null) { stack.push(cur); cur = cur.next; } while (!stack.empty()) { ListNode pop= stack.pop(); System.out.print(pop.value + " "); } System.out.println(); } //9.從尾到頭打印單鏈表 -----遞歸------public static void reversePrintListRec(ListNode head) { if (head == null) return; reversePrintListRec(head.next); //默認已經(jīng)把子問題攻克了,即已經(jīng)輸出了6-->5-->3-->2,后面僅僅須要再輸出頭節(jié)點的值 System.out.print(head.value + " "); //這樣理解會方便我們非常快寫出遞歸,可是還是要知道遞歸真正的實現(xiàn)過程~} //10.逆置單鏈表/*** 思路:把每次遍歷到的都放到新鏈表的尾巴的前一個*/public static ListNode reverseList(ListNode head) { // 假設(shè)鏈表為空或僅僅有一個節(jié)點,無需反轉(zhuǎn),直接返回原鏈表表頭 if (head == null || head.next == null) return head; ListNode newTail = null; //新鏈表的尾巴ListNode cur = head; while (cur != null){ ListNode pre = cur; //新鏈表尾巴的前一個 cur = cur.next; // cur更新到下一個節(jié)點 pre.next = newTail ; newTail = pre; // 把尾巴的前一個設(shè)為新的尾巴 } return newTail; } //10.逆置單鏈表 ----遞歸-----public static ListNode reverseListRec(ListNode head){ if(head == null || head.next == null) return head; ListNode reHead = reverseListRec(head.next); //默覺得已經(jīng)逆置好了6-->5-->3-->2,即僅僅須要在2的后面接1,由于2是head.next.所以 head.next.next = head; head.next.next = head; head.next = null; // 防止循環(huán)鏈表 return reHead; } //11.合并兩個有序鏈表,使合并后的鏈表依舊有序/*** 思路:先確定合并后的頭節(jié)點,然后對照兩個鏈表的每個節(jié)點值,若有個鏈表沒有合并完就直接加在后面就能夠了*/public static ListNode mergeSortedList(ListNode head1, ListNode head2) { if (head1 == null) return head2; if (head2 == null) return head1; ListNode mergeHead = null; // 先確定合并后的頭節(jié)點if (head1.value < head2.value ){ mergeHead = head1; head1 = head1.next; // 跳過已經(jīng)合并了的元素 mergeHead.next = null; // 斷開mergeHead的下一個置空} else{ mergeHead = head2; head2 = head2.next; mergeHead.next = null; } ListNode mergeCur = mergeHead; while (head1 != null && head2 != null) { if (head1.value < head2.value ) { mergeCur.next = head1; // 把找到較小的元素合并到merge中 head1 = head1.next; // 跳過已經(jīng)合并了的元素 mergeCur = mergeCur.next; // 找到下一個準備合并的元素 mergeCur.next = null; // 斷開mergeCur和后面的聯(lián)系 } else { mergeCur.next = head2; head2 = head2.next; mergeCur = mergeCur.next; mergeCur.next = null; } } if (head1 != null) // 合并剩余的元素 mergeCur.next = head1; else if (head2 != null) mergeCur.next = head2; return mergeCur; } //11.合并兩個有序鏈表,使合并后的鏈表依舊有序 ----遞歸-----public static ListNode mergeSortedListRec(ListNode head1, ListNode head2) { if (head1 == null) return head2; if (head2 == null) return head1; ListNode mergeHead = null; if (head1.value < head2.value ){ mergeHead = head1; mergeHead.next = mergeSortedListRec(head1.next, head2); // 連接已解決的子問題 } else{ mergeHead = head2; mergeHead.next = mergeSortedListRec(head1, head2.next); } return mergeHead; } //12.在o(1)的時間復(fù)雜度刪除單鏈表中指定的某一節(jié)點/*** 對于刪除節(jié)點,我們普通的思路就是讓該節(jié)點的前一個節(jié)點指向該節(jié)點的下一個節(jié)點 * ,這樣的情況須要遍歷找到該節(jié)點的前一個節(jié)點,時間復(fù)雜度為O(n)。對于鏈表, * 鏈表中的每個節(jié)點結(jié)構(gòu)都是一樣的,所以我們能夠把該節(jié)點的下一個節(jié)點的數(shù)據(jù)拷貝到該節(jié)點 * ,然后刪除下一個節(jié)點就可以。要注意最后一個節(jié)點的情況,這個時候僅僅能用常見的方法來操作,先找到前一個節(jié)點,但整體的平均時間復(fù)雜度還是O(1)*/public void delete(ListNode head, ListNode toDelete){ if(toDelete == null) return; if(toDelete.next != null)//帶刪除的不是尾巴!!!~~~~~~~~~{ toDelete.value = toDelete.next.value ; toDelete.next = toDelete.next.next; } else{ if(head == toDelete)//僅僅有一個節(jié)點時head = null; else{ ListNode node = head; while(node.next != toDelete) node = node.next; // 找到倒數(shù)第二個節(jié)點 node.next = null; } } } }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

轉(zhuǎn)載于:https://www.cnblogs.com/bhlsheji/p/4045110.html

總結(jié)

以上是生活随笔為你收集整理的面试准备系列01----面试中的链表题目汇总的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。