LeetCode | 鏈表相關題目

  • LeetCode 160.相交鏈表

編寫一個程序桨菜,找到兩個單鏈表相交的起始節(jié)點吮成。
如下面的兩個鏈表:


在節(jié)點 c1 開始相交鳄虱。
示例 1:
示例1

輸入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
輸出:Reference of the node with value = 8
輸入解釋:相交節(jié)點的值為 8 (注意蒜田,如果兩個列表相交則不能為 0)。從各自的表頭開始算起膜廊,鏈表 A 為 [4,1,8,4,5]乏沸,鏈表 B 為 [5,0,1,8,4,5]。在 A 中爪瓜,相交節(jié)點前有 2 個節(jié)點蹬跃;在 B 中,相交節(jié)點前有 3 個節(jié)點铆铆。
注意:
如果兩個鏈表沒有交點炬转,返回 null.
在返回結果后,兩個鏈表仍須保持原有的結構算灸。
可假定整個鏈表結構中沒有循環(huán)。
程序盡量滿足 O(n) 時間復雜度驻啤,且僅用 O(1) 內存菲驴。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
//令兩個指針分別指向兩個鏈表的頭,然后依次往后遍歷骑冗,當一個鏈表遍歷至尾時赊瞬,令指針指向另一鏈表的頭。
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode l1 = headA;
        ListNode l2 = headB;
        while(l1 != l2){
            l1 = (l1 == null) ? headB : l1.next;
            l2 = (l2 == null) ? headA : l2.next;
        }
        return l1;
    }
}
  • LeetCode 21.合并兩個有序鏈表

將兩個有序鏈表合并為一個新的有序鏈表并返回贼涩。新鏈表是通過拼接給定的兩個鏈表的所有節(jié)點組成的巧涧。
示例:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4

