[蓝蓝计算机考研算法训练二期]-day25

113 阅读2分钟

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;
}

image.png

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;
}

小结

本次算法在创建的时候要注意不要断链,其他的思路与前几次的相似。