對積性函式篩法的理解
阿新 • • 發佈:2020-10-29
方法一:迭代
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
反轉從位置 m 到 n 的連結串列。請使用一趟掃描完成反轉。
說明:
1 ≤ m ≤ n ≤ 連結串列長度。
示例:
輸入: 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