37、递增的单链表去点表中重复的元素,只保留一个数值。
思路
运用了以往算法所使用的数据处理方法,将输入的数据放入链表中,然后对链表进行遍历,当本节点和下一个节点的val值相同时,释放下一个节点依次类推。
具体实现
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
#define MAX_LEN 10000
// 链表结构体
struct ListNode {
int val;
struct ListNode* next;
};
// 删除链表中指定值的节点,返回链表头指针
struct ListNode* deleteNode(struct ListNode* head) {
struct ListNode* curr = head;
while (curr->next != NULL) {
if( curr->val == curr->next->val) {
struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
temp = curr->next;
curr->next = temp->next;
free(temp);
}
else
curr = curr->next;
}
return head;
}
// 创建链表的函数
struct ListNode* createList() {
char str[MAX_LEN];
int num[MAX_LEN];
int i,j=0;
// 将输入的内容按照字符串读入
scanf("%s", str);
// 读取字符串中不含‘{’‘}’的内容
for (i = 0; str[i] != '}'; i++) {
if (str[i] != '{') {
str[j++] = str[i];
}
}
str[j] = '\0'; // 确保新字符串以 '\0' 结尾
// 分割字符串并转换为数字
i=0;
char *token = strtok(str, ",");
while (token != NULL) {
num[i++] = atoi(token);
token = strtok(NULL, ",");
}
// 输出数组测试
// for(j=0;j<i;j++) {
// printf("%d", num[j]);
// }
struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
head->val = num[0];
head->next = NULL;
struct ListNode* p = head;
for (j = 1; j < i; j++) {
struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));
node->val = num[j];
node->next = NULL;
p->next = node;
p = p->next;
}
return head;
}
// 打印链表的函数
void printList(struct ListNode* head) {
struct ListNode* current = head;
printf("{");
while (current != NULL) {
printf("%d", current->val);
current = current->next;
if(current != NULL)
printf(",");
}
printf("}");
printf("\n");
}
int main() {
struct ListNode* list = createList();
deleteNode(list);
printList(list);
return 0;
}
38、判断带头结点的循环双链表是否对称。
思路
具体实现
#include <iostream>
using namespace std;
// 定义循环双链表结点类型
typedef struct DNode {
int data;
DNode *prev, *next;
DNode(int val) : data(val), prev(nullptr), next(nullptr){};
} DNode, *DLinkList;
// 判断循环双链表是否对称
bool isSymmetric(DLinkList L) {
// 空链表和只有一个结点的链表都是对称的
if (L == NULL || L->next == L) {
return true;
}
// 定义两个指针,分别指向首尾结点
DNode *p = L->next;
DNode *q = L->prev;
// 依次比较首尾结点、次首次尾结点、次次首次次尾结点,以此类推
while (p != q && p->prev != q) {
if (p->data != q->data) {
return false;
}
p = p->next;
q = q->prev;
}
return true;
}
int main() {
// 创建循环双链表
DNode *L = new DNode(-1); // 虚拟头节点,不存储实际的数据
DNode *n1 = new DNode(1);
DNode *n2 = new DNode(2);
DNode *n3 = new DNode(2);
DNode *n4 = new DNode(1);
L->next = n1;
n1->prev = L;
n1->next = n2;
n2->prev = n1;
n2->next = n3;
n3->prev = n2;
n3->next = n4;
n4->prev = n3;
n4->next = L;
L->prev = n4;
// 判断链表是否对称
if (isSymmetric(L)) {
cout << "这个是对称的" << endl;
} else {
cout << "这个不是对称的" << endl;
}
return 0;
}
小结
本次算法在创建的时候要注意不要断链,其他的思路与前几次的相似。