/**
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode result = new ListNode(0);//創(chuàng)建一個新鏈表用于保存合并后的結果
        ListNode curr = result;//創(chuàng)建一個指向結果鏈表頭結點的指針,用于執(zhí)行歸并操作
        while(l1 != null && l2 != null){  //如果l1和l2都還有元素
            if(l1.val < l2.val){  //如果l1元素較小遥倦,插入結果鏈表谤绳,兩個鏈表都進行后移
                curr.next = l1;
                curr = curr.next;
                l1 = l1.next;
            }else{
                curr.next = l2;
                curr = curr.next;
                l2 = l2.next;
            }
        }
        if(l1 == null){   
            curr.next = l2;  //如果l2已經無元素,則插入l1剩余元素
        }else{
            curr.next = l1;
        }
        return result.next;
    }
}
  • LeetCode 328.奇偶鏈表

給定一個單鏈表袒哥,把所有的奇數(shù)節(jié)點和偶數(shù)節(jié)點分別排在一起缩筛。請注意,這里的奇數(shù)節(jié)點和偶數(shù)節(jié)點指的是節(jié)點編號的奇偶性堡称,而不是節(jié)點的值的奇偶性瞎抛。
請嘗試使用原地算法完成。你的算法的空間復雜度應為 O(1)却紧,時間復雜度應為 O(nodes)桐臊,nodes 為節(jié)點總數(shù)。
示例 1:
輸入:1->2->3->4->5->NULL
輸出: 1->3->5->2->4->NULL
示例 2:
輸入: 2->1->3->5->6->4->7->NULL
輸出: 2->3->6->7->1->5->4->NULL
說明:
應當保持奇數(shù)節(jié)點和偶數(shù)節(jié)點的相對順序晓殊。
鏈表的第一個節(jié)點視為奇數(shù)節(jié)點断凶,第二個節(jié)點視為偶數(shù)節(jié)點,以此類推巫俺。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode oddEvenList(ListNode head) {
        if(head == null){
            return head;
        }
        ListNode odd = head; //奇指針指向鏈表頭
        ListNode even = head.next; //偶指針指向鏈表頭指向的下一個元素(第一個偶數(shù)對象)
        ListNode evenHead = even; //保存對應的偶數(shù)節(jié)點
        while(even != null && even.next != null){
            odd.next = odd.next.next;
            odd = odd.next;
            even.next = even.next.next;
            even = even.next;
        }
        odd.next = evenHead; //再把奇偶連接起來
        return head;
    }
}
  • LeetCode 206.反轉鏈表

反轉一個單鏈表懒浮。
示例:
輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
進階:
你可以迭代或遞歸地反轉鏈表。你能否用兩種方法解決這道題?

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null||head.next == null){
            return head;
        }
        ListNode p = head;
        ListNode newH = null;
        while(p!=null){
            ListNode temp = p.next;
            p.next = newH;
            newH = p;
            p = temp;
    }  
        return newH;
    }
}
  • LeetCode 19.刪除鏈表中的倒數(shù)第N個節(jié)點

給定一個鏈表砚著,刪除鏈表的倒數(shù)第 n 個節(jié)點次伶,并且返回鏈表的頭結點。
示例:
給定一個鏈表: 1->2->3->4->5, 和 n = 2.
當刪除了倒數(shù)第二個節(jié)點后稽穆,鏈表變?yōu)?1->2->3->5.
說明:
給定的 n 保證是有效的冠王。
進階:
你能嘗試使用一趟掃描實現(xiàn)嗎?

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode fast_p = dummy;
        ListNode slow_p = dummy;
        for(int i = 0; i < n + 1; i++){
            fast_p = fast_p.next;
        }
        while(fast_p != null){
            fast_p = fast_p.next;
            slow_p = slow_p.next;
        }
        slow_p.next = slow_p.next.next;
        return dummy.next;
    }
}
  • LeetCode 445.兩數(shù)相加②

給定兩個非空鏈表來代表兩個非負整數(shù)舌镶。數(shù)字最高位位于鏈表開始位置柱彻。它們的每個節(jié)點只存儲單個數(shù)字。將這兩數(shù)相加會返回一個新的鏈表餐胀。
你可以假設除了數(shù)字 0 之外哟楷,這兩個數(shù)字都不會以零開頭。
進階:
如果輸入鏈表不能修改該如何處理否灾?換句話說卖擅,你不能對列表中的節(jié)點進行翻轉。
示例:
輸入: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出: 7 -> 8 -> 0 -> 7

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Stack<Integer> l1_Stack = LinkListToStack(l1);
        Stack<Integer> l2_Stack = LinkListToStack(l2);
        int carry = 0;
        ListNode head = new ListNode(-1);
        while(!l1_Stack.isEmpty() || !l2_Stack.isEmpty() || carry != 0){
            int l1_val = l1_Stack.isEmpty() ? 0 : l1_Stack.pop();
            int l2_val = l2_Stack.isEmpty() ? 0 : l2_Stack.pop();
            int sum = l1_val + l2_val + carry;
            ListNode node = new ListNode(sum % 10);
            node.next = head.next;
            head.next = node;
            carry = sum / 10;
        }
        return head.next;
    }
    private Stack<Integer> LinkListToStack(ListNode l) {
        Stack<Integer> stack = new Stack<>();
        while(l != null){
            stack.push(l.val);
            l = l.next;
        }
        return stack;
    }
}
  • LeetCode 2.兩數(shù)相加

給出兩個 非空 的鏈表用來表示兩個非負的整數(shù)墨技。其中惩阶,它們各自的位數(shù)是按照 逆序 的方式存儲的,并且它們的每個節(jié)點只能存儲 一位 數(shù)字扣汪。
如果断楷,我們將這兩個數(shù)相加起來,則會返回一個新的鏈表來表示它們的和崭别。
您可以假設除了數(shù)字 0 之外冬筒,這兩個數(shù)都不會以 0 開頭。
示例:
輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode result = new ListNode(0);
        ListNode temp = result;
        int sum = 0;
        while(l1!=null || l2!= null){
            if(l1!= null){
                sum += l1.val;
                l1 = l1.next;
            }
            if(l2!= null){
                sum += l2.val;
                l2 = l2.next;
            }
            temp.next = new ListNode(sum % 10);
            temp = temp.next;
            sum = sum / 10;
        }
        if(sum != 0){
            temp.next = new ListNode(1);
        }
        return result.next;
    }
}
  • LeetCode 234.回文鏈表

請判斷一個鏈表是否為回文鏈表茅主。
示例 1:
輸入:1->2
輸出: false
示例 2:
輸入: 1->2->2->1
輸出: true
進階:
你能否用 O(n) 時間復雜度和 O(1) 空間復雜度解決此題账千?

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    //使用快慢指針找到鏈表的中段。
    public boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null){
            return true;
        }
        
        ListNode slow_p = head;
        ListNode fast_p = head.next;
        while(fast_p != null && fast_p.next != null){
            slow_p = slow_p.next;
            fast_p = fast_p.next.next;
        }
        if(fast_p != null){
            slow_p = slow_p.next;
        }
        cut(head,slow_p);
        return isEqual(head,reverse(slow_p));
    }
    
    //剪切鏈表讓其劃分為兩段
    private void cut(ListNode head,ListNode cutNode){
        while(head.next != cutNode){
            head = head.next;
        }
        head.next = null;
    }
    
    //翻轉鏈表
    private ListNode reverse(ListNode head){
        ListNode newH = null;
       
        while(head != null){
            ListNode temp = head.next;
            head.next = newH;
            newH = head;
            head = temp;
        }
        return newH;
    }
    
    //判斷鏈表是否回文
    private boolean isEqual(ListNode l1,ListNode l2){
        while(l1 != null && l2 != null){
            if(l1.val != l2.val){
                return false;
            }
            l1 = l1.next;
            l2 = l2.next;
        }
        return true;
    }
}
  • LeetCode 83.刪除排序鏈表中的重復元素

給定一個排序鏈表暗膜,刪除所有重復的元素匀奏,使得每個元素只出現(xiàn)一次。
示例 1:
輸入: 1->1->2
輸出: 1->2
示例 2:
輸入: 1->1->2->3->3
輸出: 1->2->3

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode current = head;
        while(current != null && current.next != null){
            if(current.val == current.next.val){
                current.next = current.next.next;
            }else{
                current = current.next;
            }
        }
        return head;
    }
}
  • LeetCode 19.刪除鏈表的倒數(shù)第N個節(jié)點

給定一個鏈表学搜,刪除鏈表的倒數(shù)第 n 個節(jié)點娃善,并且返回鏈表的頭結點。
示例:
給定一個鏈表: 1->2->3->4->5, 和 n = 2.
當刪除了倒數(shù)第二個節(jié)點后瑞佩,鏈表變?yōu)?1->2->3->5.
說明:
給定的 n 保證是有效的聚磺。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode fast_p = dummy;
        ListNode slow_p = dummy;
        for(int i = 0; i < n + 1; i++){
            fast_p = fast_p.next;
        }
        while(fast_p != null){
            fast_p = fast_p.next;
            slow_p = slow_p.next;
        }
        slow_p.next = slow_p.next.next;
        return dummy.next;
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市炬丸,隨后出現(xiàn)的幾起案子瘫寝,更是在濱河造成了極大的恐慌蜒蕾,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焕阿,死亡現(xiàn)場離奇詭異咪啡,居然都是意外死亡,警方通過查閱死者的電腦和手機暮屡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門撤摸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人褒纲,你說我怎么就攤上這事准夷。” “怎么了莺掠?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵衫嵌,是天一觀的道長。 經常有香客問我彻秆,道長楔绞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任掖棉,我火速辦了婚禮,結果婚禮上膀估,老公的妹妹穿的比我還像新娘幔亥。我一直安慰自己,他們只是感情好察纯,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布帕棉。 她就那樣靜靜地躺著,像睡著了一般饼记。 火紅的嫁衣襯著肌膚如雪香伴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天具则,我揣著相機與錄音即纲,去河邊找鬼。 笑死博肋,一個胖子當著我的面吹牛低斋,可吹牛的內容都是我干的。 我是一名探鬼主播匪凡,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼膊畴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了病游?” 一聲冷哼從身側響起唇跨,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后买猖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體改橘,經...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年政勃,在試婚紗的時候發(fā)現(xiàn)自己被綠了唧龄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡奸远,死狀恐怖既棺,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情懒叛,我是刑警寧澤丸冕,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站薛窥,受9級特大地震影響胖烛,放射性物質發(fā)生泄漏。R本人自食惡果不足惜诅迷,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一佩番、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧罢杉,春花似錦趟畏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至律想,卻和暖如春猎莲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背技即。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工著洼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人而叼。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓郭脂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親澈歉。 傳聞我的和親對象是個殘疾皇子展鸡,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內容