0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

移動(dòng)旋轉(zhuǎn)鏈表的每個(gè)節(jié)點(diǎn)

算法與數(shù)據(jù)結(jié)構(gòu) ? 來(lái)源:吳師兄學(xué)算法 ? 作者:吳師兄 ? 2022-10-25 18:05 ? 次閱讀

一、題目描述

給你一個(gè)鏈表的頭節(jié)點(diǎn)head,旋轉(zhuǎn)鏈表,將鏈表每個(gè)節(jié)點(diǎn)向右移動(dòng)k個(gè)位置。

示例 1:

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

示例 2:

輸入:head =[0,1,2], k = 4
輸出:[2,0,1]
231674e4-4859-11ed-a3b6-dac502259ad0.png

提示:

鏈表中節(jié)點(diǎn)的數(shù)目在范圍 [0, 500] 內(nèi)

-100 <= Node.val <= 100

0 <= k <= 2 * 10^9

原題地址:https://leetcode.cn/problems/rotate-list/

二、題目解析

1、首先遍歷整個(gè)鏈表,求出鏈表的長(zhǎng)度len。

2、根據(jù)題目的提示,k可能很大,遠(yuǎn)超鏈表的長(zhǎng)度,這樣就會(huì)導(dǎo)致一種情況,比如 k = 1000,len = 999,每個(gè)節(jié)點(diǎn)向右移動(dòng) 1 個(gè)節(jié)點(diǎn)和向右移動(dòng) k = 1000 個(gè)節(jié)點(diǎn)結(jié)果一樣,所以進(jìn)行一個(gè)取模的操作可以節(jié)省大量的移動(dòng)操作。

3、接下來(lái)設(shè)置兩個(gè)指針 former、latter 均指向鏈表的頭節(jié)點(diǎn),這兩個(gè)指針的目的是去尋找出旋轉(zhuǎn)之前的尾節(jié)點(diǎn)位置、旋轉(zhuǎn)成功之后的尾節(jié)點(diǎn)位置。

4、先讓former指針先向前移動(dòng) k 次,此時(shí),former就和latter相距 k 個(gè)節(jié)點(diǎn)了。

5、接下來(lái),讓former、latter同時(shí)向后移動(dòng),直到former來(lái)到了最后一個(gè)節(jié)點(diǎn)位置。

23256972-4859-11ed-a3b6-dac502259ad0.png

6、這個(gè)時(shí)候,從head到latter有len - k個(gè)節(jié)點(diǎn),latter + 1 到 former 有 k 個(gè)節(jié)點(diǎn)。

7、也就意味著,latter + 1這個(gè)節(jié)點(diǎn)是移動(dòng) k 個(gè)節(jié)點(diǎn)成功之后的頭節(jié)點(diǎn)。

2330f4c2-4859-11ed-a3b6-dac502259ad0.png

8、只需要返回latter + 1后面這個(gè)節(jié)點(diǎn)newHead,并且斷開(kāi)連接就行了。

三、參考代碼

1、Java 代碼

