Leetcode問題解決策25-Kフリップリンクリストのセット

問題の説明

リンクリストを提供します。k個のノードごとに反転します。反転したリンクリストに戻ってください。

kは正の整数であり、その値はリンクリストの長さ以下です。

ノードの総数がkの整数倍でない場合は、最後に残っているノードを元の順序のままにしてください。

上級:

この問題を解決するために一定の余分なスペースのみを使用するアルゴリズムを設計できますか?
ノード内の値を変更するだけでなく、実際にノードを交換する必要があります。

例1:
ここに画像の説明を挿入します

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

例2:
ここに画像の説明を挿入します

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

例3:

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

例4:

输入:head = [1], k = 1
输出:[1]

問題解決のアイデア

1.
リンクリストの長さ数えます2.リンクリストが反転する回数を計算しますreverse_times = len / k;

  • フリップの数が0の場合は、元のリンクリストに戻るだけです。

3.複数の変数を定義します

  • cur_timeは、現在のフリップ数を保存します(フリップ数を決定するために使用できます)
  • nhead仮想ヘッドノード(データを含まないセンチネルヘッドノードは、一般的なリンクリストの質問で定義できます)
  • knextは、次のフリップのリンクリストヘッドノードを保存します(後続のリンクリストデータの損失を防ぐため)
  • cur_headが現在反転する必要がある部分リンクリストのヘッドノードは、実際にはヘッドノードの前のノードです(これは部分反転に便利です)。
  • 現在cur_tailによってフリップされている部分リンクリストのテールノードは、フリップが完了した後にknextに接続するために使用され、データが失われないようにします。

4.リンクリストの反転を実行します

  • 1.次のフリップでリンクリストのヘッドノードの隣にknextをポイントします
  • 2.ヘッド補間法を使用して反転します(ローカルリンクリストの最初のノードを保存するにはcur_tailを使用する必要があることに注意してください。フリップが完了すると、ローカルリンクリストの最後の位置になり、接続します次のリンクリストでそれ)
  • 3.テールノードをヘッドノードに再割り当てし、テールノードの次のポインターがknextを指すようにします。
  • 4.フリップの数+
    15.next.nextに戻ります。
class Solution {
    
    
    public ListNode reverseKGroup(ListNode head, int k) {
    
    
        int len=0;                  //统计链表的长度
        ListNode plen=head;
        while(plen!=null){
    
    
            len++;
            plen=plen.next;
        }

        int reverse_times=len/k;     //计算链表的翻转次数
        if(k<=1 || reverse_times==0){
    
    
            return head;
        }

        ListNode knext=head;         //保存下一次翻转时候的链表头结点
        int cur_times=0;      //保存当前翻转次数
        ListNode nhead=new ListNode(-1);    //虚拟头结点,不包含任何数据
        ListNode cur_head=nhead;
        cur_head.next=head;
        ListNode cur_tail=null;
        while(cur_times<reverse_times){
    
    
            //将knext指向下一次翻转时候的链表头结点
            for(int i=0;i<k;i++){
    
    
                knext=knext.next;
            }

            //使用头插法进行反转            
            ListNode p=cur_head.next;        //保存当前需要头插的结点
            cur_tail=cur_head.next;
            ListNode next=null;         //保存反转时下一个结点的指针
            for(int i=0;i<k;i++){
    
    
                next=p.next;           
                p.next=cur_head.next;
                cur_head.next=p;
                p=next;
            }
            //将尾部结点重新赋值给头部结点,并且让尾部结点的next指针指向knext
            cur_head=cur_tail;
            cur_tail.next=knext;
            // System.out.println("3 "+knext.val);
            cur_times++;
        }        
        return nhead.next;
    }
}

おすすめ

転載: blog.csdn.net/qq_39736597/article/details/115029580
おすすめ