1. 程式人生 > >61. Rotate List(python+cpp)

61. Rotate List(python+cpp)

題目:

Given a linked list, rotate the list to the right by k places, where k is non-negative. Example 1:

Input: 1->2->3->4->5->NULL, k = 2 
Output: 4->5->1->2->3->NULL
Explanation: 
rotate 1 steps to the right: 5->1->2->3->4->NULL 
rotate 2 steps to the right: 4->5->1->2->3->NULL 

Example 2:

Input: 0->1->2->NULL, k = 4 
Output: 2->0->1->NULL 
Explanation: 
rotate 1 steps to the right: 2->0->1->NULL 
rotate 2 steps to the right: 1->2->0->NULL 
rotate 3 steps to the right: 0->1->2->NULL 
rotate 4 steps to the right: 2->0->1->NULL

解釋: 和rotate陣列是一樣的,所以需要用到206. Reverse Linked List(python+cpp),並且找到了關於陣列rotate的一般規律: 向左移動:先分別翻轉兩部分,再全部翻轉 向右移動:先全部翻轉,再分別翻轉兩部分 其中左半部分是nums[:k],右半部分是nums[k:] 由於連結串列翻轉比較複雜,所以這裡選擇使用額外空間,先把連結串列存成陣列,再對陣列完成各種翻轉操作,再把陣列轉換為連結串列。 python程式碼:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
# self.val = x # self.next = None class Solution: def rotateRight(self, head, k): """ :type head: ListNode :type k: int :rtype: ListNode """ if not head: return head _list=[] p=head while p!=None: _list.append(p.val) p=p.next k=k%len(_list) _list_reverse=_list[::-1] result=_list_reverse[:k][::-1]+_list_reverse[k:][::-1] new_head=ListNode(0) pre=new_head p=new_head.next for i in range(len(result)): temp=ListNode(result[i]) pre.next=temp pre=pre.next return new_head.next

後來發現,連結串列的rotate,根本不需要原地翻轉,也不需要轉換成陣列再翻轉,只需要操作工作指標即可,甚至比陣列rotate更簡單。注意因為cur一定要指向最後一個結點而不是None,所以要用while(cur.next)作為迴圈語句的判斷條件,這樣寫就要求在head前面加一個結點,不然算出的size會比真實的小1。 python程式碼:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def rotateRight(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        if not head or k==0:
            return head
        
        size=0;
        tmp=ListNode(0)
        tmp.next=head
        cur=tmp
        while cur.next:
            size+=1
            cur=cur.next
        #此時cur指向最後一個結點,這裡先和head接上,變成一個環
        cur.next=head
        #找到新的頭結點的前一個結點,摘鏈
        for i in range(size-k%size):
            cur=cur.next
        #此時cur指向新的頭結點的前一個結點
        new_head=cur.next
        #摘鏈
        cur.next=None
        return new_head

c++程式碼:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (!head || k==0)
            return head;
        ListNode* tmp=new ListNode(0);
        tmp->next=head;
        ListNode* cur=tmp;
        int size=0;
        while(cur->next)
        {
            size+=1;
            cur=cur->next;
        }
        cur->next=head;
        for(int i =0;i<size-k%size;i++)
        {
            cur=cur->next;
        }
        ListNode* new_head=cur->next;
        cur->next=NULL;
        return new_head;       
    }
};

總結: 事實上

while(k>n)
	k-=n;

可以直接用

k%=n

代替 注意考慮head為空和k為0的情況。 第二種解法才是經典解法。