写在前边的话:我粘贴的代码都是可以直接运行的,但是请不要纠结异常输入。
单链表节点结构如下:
typedef struct node{
int data;
struct node * next;
}Node;
2020-889-北京理工大学
【2020-889-北京理工大学】一个有头结点的单链表L,在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第K(K为正整数)个节点。若查找成功,输出该节点的data值,并return 1,否则 return 0
剑指 Offer 22. 链表中倒数第k个节点 - 力扣(LeetCode)
思路过程 |
---|
思路一:双指针,p和q,首先让p先移动K个位置,此时,p和q之间的距离就位K了。然后让两个指针一起向后移动,当p移动到链表尾时,q指向的元素就是倒数第K个。 |
思路二:先遍历链表,求得链表长length,然后就可以计算倒数第K个是正数第length-K+1 个。再遍历一次链表,找到第length-K+1 个节点。 |
// 复制到leetcode中可直接提交
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
struct ListNode *p = head;
int i;
for(i=0; i<k && p; i++){
// 题中给出,保证k有效,因此无需判断链表够长不,即p一定能向后走k步
p = p->next;
}
if (i != k){
return NULL;
}
struct ListNode *q = head;
while(p){
p = p->next;
q = q->next;
}
return q;
}
};
2019-408
【2019-408】设线性表 L = ( a 1 , a 2 , ⋯ , a n − 2 , a n − 1 , a n ) L=(a_1, a_2, \cdots, a_{n-2}, a_{n-1},a_n) L=(a1,a2,⋯,an−2,an−1,an)采用带头结点的单链表保存,链表中的节点定义如下:
typedef struct node{ int data; struct node * next; }Node;
请设计一个空间复杂度为 O ( 1 ) O(1) O(1)且时间上尽可能高效的算法,重新排列L中的各结点,得到线性表 L ′ = ( a 1 , a n , a 2 , a n − 1 , a 3 , a n − 2 , ⋯ ) L^{\prime}=\left(a_{1}, a_{n}, a_{2}, a_{n-1}, a_{3}, a_{n-2}, \cdots\right) L′=(a1,an,a2,an−1,a3,an−2,⋯)要求:
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
(3)说明你所设计的算法的时间复杂度。
思路过程 |
---|
视频:后期贴链接 |
算法思想:
- 先将链表L对半分为前半段L和后半段L2
- 将L2逆置
- 将L2的每个节点,每隔一个插入到L中
- 最终得到完整的 L ′ L' L′
时间复杂度: O ( n ) O(n) O(n)
#include<iostream>
#include<malloc.h>
using namespace std;
//节点
typedef struct Node{
int val;
struct Node *next;
}Node;
void createLinkListFromEnd(int a[], int n, Node *L){
Node *q = L;
for(int i=0; i<n; i++){
Node *p = new Node();
p->next = NULL;
p->val = a[i];
q->next = p;
q = p;
}
}
//逆置链表
void reverse(Node *L){
Node *L2 = L->next;
L->next = NULL;
while(L2){
Node *p = L2;
L2 = L2->next;
p->next = L->next;
L->next = p;
}
}
//统计链表长
int len(Node *L){
Node *p = L->next;
int n = 0;
while(p){
n++;
p = p->next;
}
return n;
}
//对半分
void split(Node *L, Node *L2, int k){
Node *p = L;
while(k--){
p = p->next;
}
L2->next = p->next;
p->next = NULL;
}
//将两个链表合并
void merge(Node *L, Node *L2){
Node *p = L->next;
Node *q = L2->next;
while(1){
L2->next = q->next;
q->next = p->next;
p->next = q;
q = L2->next;
p = p->next;
if(p->next){
p = p->next;
}else{
break;
}
}
p->next = q;
}
//输出单链表
void show(Node *L){
Node *p = L->next;
while(p){
cout<<p->val<<" ";
p = p->next;
}
cout<<endl;
}
int main(){
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
Node *L = new Node();
L->next = NULL;
createLinkListFromEnd(a, 9, L);
int length = len(L);
Node *L2 = new Node();
split(L, L2, length/2);
reverse(L2);
merge(L, L2);
show(L);
}
【2015-824-南京理工大学】对称串(symmetric)是一个具有偶数个字符的字符串,对于长度为N的这种字符串,如果k在1到N/2之间,那么有第k个字符和第(N+1-k)字符相同。例如,字符串abcddcba就是一个回文串,而abcdefgh则不是。假设有一个单链表构成的字符串(即每个字符都在一个节点上),请用程序设计语言程序写一个用于判断该链表是否是一个对称串的程序,且不能破坏该链表的原始状态。你的程序的函数名是IsSymmetric 。如果该链表是一个回文串,则返回1,否则返回0。这个函数的复杂度应该是一个0(N)的复杂度。