//登錄AlgoMooc官網(wǎng)獲取更多算法圖解
//https://www.algomooc.com
//作者:程序員吳師兄
//代碼有看不懂的地方一定要私聊咨詢(xún)吳師兄呀
//旋轉(zhuǎn)鏈表(LeetCode61)//leetcode.cn/problems/rotate-list/
classSolution{
publicListNoderotateRight(ListNodehead,intk){

//邊界條件判斷
if(head==null){
returnhead;
}

//1、第一步先要計(jì)算出鏈表的長(zhǎng)度來(lái)
intlen=0;

//2、這里我們?cè)O(shè)置一個(gè)指針指向鏈表的頭節(jié)點(diǎn)的位置
ListNodetempHead=head;

//3、通過(guò)不斷的移動(dòng)tempHead,來(lái)獲取鏈表的長(zhǎng)度
while(tempHead!=null){

//tempHead不斷向后移動(dòng),直到為null
tempHead=tempHead.next;

//每次遍歷一個(gè)新的節(jié)點(diǎn),意味著鏈表長(zhǎng)度新增1
len++;

}

//由于題目中的k會(huì)超過(guò)鏈表的長(zhǎng)度,因此進(jìn)行一個(gè)取余的操作
//比如k=1000,len=999
//實(shí)際上就是將鏈表每個(gè)節(jié)點(diǎn)向右移動(dòng)1000%999=1個(gè)位置就行了
//因?yàn)殒湵碇械拿總€(gè)節(jié)點(diǎn)移動(dòng)len次會(huì)回到原位
k=k%len;


//4、接下來(lái)設(shè)置兩個(gè)指針指向鏈表的頭節(jié)點(diǎn)
//這兩個(gè)指針的目的是去尋找出旋轉(zhuǎn)之前的尾節(jié)點(diǎn)位置、旋轉(zhuǎn)成功之后的尾節(jié)點(diǎn)位置

//former指針
ListNodeformer=head;

//latter指針
ListNodelatter=head;

//former指針先向前移動(dòng)k次
for(inti=0;i

2、C++ 代碼

classSolution{
public:
ListNode*rotateRight(ListNode*head,intk){

//邊界條件判斷
if(head==NULL){
returnhead;
}

//1、第一步先要計(jì)算出鏈表的長(zhǎng)度來(lái)
intlen=0;

//2、這里我們?cè)O(shè)置一個(gè)指針指向鏈表的頭節(jié)點(diǎn)的位置
ListNode*tempHead=head;

//3、通過(guò)不斷的移動(dòng)tempHead,來(lái)獲取鏈表的長(zhǎng)度
while(tempHead!=NULL){

//tempHead不斷向后移動(dòng),直到為NULL
tempHead=tempHead->next;

//每次遍歷一個(gè)新的節(jié)點(diǎn),意味著鏈表長(zhǎng)度新增1
len++;

}

//由于題目中的k會(huì)超過(guò)鏈表的長(zhǎng)度,因此進(jìn)行一個(gè)取余的操作
//比如k=1000,len=999
//實(shí)際上就是將鏈表每個(gè)節(jié)點(diǎn)向右移動(dòng)1000%999=1個(gè)位置就行了
//因?yàn)殒湵碇械拿總€(gè)節(jié)點(diǎn)移動(dòng)len次會(huì)回到原位
k=k%len;


//4、接下來(lái)設(shè)置兩個(gè)指針指向鏈表的頭節(jié)點(diǎn)
//這兩個(gè)指針的目的是去尋找出旋轉(zhuǎn)之前的尾節(jié)點(diǎn)位置、旋轉(zhuǎn)成功之后的尾節(jié)點(diǎn)位置

//former指針
ListNode*former=head;

//latter指針
ListNode*latter=head;

//former指針先向前移動(dòng)k次
for(inti=0;inext;

}

//這樣former和latter就相差了k個(gè)節(jié)點(diǎn)
//5、接下來(lái),兩個(gè)指針同時(shí)向后移動(dòng),直到former來(lái)到了最后一個(gè)節(jié)點(diǎn)位置
while(former->next!=NULL){

//former不斷向后移動(dòng)
former=former->next;

//latter不斷向后移動(dòng)
latter=latter->next;
}

//6、此時(shí),former指向了最后一個(gè)節(jié)點(diǎn),需要將這個(gè)節(jié)點(diǎn)和原鏈表的頭節(jié)點(diǎn)連接起來(lái)
former->next=head;

//7、latter指向的節(jié)點(diǎn)的【下一個(gè)節(jié)點(diǎn)】是倒數(shù)第k個(gè)節(jié)點(diǎn),那就是旋轉(zhuǎn)成功之后的頭節(jié)點(diǎn)
ListNode*newHead=latter->next;

//8、斷開(kāi)鏈接,避免成環(huán)
latter->next=NULL;

//9、返回newHead
returnnewHead;

}
};

3、Python 代碼

classSolution:
defrotateRight(self,head:Optional[ListNode],k:int)->Optional[ListNode]:
#邊界條件判斷
ifnotheadork==0:
returnhead

#1、第一步先要計(jì)算出鏈表的長(zhǎng)度來(lái)
_len=0

#2、這里我們?cè)O(shè)置一個(gè)指針指向鏈表的頭節(jié)點(diǎn)的位置
tempHead=head

#3、通過(guò)不斷的移動(dòng)tempHead,來(lái)獲取鏈表的長(zhǎng)度
whiletempHead:

#tempHead不斷向后移動(dòng),直到為NULL
tempHead=tempHead.next

#每次遍歷一個(gè)新的節(jié)點(diǎn),意味著鏈表長(zhǎng)度新增1
_len+=1



#由于題目中的k會(huì)超過(guò)鏈表的長(zhǎng)度,因此進(jìn)行一個(gè)取余的操作
#比如k=1000,len=999
#實(shí)際上就是將鏈表每個(gè)節(jié)點(diǎn)向右移動(dòng)1000%999=1個(gè)位置就行了
#因?yàn)殒湵碇械拿總€(gè)節(jié)點(diǎn)移動(dòng)len次會(huì)回到原位
k=k%_len


#4、接下來(lái)設(shè)置兩個(gè)指針指向鏈表的頭節(jié)點(diǎn)
#這兩個(gè)指針的目的是去尋找出旋轉(zhuǎn)之前的尾節(jié)點(diǎn)位置、旋轉(zhuǎn)成功之后的尾節(jié)點(diǎn)位置

#former指針
former=head

#latter指針
latter=head

#former指針先向前移動(dòng)k次
foriinrange(0,k):

#former不斷向后移動(dòng)
former=former.next


#這樣former和latter就相差了k個(gè)節(jié)點(diǎn)
#5、接下來(lái),兩個(gè)指針同時(shí)向后移動(dòng),直到former來(lái)到了最后一個(gè)節(jié)點(diǎn)位置
whileformer.next:

#former不斷向后移動(dòng)
former=former.next

#latter不斷向后移動(dòng)
latter=latter.next


#6、此時(shí),former指向了最后一個(gè)節(jié)點(diǎn),需要將這個(gè)節(jié)點(diǎn)和原鏈表的頭節(jié)點(diǎn)連接起來(lái)
former.next=head

#7、latter指向的節(jié)點(diǎn)的【下一個(gè)節(jié)點(diǎn)】是倒數(shù)第k個(gè)節(jié)點(diǎn),那就是旋轉(zhuǎn)成功之后的頭節(jié)點(diǎn)
newHead=latter.next

#8、斷開(kāi)鏈接,避免成環(huán)
latter.next=None

#9、返回newHead
returnnewHead

四、復(fù)雜度分析

時(shí)間復(fù)雜度:鏈表一共被遍歷兩次,因此總的時(shí)間復(fù)雜度為O(n),n是鏈表的長(zhǎng)度。

空間復(fù)雜度:O(1),我們只需要常數(shù)的空間存儲(chǔ)若干變量。





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2967

    瀏覽量

    104764

原文標(biāo)題:旋轉(zhuǎn)鏈表(LeetCode 61)

文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    C語(yǔ)言-鏈表(單向鏈表、雙向鏈表)

    在前面章節(jié)已經(jīng)學(xué)習(xí)了數(shù)組的使用,數(shù)組的空間是連續(xù)空間,數(shù)組的大小恒定的,在很多動(dòng)態(tài)數(shù)據(jù)存儲(chǔ)的應(yīng)用場(chǎng)景下,使用不方便;而這篇文章介紹的鏈表結(jié)構(gòu),支持動(dòng)態(tài)增加節(jié)點(diǎn),釋放節(jié)點(diǎn),比較適合存儲(chǔ)動(dòng)態(tài)數(shù)據(jù)的應(yīng)用場(chǎng)景,而且
    的頭像 發(fā)表于 09-09 11:30 ?1679次閱讀

    C語(yǔ)言實(shí)現(xiàn)單鏈表-增刪改查

    鏈表是由一連串節(jié)點(diǎn)組成的數(shù)據(jù)結(jié)構(gòu),每個(gè)節(jié)點(diǎn)包含一個(gè)數(shù)據(jù)值和一個(gè)指向下一個(gè)節(jié)點(diǎn)的指針。鏈表可以在頭
    的頭像 發(fā)表于 05-25 15:05 ?1234次閱讀
    C語(yǔ)言實(shí)現(xiàn)單<b class='flag-5'>鏈表</b>-增刪改查

    C語(yǔ)言單向鏈表

    本帖最后由 snowmay001 于 2016-5-22 15:57 編輯 lianbiao.cpp/* 練習(xí)使用鏈表:創(chuàng)建鏈表、遍歷鏈表、查找節(jié)點(diǎn)、添加
    發(fā)表于 05-22 15:53

    Linux內(nèi)核的鏈表操作

    ) 搬移Linux提供了將原本屬于一個(gè)鏈表節(jié)點(diǎn)移動(dòng)到另一個(gè)鏈表的操作,并根據(jù)插入到新鏈表的位置分為兩類(lèi):static inline voi
    發(fā)表于 08-29 11:13

    玩轉(zhuǎn)C語(yǔ)言鏈表-鏈表各類(lèi)操作詳解

    p節(jié)點(diǎn)之后,已經(jīng)改變了first節(jié)點(diǎn),所以first節(jié)點(diǎn)應(yīng)該在被修改之前往后移動(dòng),不能放到下面注釋的位置上去  first = first->next; //無(wú)序
    發(fā)表于 09-18 13:30

    數(shù)據(jù)結(jié)構(gòu)鏈表的基本操作

    嵌入式學(xué)習(xí)基礎(chǔ)-數(shù)據(jù)結(jié)構(gòu)鏈表的基本操作鏈表節(jié)點(diǎn)采用結(jié)構(gòu)體的方式進(jìn)行定義,下面是最基礎(chǔ)的定義只有一個(gè)數(shù)據(jù)data,*pNext用于指向下一個(gè)節(jié)點(diǎn)(若為尾
    發(fā)表于 12-22 08:05

    RT-Thread內(nèi)核中雙鏈表的使用與實(shí)現(xiàn)

    1. 單鏈表與雙鏈表鏈表: 由一個(gè)個(gè)節(jié)點(diǎn)(node)組成,每個(gè)節(jié)點(diǎn)都有指向下一個(gè)
    發(fā)表于 04-01 12:05

    OpenHarmony中的HDF單鏈表及其迭代器

    , or NULL};如上圖所述,每個(gè)節(jié)點(diǎn)都是HdfSListNode,上圖共有5個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)內(nèi)部有一個(gè)next成員,其值為下
    發(fā)表于 08-30 10:31

    OpenHarmony中的HDF單鏈表及其迭代器

    , or NULL};如上圖所述,每個(gè)節(jié)點(diǎn)都是HdfSListNode,上圖共有5個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)內(nèi)部有一個(gè)next成員,其值為下
    發(fā)表于 09-05 11:38

    C語(yǔ)言基礎(chǔ)教程之鏈表

    (一)什么是鏈表鏈表是一種常見(jiàn)的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),是一種線性表,是一種在物理存儲(chǔ)單元上非連續(xù)非順序的存儲(chǔ)結(jié)構(gòu)。 鏈表有一系列節(jié)點(diǎn)構(gòu)成,節(jié)點(diǎn)
    發(fā)表于 11-16 10:22 ?2185次閱讀

    驅(qū)動(dòng)之路-內(nèi)核鏈表的使用

    kernel list展示的是內(nèi)核鏈表的結(jié)構(gòu),normallist展示的是普通鏈表的結(jié)構(gòu)。head是鏈表頭,p1,p2,p3是鏈表節(jié)點(diǎn)。從圖
    發(fā)表于 05-15 17:24 ?1346次閱讀
    驅(qū)動(dòng)之路-內(nèi)核<b class='flag-5'>鏈表</b>的使用

    雙向循環(huán)鏈表的創(chuàng)建

    需要注意的是,雖然雙向循環(huán)鏈表成環(huán)狀,但本質(zhì)上還是雙向鏈表,因此在雙向循環(huán)鏈表中,依然能夠找到頭指針和頭節(jié)點(diǎn)等。雙向循環(huán)鏈表和雙向
    的頭像 發(fā)表于 05-24 16:27 ?2115次閱讀

    鏈表的基礎(chǔ)知識(shí)

    ,也就是數(shù)組,數(shù)組的每個(gè)元素之間的地址是連續(xù)的;對(duì)于鏈?zhǔn)酱鎯?chǔ)來(lái)說(shuō),也就是平常所說(shuō)的鏈表,鏈表每個(gè)元素之間的地址并不是連續(xù)的,而是分散的,他們之間的聯(lián)系通過(guò)結(jié)點(diǎn)的 next 指針來(lái)建立。
    的頭像 發(fā)表于 01-20 17:00 ?1089次閱讀
    <b class='flag-5'>鏈表</b>的基礎(chǔ)知識(shí)

    鏈表的替代品--Vector組件

    概述 在之前的一篇文章中,作者寫(xiě)了一個(gè)事件組件-- 超精簡(jiǎn)的訂閱發(fā)布事件組件--SPEvent ,這個(gè)組件是采用鏈表建立所有事件節(jié)點(diǎn)的關(guān)系的。 鏈表的優(yōu)缺點(diǎn): 優(yōu)點(diǎn):①鏈表上的元素在空
    的頭像 發(fā)表于 04-06 15:39 ?534次閱讀

    鏈表和雙鏈表的區(qū)別在哪里

    鏈表和雙鏈表的區(qū)別 單鏈表的每一個(gè)節(jié)點(diǎn)中只有指向下一個(gè)結(jié)點(diǎn)的指針,不能進(jìn)行回溯。 雙鏈表的每一個(gè)節(jié)點(diǎn)
    的頭像 發(fā)表于 07-27 11:20 ?1669次閱讀
    單<b class='flag-5'>鏈表</b>和雙<b class='flag-5'>鏈表</b>的區(qū)別在哪里