1. 程式人生 > 其它 >python編寫midi檔案

python編寫midi檔案

技術標籤:刷題連結串列演算法資料結構單鏈表jquery

反轉連結串列

方法一:迭代

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

反轉連結串列 II

反轉從位置 mn 的連結串列。請使用一趟掃描完成反轉。

說明:
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;//指向開始反轉位置的前一個元素
    ListNode nextP = dummy.next;//指向開始反轉位置,即反轉後的鏈尾
    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;//新的頭結點
    ans[1] = next;//反轉前連結串列尾的後一個元素
    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;

//反轉前n個元素
public ListNode reverseList(ListNode head, int n) {
    if(n==1){
        successor=head.next;//記錄後繼結點
        return head;
    }
    ListNode p=reverseList(head.next,n-1);
    head.next.next=head;
    head.next=successor;//將head指向後繼,反轉整條連結串列尾null
    return p;
}

K 個一組翻轉連結串列

給你一個連結串列,每 k 個節點一組進行翻轉,請你返回翻轉後的連結串列。

k 是一個正整數,它的值小於或等於連結串列的長度。

如果節點總數不是 k 的整數倍,那麼請將最後剩餘的節點保持原有順序。

示例:

給你這個連結串列:1->2->3->4->5

k = 2 時,應當返回: 2->1->4->3->5

k = 3 時,應當返回: 3->2->1->4->5

思路:回憶常規連結串列反轉,將每部分反轉的鏈起來

//常規連結串列反轉
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) {
    //參考上一題利用啞結點
    ListNode dummy=new ListNode(0);
    dummy.next=head;
    //用於連結連結串列
    ListNode p=dummy;
    //用於判斷剩餘結點是否是k的整數倍
    ListNode q=head;
    //臨時儲存應該常規反轉連結串列的開始位置
    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

新增啞結點後: 0->1->2->3->4->5 此時p=0 q=1

第一次反轉

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

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

第二次反轉

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