合并兩個排序的鏈表&反轉(zhuǎn)鏈表&兩兩交換鏈表中的節(jié)點

合并兩個排序的鏈表

輸入兩個遞增排序的鏈表可霎,合并這兩個鏈表并使新鏈表中的節(jié)點仍然是遞增排序的咏花。

示例1:

輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    ListNode dummy=new ListNode(0);
    ListNode r=dummy;
    while(l1!=null&&l2!=null){
        if(l1.val<=l2.val){
            r.next=l1;
            l1=l1.next;
        } else{
            r.next=l2;
            l2=l2.next;

        }
        r=r.next;
    }
    r.next=l1==null?l2:l1;
    return dummy.next;
}

遞歸形式:

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    if(l1==null){
        return l2;
    }
    if(l2==null){
        return l1;
    }
    ListNode head;
    if(l1.val<=l2.val){
        l1.next=mergeTwoLists(l1.next,l2);
        return l1;
    } else{
        l2.next=mergeTwoLists(l1,l2.next);
        return l2;
    }
}

反轉(zhuǎn)鏈表

方法一:迭代

public ListNode reverseList(ListNode head) {
    ListNode newHead=null;
    ListNode p=head;
    while(p!=null){
        ListNode next=p.next;
        p.next=newHead;
        newHead=p;
        p=next;
    }
    return newHead;
}

方法二:遞歸

public ListNode reverseList(ListNode head) {
    if(head==null||head.next==null){
        return head;
    }
    ListNode p=reverseList(head.next);
    head.next.next=head;
    head.next=null;
    return p;
}

反轉(zhuǎn)鏈表 II

反轉(zhuǎn)從位置 mn 的鏈表。請使用一趟掃描完成反轉(zhuǎn)短蜕。

說明:
1 ≤ mn ≤ 鏈表長度。

示例:

輸入: 1->2->3->4->5->NULL, m = 2, n = 4
輸出: 1->4->3->2->5->NULL

方法一:迭代

public ListNode reverseBetween(ListNode head, int m, int n) {
    ListNode dummy=new ListNode(0);//m=1時
    dummy.next=head;
    ListNode p = dummy;//指向開始反轉(zhuǎn)位置的前一個元素
    ListNode nextP = dummy.next;//指向開始反轉(zhuǎn)位置傻咖,即反轉(zhuǎn)后的鏈尾
    for (int i = 0; i < m-1 ; i++) {
        p = p.next;
        nextP = nextP.next;
    }
    ListNode[] ans = reverseList(nextP, n - m + 1);
    p.next = ans[0];
    nextP.next = ans[1];
    return dummy.next;
}

public ListNode[] reverseList(ListNode head, int n) {
    ListNode newHead = null;
    ListNode p = head;
    ListNode[] ans = new ListNode[2];

    ListNode next =null;
    for (int i = 0; i < n; i++) {
        next = p.next;
        p.next = newHead;
        newHead = p;
        p = next;
    }
    ans[0] = newHead;//新的頭結(jié)點
    ans[1] = next;//反轉(zhuǎn)前鏈表尾的后一個元素
    return ans;
}

方法二:遞歸

public ListNode reverseBetween(ListNode head, int m, int n) {
    if(m==1){//從第一個位置開始朋魔,即返回前n個
        return reverseList(head,n);
    }
    head.next=reverseBetween(head.next,m-1,n-1);
    return head;
}

private ListNode successor;

//反轉(zhuǎn)前n個元素
public ListNode reverseList(ListNode head, int n) {
    if(n==1){
        successor=head.next;//記錄后繼結(jié)點
        return head;
    }
    ListNode p=reverseList(head.next,n-1);
    head.next.next=head;
    head.next=successor;//將head指向后繼,反轉(zhuǎn)整條鏈表尾null
    return p;
}

K 個一組翻轉(zhuǎn)鏈表

給你一個鏈表卿操,每 k 個節(jié)點一組進行翻轉(zhuǎn)铺厨,請你返回翻轉(zhuǎn)后的鏈表。

k 是一個正整數(shù)硬纤,它的值小于或等于鏈表的長度解滓。

如果節(jié)點總數(shù)不是 k 的整數(shù)倍,那么請將最后剩余的節(jié)點保持原有順序筝家。

示例:

給你這個鏈表:1->2->3->4->5

k = 2 時洼裤,應(yīng)當返回: 2->1->4->3->5

k = 3 時,應(yīng)當返回: 3->2->1->4->5

思路:回憶常規(guī)鏈表反轉(zhuǎn)溪王,將每部分反轉(zhuǎn)的鏈起來

//常規(guī)鏈表反轉(zhuǎn)
public static ListNode reverse(ListNode head,int k) {
    ListNode p=head;
    ListNode newHead=null;
    for (int i = 0; i <k ; i++) {
        ListNode next=p.next;
        p.next=newHead;
        newHead=p;
        p=next;
    }
    return newHead;
}

