面试算法题:乾坤大挪移(链表旋转K个位置)

题目:

给定一个单向链表,设计一个算法实现链表向右旋转K个位置。K是非负的整数。

举例:

给定:1->2->3->4->5->6->null 并且 K=3;

则有:4->5->6->1->2->3->null。


分析:

这道题看上去简单,但是能耐做到bug free还是需要仔细思考的。

思考一些细节:

1.当K=0,怎么办?

2.当K等于链表长度时,怎么办?

3.当K大于链表长度时,怎么办?

算法设计:

除了K=0,显然,我们需要知道尾指针。那么,第一步,扫描链表得到尾指针tail和链表的长度M。如果M=0,完毕。第二步,设置两个指针p和q,同时指向第一个结点,然后q先走M-(K%M)-1步,然后p和q指针一起走,直到q指到终点,这个时候:

1)p->next所指向的节点为链表的第一个结点,设置头指针head->next = p->next;

2)将p所指节点的next指针指向null;

3)将q所指的结点的next指针指向旧的头结点。


代码:

#include<iostream>
#include<stdio.h>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std; 

typedef int tData;

typedef struct LNode
{
    tData data;
    struct LNode *next;
}tLNode;

tLNode *head;

void add(tData data);

void create_list(tData *arr , int len)
{
    head = new tLNode();
    head->next = NULL;
    for(int i=0;i<len;i++)      
    {
        add(arr[i]);
    }
}

void add(tData data)
{
    tLNode *s = new tLNode();
    s->data = data;
    s->next = NULL;
    tLNode *p = head;
    while(p->next!=NULL)     
    {
        p = p->next;             
    }
    p->next = s;
}

void display()
{
    tLNode *p = head->next;
    while(p!=NULL)
    {
        cout<<"->"<<p->data;
        p = p->next;                    
    }
    cout<<endl;
}

void rotate_k(int k)
{
    if(k==0)   return ;
    
    tLNode *tail = head;
    int len = 0;
    while(tail->next!=NULL)    
    {
        tail = tail->next;
        len++;
    }
    cout<<"the len = "<<len<<endl;
    
    tLNode *p = head->next;
    tLNode *q = p;
    int step = len - k%len - 1;
    for(int i=0;i<step;i++)
    {
        q = q->next;        
    }
    
    head->next = q->next;
    q->next = NULL;
    tail->next = p;
    
}

int main()
{ 
    tData array[] = {1,2,3,4,5,6,7,8,9} ; // *array ?
    int len = sizeof(array)/sizeof(array[0]);
    create_list(array,len);
    
    cout<<"input the k : ";
    int k;
    cin>>k;
    
    display();
    rotate_k(k);
    display();
    system("pause");
    return 0;
}

结果:

K=0:


K=2:


K=3:


K=4:



再来看一个类似的题目:

对于有n个元素的数组int a[n]={....};写一个搞笑算法将数组内容循环左移m位。比如:char arr[] = "ABCDEFG",循环左移3位得到结果"DEFGABC"。

现在提供一个时间复杂度为O(n)的算法。

1)将arr[0]arr[1]...arr[m-1]所有元素逆置;

2)将arr[m]arr[m+1]..arr[strlen(arr)-1]所有元素逆置;

3)将arr整体逆置。


代码:

#include<iostream>

using namespace std;

typedef char tData; 

void rotate(tData *start , tData *end  )
{
    tData tmp; 
    while(start<end) 
    {
        tmp = *start;
        *start = *end;
        *end = tmp;
        start++;
        end--;                  
    }
}

int main()
{
     tData arr[] = "ABCDEFG";
     int k , len = strlen(arr);
     cout<<"please input the k : ";
     cin>>k; 
     k = k%len;
     rotate(arr,arr+k-1);
     rotate(arr+k,arr+len-1);
     rotate(arr,arr+len-1);
     
     cout<<arr<<endl;
     
     system("pause");
     return 0;
}


注明出处:http://blog.csdn.net/lavorange/article/details/19828095





你可能感兴趣的:(c,算法,面试,链表数组旋转)