2020-8-04毎日の質問ノート-逆リンクリストⅡ

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;
    }
};

おすすめ

転載: blog.csdn.net/weixin_45336082/article/details/107804108