看了很多热心人的推荐,觉得LeetCode应该也是个不错的练习算法的地方。
问题:
Given a list, rotate the list to the right by k places, where k is non-negative.
For example:
Given 1->2->3->4->5->NULL
and k = 2
,
return 4->5->1->2->3->NULL
.
看起来非常简单的问题,但是试了几次才Accepted,归结其耗时的原因是:
1 . 匆忙解答,思路不系统(尤其是对看起来简单的问题,最容易犯的毛病);
2. 没有系统分析特殊情况
LeetCode的Online Judge系统还是不错的,测试用例很全,所以,有一点东西没考虑到都会被rejected的。
下面是解答程序,应该都注释好了,看起来算清晰了吧:
#include<iostream>
using namespace std;
//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) {
//Special treatment
if(head==NULL)
return NULL;
//initialization variables
ListNode *cur = head;
ListNode *pre = head;
int i = 1, j = 1;
//1. Normal situation
for(; cur->next!=NULL; i++, cur=cur->next)
{
if((i-j)==k)
{
j++;
pre=pre->next;
}
}
//2. special situation1
if(i==k) return head;
//3. special situation2
if(k>i)
{
k%=i;
while ((i-j)!=k)
{
j++;
pre=pre->next;
}
}
//connect new link
cur->next = head;
head = pre->next;
pre->next = NULL;
return head;
}
};
int main()
try
{
{
ListNode head(11);
ListNode fir(1);
ListNode sec(2);
ListNode thi(3);
ListNode fou(4);
ListNode fiv(5);
ListNode six(6);
ListNode sev(7);
ListNode eig(8);
ListNode nin(9);
ListNode ten(10);
head.next = &fir;
fir.next = &sec;
sec.next = &thi;
thi.next = &fou;
fou.next = &fiv;
fiv.next = &six;
six.next = &sev;
sev.next = &eig;
eig.next = &nin;
nin.next = &ten;
ten.next = NULL;
ListNode *pn(NULL);
pn = &head;
for(; pn!=NULL; )
{
cout<<pn->val<<" ";
pn=pn->next;
}
cout<<endl;
Solution solu;
pn = solu.rotateRight(&head, 100);
//pn = &head;
for(; pn!=NULL; )
{
cout<<pn->val<<" ";
pn=pn->next;
}
cout<<endl;
return 0;
}
}
catch(out_of_range)
{
cerr<<"range error\n";
}
catch(...)
{
cerr<<"unknow exception thrown\n";
}
看来算法的提高真是任重而道远!
//2014-1-30 update
ListNode *rotateRight(ListNode *head, int k)
{
if (!head || !head->next) return head;
ListNode dummy(-1);
dummy.next = head;
ListNode *pre = &dummy;
int n = getListLength(head);
k %= n;
for (k--; k && head->next; k--) head = head->next;
while (head->next)
{
head = head->next;
pre = pre->next;
}
ListNode *h = pre->next;
pre->next = nullptr;
head->next = dummy.next;
return h;
}
int getListLength(ListNode *h)
{
int len = 0;
for ( ; h; h = h->next) len++;
return len;
}