1、超级楼梯(典型斐波那契数列)
Problem Description
有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?
Input
输入数据首先包含一个整数N,表示测试实例的个数,然后是N行数据,每行包含一个整数M(1<=M<=40),表示楼梯的级数。
Output
对于每个测试实例,请输出不同走法的数量
Sample Input
2 2 3
Sample Output
1 2
#include <stdio.h>
#include <stdlib.h>
#define eleType int
typedef struct ListNode{
eleType data;
struct ListNode *next;
}ListNode;
typedef struct LinkList{
struct ListNode *head;
size_t size;
}LinkList;
//初始化链表
void LinkListInit(LinkList *list){
list->head=NULL;
list->size=0;
}
//删除链表
void LinkListDelete(LinkList *list){
while(list->head){
ListNode *temp=list->head;
list->head=list->head->next;
free(temp);
}
list->size=0;
}
//插入
void LinkListInsert(LinkList *list,int index,eleType value){
if(index<0||index>list->size){
printf("Invalid Index");
return ;
}
ListNode *NewNode=(ListNode*)malloc(sizeof(eleType));
NewNode->data=value;
if(index==0){
NewNode->next=list->head;
list->head=NewNode;
}
else{
ListNode *couret=list->head;
for(int i=0;i<index-1;++i){
couret=couret->next;
}
NewNode->next=couret->next;
couret->next=NewNode;
}
list->size++;
}
//删除某个元素
void LinkListRemov(LinkList *list,int index){
if(index<0||index>=list->size){
printf("Invalid Index");
return ;
}
if(index==0){
ListNode *couret=list->head;
couret->next=list->head->next;
free(list->head);
list->head=couret;
}
else{
ListNode *couret=list->head;
for(int i=0;i<index-1;++i){
couret=couret->next;
}
ListNode *next=couret->next->next;
free(couret->next);
couret->next=next;
}
list->size--;
}
//查找
ListNode *LinkListFind(LinkList *list,eleType value){
ListNode *couret=list->head;
while(couret){
if(couret->data==value){
return couret;
}
couret=couret->next;
}
return NULL;
}
//索引
ListNode *LinkListGet(LinkList *list,int index){
if(index<0||index>=list->size){
printf("Invalid Index");
return NULL;
}
ListNode *couret=list->head;
for(int i=0;i<index;++i){
couret=couret->next;
}
return couret;
}
void LinkListUpdata(LinkList *list,int index,eleType value){
ListNode *nod=LinkListGet(list,index);
if(nod){
nod->data=value;
}
}
void LinkListPrintf(LinkList *list){
ListNode *couret=list->head;
while(couret){
printf("%d ->",couret->data);
couret=couret->next;
}
printf("NULL\n");
}
/*
斐波那契数列
0 1 1 2 3 5 8 13....
i ->data=(i-1)->data + (i-2)->data
*/
int main(){
LinkList list;
LinkListInit(&list);
LinkListInsert(&list,0,0);
LinkListInsert(&list,1,1);
for(int i=2;i<40;++i){
int i_1=LinkListGet(&list,i-1)->data;
int i_2=LinkListGet(&list,i-2)->data;
LinkListInsert(&list,i,i_1+i_2);
}
int n;
scanf("%d",&n);
while(n--){
int m;
scanf("%d",&m);
printf("%d\n",LinkListGet(&list,m)->data);
}
LinkListDelete(&list);
return 0;
}
2、数列有序
需要稍加修改一下输出函数
Problem Description
有n(n<=100)个整数,已经按照从小到大顺序排列好,现在另外给一个整数x,请将该数插入到序列中,并使新的序列仍然有序。
Input
输入数据包含多个测试实例,每组数据由两行组成,第一行是n和m,第二行是已经有序的n个数的数列。n和m同时为0标示输入数据的结束,本行不做处理。
Output
对于每个测试实例,输出插入新的元素后的数列。
Sample Input
3 3 1 2 4 0 0
Sample Output
1 2 3 4
void LinkListPrintf(LinkList *list){
ListNode *couret=list->head;
while(couret){
printf("%d ",couret->data);
couret=couret->next;
}
printf("\n");
}
int main(){
int n,m;
while(scanf("%d %d",&n,&m)!=EOF && n!=0 && m!=0){
LinkList list;
LinkListInit(&list);
int x;
for(int i=0;i<n;++i){
scanf("%d",&x);
LinkListInsert(&list,i,x);
}
ListNode *node=list.head;
int pos=0;
for(int i=0;i<n;++i){
if(node->data>m){
break;
}
node=node->next;
pos++;
}
LinkListInsert(&list,pos,m);
LinkListPrintf(&list);
LinkListDelete(&list);
}
return 0;
}
3、二进制链表转整数
(在链表中存储二进制的方法是从低地址开始存储的就是 0 --> i-1 个位置,而二进制是从右往左是逐渐增大的,比如 链表 0-->i-1 [10110] ,二进制 n<--1[ 01101])
给你一个单链表的引用结点 head
。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。
请你返回该链表所表示数字的 十进制值 。
示例 1:
输入:head = [1,0,1] 输出:5 解释:二进制数 (101) 转化为十进制数 (5)
示例 2:
输入:head = [0] 输出:0
示例 3:
输入:head = [1] 输出:1
示例 4:
输入:head = [1,0,0,1,0,0,1,1,1,0,0,0,0,0,0] 输出:18880
示例 5:
输入:head = [0,0] 输出:0
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
int getDecimalValue(struct ListNode* head) {
int sum=0;
while(head){
sum=sum*2+head->val;
head=head->next;
}
return sum;
}
4、返回倒数第K个节点 (快慢指针的应用)
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。
示例:
输入: 1->2->3->4->5 和 k = 2 输出: 4
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
int kthToLast(struct ListNode* head, int k){
struct ListNode *fast =head;
while(k--){
fast=fast->next;
}
struct ListNode *slow =head;
while(fast){
fast=fast->next;
slow=slow->next;
}
return slow->val;
}
5、训练计划
给定一个头节点为 head
的链表用于记录一系列核心肌群训练项目编号,请查找并返回倒数第 cnt
个训练项目编号。
示例 1:
输入:head = [2,4,7,8], cnt = 1 输出:8
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* trainingPlan(struct ListNode* head, int cnt) {
struct ListNode *fast=head;
while(cnt--){
fast=fast->next;
}
struct ListNode *slow=head;
while(fast){
fast=fast->next;
slow=slow->next;
}
return slow;
}
6、删除中间节点
若链表中的某个节点,既不是链表头节点,也不是链表尾节点,则称其为该链表的「中间节点」。
假定已知链表的某一个中间节点,请实现一种算法,将该节点从链表中删除。
例如,传入节点 c
(位于单向链表 a->b->c->d->e->f
中),将其删除后,剩余链表为 a->b->d->e->f
示例:
输入:节点 5 (位于单向链表 4->5->1->9 中) 输出:不返回任何数据,从链表中删除传入的节点 5,使链表变为 4->1->9
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
void deleteNode(struct ListNode* node) {
struct ListNode *fast=node->next;
if(fast){
node->val=fast->val;
node->next=fast->next;
free(fast);
}
}
7、移除链表中的元素
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1 输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7 输出:[]
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val) {
struct ListNode *temp;
while(head && head->val == val){
temp=head;
head=head->next;
free(temp);
}
struct ListNode *crut=head;
while(crut && (temp=crut->next)){
if(temp->val==val){
crut->next=crut->next->next;
free(temp);
}else{
crut=crut->next;
}
}
return head;
}
8、删除链表中的节点
有一个单链表的 head
,我们想删除它其中的一个节点 node
。
给你一个需要删除的节点 node
。你将 无法访问 第一个节点 head
。
链表的所有值都是 唯一的,并且保证给定的节点 node
不是链表中的最后一个节点。
删除给定的节点。注意,删除节点并不是指从内存中删除它。这里的意思是:
- 给定节点的值不应该存在于链表中。
- 链表中的节点数应该减少 1。
node
前面的所有值顺序相同。node
后面的所有值顺序相同。
自定义测试:
- 对于输入,你应该提供整个链表
head
和要给出的节点node
。node
不应该是链表的最后一个节点,而应该是链表中的一个实际节点。 - 我们将构建链表,并将节点传递给你的函数。
- 输出将是调用你函数后的整个链表。
示例 1:
输入:head = [4,5,1,9], node = 5 输出:[4,1,9] 解释:指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9
示例 2:
输入:head = [4,5,1,9], node = 1 输出:[4,5,9] 解释:指定链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
void deleteNode(struct ListNode* node) {
node->val=node->next->val;
node->next=node->next->next;
}
9、删除排序链表中重复的元素
给定一个已排序的链表的头 head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
示例 1:
输入:head = [1,1,2] 输出:[1,2]
示例 2:
输入:head = [1,1,2,3,3] 输出:[1,2,3]
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* deleteDuplicates(struct ListNode* head) {
if(!head){
return head;
}
struct ListNode *temp;
struct ListNode *crut=head;
while(crut && (temp=crut->next)){
if(crut->val==temp->val){
// crut->val=crut->next->val;
crut->next=crut->next->next;
free(temp);
}else{
crut=crut->next;
}
}
return head;
}