public static ListNode reverseKGroup(ListNode head, int k) {
    //參考上一題利用啞結(jié)點
    ListNode dummy=new ListNode(0);
    dummy.next=head;
    //用于鏈接鏈表
    ListNode p=dummy;
    //用于判斷剩余結(jié)點是否是k的整數(shù)倍
    ListNode q=head;
    //臨時保存應(yīng)該常規(guī)反轉(zhuǎn)鏈表的開始位置
    ListNode temp;
    while (p!=null){
        temp=q;
        for (int i = 0; i < k; i++) {
            //不夠直接鏈接
            if(q==null){
                p.next=temp;
                return dummy.next;
            }
            q=q.next;
        }
        p.next= reverse(temp, k);
        p=temp;
    }
    return dummy.next;
}

對于這個鏈表:1->2->3->4->5

添加啞結(jié)點后: 0->1->2->3->4->5 此時p=0 q=1

第一次反轉(zhuǎn)

temp=1 q=3 2= reverse(1,2)

0->2->1 p=1 剩下3->4>5

第二次反轉(zhuǎn)

temp=3 q=5 4=reverse(3,2)

0->2->1->4->3 p=3 剩下 5

第三次

temp=5 q==null 0->2->1->4->3->5

新代碼

public ListNode reverseKGroup(ListNode head, int k) {
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode p = head;
    ListNode linkNode = dummy;//用于連接鏈表
    while (p != null) {
        ListNode seeNode = p;//向前查看是否有k個
        for (int i = 0; i < k; i++) {
            if (seeNode == null) {//不夠了直接順序返回
                linkNode.next = p;
                return dummy.next;
            }
            seeNode = seeNode.next;
        }
        ListNode[] reverseNode = reverse(p, k);
        linkNode.next = reverseNode[0];//連接到反轉(zhuǎn)后的頭結(jié)點
        linkNode = p;//反轉(zhuǎn)前的頭結(jié)點成了尾結(jié)點腮鞍,現(xiàn)在連接從這里開始
        p = reverseNode[1];
    }
    return dummy.next;
}

// 返回新的頭結(jié)點和原來鏈表n+1位置的結(jié)點
public ListNode[] reverse(ListNode head, int n) {
    ListNode newHead = null;
    ListNode p = head;
    for (int i = 0; i < n; i++) {
        ListNode next = p.next;
        p.next = newHead;
        newHead = p;
        p = next;
    }
    return new ListNode[]{newHead, p};
}

兩兩交換鏈表中的節(jié)點

給定一個鏈表,兩兩交換其中相鄰的節(jié)點莹菱,并返回交換后的鏈表移国。

你不能只是單純的改變節(jié)點內(nèi)部的值,而是需要實際的進行節(jié)點交換道伟。

示例 1:

輸入:head = [1,2,3,4]
輸出:[2,1,4,3]

示例 2:

輸入:head = []
輸出:[]

示例 3:

輸入:head = [1]
輸出:[1]

提示:

  • 鏈表中節(jié)點的數(shù)目在范圍 [0, 100] 內(nèi)
  • 0 <= Node.val <= 100

方法一:迭代

public ListNode swapPairs(ListNode head) {
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode p = head;
    ListNode link = dummy;
    while (p != null && p.next != null) {
        ListNode pair = p.next;
        ListNode next = pair.next;
        pair.next = p;
        link.next = pair;
        link = p;
        p.next = next;
        p = next;
    }
    return dummy.next;
}

方法二:遞歸

public ListNode swapPairs(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode nextHead = swapPairs(head.next.next);
    ListNode next = head.next;
    next.next = head;
    head.next = nextHead;
    return next;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迹缀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蜜徽,更是在濱河造成了極大的恐慌祝懂,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拘鞋,死亡現(xiàn)場離奇詭異砚蓬,居然都是意外死亡,警方通過查閱死者的電腦和手機盆色,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門灰蛙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來祟剔,“玉大人,你說我怎么就攤上這事摩梧∥镅樱” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵障本,是天一觀的道長。 經(jīng)常有香客問我响鹃,道長驾霜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任买置,我火速辦了婚禮粪糙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘忿项。我一直安慰自己蓉冈,他們只是感情好,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布轩触。 她就那樣靜靜地躺著寞酿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脱柱。 梳的紋絲不亂的頭發(fā)上伐弹,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機與錄音榨为,去河邊找鬼惨好。 笑死,一個胖子當著我的面吹牛随闺,可吹牛的內(nèi)容都是我干的日川。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼矩乐,長吁一口氣:“原來是場噩夢啊……” “哼龄句!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起散罕,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤撒璧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后笨使,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卿樱,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年硫椰,在試婚紗的時候發(fā)現(xiàn)自己被綠了繁调。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萨蚕。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蹄胰,靈堂內(nèi)的尸體忽然破棺而出岳遥,到底是詐尸還是另有隱情,我是刑警寧澤裕寨,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布浩蓉,位于F島的核電站,受9級特大地震影響宾袜,放射性物質(zhì)發(fā)生泄漏捻艳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一庆猫、第九天 我趴在偏房一處隱蔽的房頂上張望认轨。 院中可真熱鬧,春花似錦月培、人聲如沸嘁字。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纪蜒。三九已至,卻和暖如春此叠,著一層夾襖步出監(jiān)牢的瞬間霍掺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工拌蜘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留杆烁,地道東北人。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓简卧,卻偏偏與公主長得像兔魂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子举娩,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354