2020-8-04逆リンクリストⅡ
今日の終わりに、私はメソッドヘッド補間を1つだけ書きました。[m、n]の場合、mの前にmの後の数字を1つずつ配置する必要があります(mの位置に挿入すると、元のmは自動的に元に戻ります)
1回目はm + 1をm位置
に挿入し、2回目はm + 2をm位置に挿入します(ここに記載されている位置はデータではなく、m位置は実際には前に挿入されていることに注意してください)時間。M+ 1)
3回目、m + 3をm位置に挿入し、以下同様
に... nがm位置に挿入されるまで(この時点で元のmがn位置に到達する
まで)反復ごとにをm位置に挿入し、nm回繰り返した後、置換が完了します。これは、ヘッド挿入方法の本来の意図です。たとえば
、画像は鮮明です
1-> 2-> 3-> 4-> 5
1-> 3-> 2-> 4-> 5
1- > 4-> 3-> 2-> 5
変換が完了しました!
変換プロセス中のポインタ変換をコードで説明します
①自分で書いた方法はちょっと面倒です〜比較のために書き留めておきます
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n)
{
//这一步不要也可以,个人喜好
if(m == n || !head)
{
return head;
}
//上述所讲的头插法至少有3个节点,这里对只有2个节点的调换的情况单独讨论
if(m==1&&n==2&&!head->next->next)
{
head->next->next = head;
ListNode* temp = head->next;
head->next = NULL;
return temp;
}
//设置一个虚拟节点
struct ListNode dummy;
dummy.next = head;
//pre一开始在-1的位置
ListNode* pre = &dummy;
//pre来到m-1的位置
for(int i=1;i < m;i++)
{
pre = pre->next;
}
//cur在m的位置
ListNode* cur = pre->next;
//开始扫描
for(int j = m;j < n; j++)
{
//m+1插到m位置(交换他们的后驱指针哦!)
//可以看到cur从原本的m现在后移到了m+1的位置
//每一次迭代cur都是指向2,但是它都会在链表上后移一个位置
//而pre是一直没有动的,一直都在m-1的位置,它要指向插过来的数据
//这样每一次迭代都会将cur与后一位进行链表意义上的位置交换直到完成
ListNode* temp=cur->next;
cur->next = temp->next;
temp->next = pre->next;
pre->next = temp;
}
return dummy.next;
}
};
同じ考えは簡潔なコードです(私はあまりにも上手です)
class Solution {
public:
//思路:head表示需要反转的头节点,pre表示需要反转头节点的前驱节点
//我们需要反转n-m次,我们将head的next节点移动到需要反转链表部分的首部,需要反转链表部分剩余节点依旧保持相对顺序即可
//比如1->2->3->4->5,m=1,n=5
//第一次反转:1(head) 2(next) 3 4 5 反转为 2 1 3 4 5
//第二次反转:2 1(head) 3(next) 4 5 反转为 3 2 1 4 5
//第三次发转:3 2 1(head) 4(next) 5 反转为 4 3 2 1 5
//第四次反转:4 3 2 1(head) 5(next) 反转为 5 4 3 2 1
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode *dummy=new ListNode(-1);
dummy->next=head;
ListNode *pre=dummy;
for(int i=1;i<m;++i)pre=pre->next;
head=pre->next;
for(int i=m;i<n;++i){
ListNode *nxt=head->next;
//head节点连接nxt节点之后链表部分,也就是向后移动一位
head->next=nxt->next;
//nxt节点移动到需要反转链表部分的首部
nxt->next=pre->next;
pre->next=nxt;//pre继续为需要反转头节点的前驱节点
}
return dummy->next;
}
};
②ダイレクトフリップ方式、昨日解いた反転リンクリストからレッスンを引き出し、反復ごとにポインタを直接変更し、1-> 2を直接1 <-2に変更し、最後に頭と尾のポインタを操作します(m then n + 1、m-1、次にn)、したがってローカルフリップを形成します
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode *dummy = new ListNode(-1);
dummy->next = head;
// 第m-1个节点
ListNode *pre=dummy;
for(int i=1; i<m; i++){
pre = pre->next;
}
// 第m个节点
ListNode *t, *cur=pre->next, *mNode=pre->next;
// 头插法
for(int i=m; i<=n; i++){
t = cur->next;
cur->next = pre->next;
pre->next = cur;
cur = t;
}
// 第m个节点指向第n+1个节点
mNode->next = cur;
return dummy->next;
}
};