笔试算法题(13):反转链表 & 左旋转字符串
出题:反转链表(递归和非递归解法);
分析:有递归跟非递归实现,注意对原始链表头节点的处理,因为其他节点都指向下一个节点,其需要指向NULL;
解题:
1 struct Node { 2 int v; 3 Node *next; 4 }; 5 Node* NonRecursiveListReverse(Node *head) { 6 if(head == NULL) return NULL; 7 Node *previous=NULL, *current=head, *temp=NULL; 8 /** 9 * 一定需要注意删除原来的结构,不然最后一个指针与倒数第二个指针 10 * 相互索引,最终导致无限循环索引 11 * */ 12 //previous->next=NULL; 13 14 while(current != NULL) { 15 temp=current->next; 16 current->next=previous; 17 18 previous=current; 19 current=temp; 20 } 21 22 return previous; 23 } 24 /** 25 * 调用此方法的时候需要将previous设置成NULL,也就是 26 * RecursiveListReverse(NULL, head); 27 * */ 28 Node* RecursiveListReverse(Node *previous, Node *current) { 29 Node *temp=current->next; 30 current->next=previous; 31 if(temp == NULL) return current; 32 else return RecursiveListReverse(current, temp); 33 }
出题:左旋转字符串算法,将字符串最左边的k个字符移动到字符串尾部,局部字符相对顺序不变。要求时间复杂度为O(N),空间复杂度为O(1);
分析:例如:对"abcdef"施用k=3的左旋转之后变成"cdefabc"。本题与19类似,首先进行全局反转,然后利用k的长度分别对两个部分进行反转;
解题:
1 /** 2 * 借用之前已经实现的全局翻转函数reverse 3 * */ 4 void reverse(char* target, int length) { 5 char temp; 6 int i; 7 for(i=0;i<length/2;i++) { 8 temp=*(target+i); 9 *(target+i)=*(target+(length-i-1)); 10 *(target+(length-i-1))=temp; 11 } 12 } 13 14 void LeftRotate(char *target, int length, int k) { 15 reverse(target,length); 16 reverse(target, length-k); 17 reverse(target+length-k, k); 18 } 19 int main() { 20 char target[]="abcdef"; 21 LeftRotate(target, 6, 3); 22 char *temp=target; 23 printf("\n%s\n", temp); 24 return 0; 25 }